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

    module Data.Random.Distribution.Triangular where

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

    -- |A description of a triangular distribution - a distribution whose PDF
    -- is a triangle ramping up from a lower bound to a specified midpoint
    -- and back down to the upper bound.  This is a very simple distribution
    -- that does not generally occur naturally but is used sometimes as an
    -- estimate of a true distribution when only the range of the values and
    -- an approximate mode of the true distribution are known.
    data Triangular a = Triangular {
        -- |The lower bound of the triangle in the PDF (the smallest number the distribution can generate)
        forall a. Triangular a -> a
    triLower  :: a,
        -- |The midpoint of the triangle (also the mode of the distribution)
        forall a. Triangular a -> a
    triMid    :: a,
        -- |The upper bound of the triangle (and the largest number the distribution can generate)
        forall a. Triangular a -> a
    triUpper  :: a}
        deriving (Triangular a -> Triangular a -> Bool
    (Triangular a -> Triangular a -> Bool)
    -> (Triangular a -> Triangular a -> Bool) -> Eq (Triangular a)
    forall a. Eq a => Triangular a -> Triangular a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall a. Eq a => Triangular a -> Triangular a -> Bool
    == :: Triangular a -> Triangular a -> Bool
    $c/= :: forall a. Eq a => Triangular a -> Triangular a -> Bool
    /= :: Triangular a -> Triangular a -> Bool
    Eq, Int -> Triangular a -> ShowS
    [Triangular a] -> ShowS
    Triangular a -> String
    (Int -> Triangular a -> ShowS)
    -> (Triangular a -> String)
    -> ([Triangular a] -> ShowS)
    -> Show (Triangular a)
    forall a. Show a => Int -> Triangular a -> ShowS
    forall a. Show a => [Triangular a] -> ShowS
    forall a. Show a => Triangular a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> Triangular a -> ShowS
    showsPrec :: Int -> Triangular a -> ShowS
    $cshow :: forall a. Show a => Triangular a -> String
    show :: Triangular a -> String
    $cshowList :: forall a. Show a => [Triangular a] -> ShowS
    showList :: [Triangular a] -> ShowS
    Show)

    -- |Compute a triangular distribution for a 'Floating' type.
    floatingTriangular :: (Floating a, Ord a, Distribution StdUniform a) => a -> a -> a -> RVarT m a
    floatingTriangular :: forall a (m :: * -> *).
    (Floating a, Ord a, Distribution StdUniform a) =>
    a -> a -> a -> RVarT m a
    floatingTriangular a
    a a
    b a
    c
        | a
    a a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    > a
    b     = a -> a -> a -> RVarT m a
    forall a (m :: * -> *).
    (Floating a, Ord a, Distribution StdUniform a) =>
    a -> a -> a -> RVarT m a
    floatingTriangular a
    b a
    a a
    c
        | a
    b a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    > a
    c     = a -> a -> a -> RVarT m a
    forall a (m :: * -> *).
    (Floating a, Ord a, Distribution StdUniform a) =>
    a -> a -> a -> RVarT m a
    floatingTriangular a
    a a
    c a
    b
        | Bool
    otherwise = do
            let p :: a
    p = (a
    ca -> a -> a
    forall a. Num a => a -> a -> a
    -a
    b)a -> a -> a
    forall a. Fractional a => a -> a -> a
    /(a
    ca -> a -> a
    forall a. Num a => a -> a -> a
    -a
    a)
            u <- RVarT m a
    forall a (m :: * -> *). Distribution StdUniform a => RVarT m a
    stdUniformT
            let d   | a
    u a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    >= a
    p    = a
    a
                    | Bool
    otherwise = a
    c
                x   | a
    u a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    >= a
    p    = (a
    u a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    p) a -> a -> a
    forall a. Fractional a => a -> a -> a
    / (a
    1 a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    p)
                    | Bool
    otherwise = a
    u a -> a -> a
    forall a. Fractional a => a -> a -> a
    / a
    p
    -- may prefer this: reusing u costs resolution, especially if p or 1-p is small and c-a is large.
    --        x <- stdUniform
            return (b - ((1 - sqrt x) * (b-d)))

    -- |@triangularCDF a b c@ is the CDF of @realFloatTriangular a b c@.
    triangularCDF :: RealFrac a => a -> a -> a -> a -> Double
    triangularCDF :: forall a. RealFrac a => a -> a -> a -> a -> Double
    triangularCDF a
    a a
    b a
    c a
    x
        | a
    x a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < a
    a
        = Double
    0
        | a
    x a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    b
        = a -> Double
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac ((a
    x a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    a)a -> Int -> a
    forall a b. (Num a, Integral b) => a -> b -> a
    ^(Int
    2 :: Int) a -> a -> a
    forall a. Fractional a => a -> a -> a
    / ((a
    c a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    a) a -> a -> a
    forall a. Num a => a -> a -> a
    * (a
    b a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    a)))
        | a
    x a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    c
        = a -> Double
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac (a
    1 a -> a -> a
    forall a. Num a => a -> a -> a
    - (a
    c a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    x)a -> Int -> a
    forall a b. (Num a, Integral b) => a -> b -> a
    ^(Int
    2 :: Int) a -> a -> a
    forall a. Fractional a => a -> a -> a
    / ((a
    c a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    a) a -> a -> a
    forall a. Num a => a -> a -> a
    * (a
    c a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    b)))
        | Bool
    otherwise
        = Double
    1

    instance (RealFloat a, Ord a, Distribution StdUniform a) => Distribution Triangular a where
        rvarT :: forall (n :: * -> *). Triangular a -> RVarT n a
    rvarT (Triangular a
    a a
    b a
    c) = a -> a -> a -> RVarT n a
    forall a (m :: * -> *).
    (Floating a, Ord a, Distribution StdUniform a) =>
    a -> a -> a -> RVarT m a
    floatingTriangular a
    a a
    b a
    c
    instance (RealFrac a, Distribution Triangular a) => CDF Triangular a where
        cdf :: Triangular a -> a -> Double
    cdf  (Triangular a
    a a
    b a
    c) = a -> a -> a -> a -> Double
    forall a. RealFrac a => a -> a -> a -> a -> Double
    triangularCDF a
    a a
    b a
    c