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

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

module Data.Random.Distribution.Rayleigh where

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

floatingRayleigh :: (Floating a, Eq a, Distribution StdUniform a) => a -> RVarT m a
floatingRayleigh :: a -> RVarT m a
floatingRayleigh a
s = do
    a
u <- RVarT m a
forall a (m :: * -> *).
(Distribution StdUniform a, Num a, Eq a) =>
RVarT m a
stdUniformPosT
    a -> RVarT m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
s a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sqrt (-a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
log a
u))

-- |The rayleigh distribution with a specified mode (\"sigma\") parameter.
-- Its mean will be @sigma*sqrt(pi/2)@ and its variance will be @sigma^2*(4-pi)/2@
--
-- (therefore if you want one with a particular mean @m@, @sigma@ should be @m*sqrt(2/pi)@)
newtype Rayleigh a = Rayleigh a

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

rayleighT :: Distribution Rayleigh a => a -> RVarT m a
rayleighT :: a -> RVarT m a
rayleighT = Rayleigh a -> RVarT m a
forall (d :: * -> *) t (n :: * -> *).
Distribution d t =>
d t -> RVarT n t
rvarT (Rayleigh a -> RVarT m a) -> (a -> Rayleigh a) -> a -> RVarT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Rayleigh a
forall a. a -> Rayleigh a
Rayleigh

rayleighCDF :: Real a => a -> a -> Double
rayleighCDF :: a -> a -> Double
rayleighCDF a
s a
x = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
exp ((-Double
0.5)Double -> Double -> Double
forall a. Num a => a -> a -> a
* a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (a
xa -> a -> a
forall a. Num a => a -> a -> a
*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
sa -> a -> a
forall a. Num a => a -> a -> a
*a
s))

instance (RealFloat a, Distribution StdUniform a) => Distribution Rayleigh a where
    rvarT :: Rayleigh a -> RVarT n a
rvarT (Rayleigh a
s) = a -> RVarT n a
forall a (m :: * -> *).
(Floating a, Eq a, Distribution StdUniform a) =>
a -> RVarT m a
floatingRayleigh a
s

instance (Real a, Distribution Rayleigh a) => CDF Rayleigh a where
    cdf :: Rayleigh a -> a -> Double
cdf  (Rayleigh a
s) a
x = a -> a -> Double
forall a. Real a => a -> a -> Double
rayleighCDF a
s a
x