module Numeric.GSL.Distribution.Discrete (
OneParamDist(..)
, TwoParamDist(..), ThreeParamDist(..)
, MultiParamDist(..)
, DistFunc(..)
, random_1p, random_1p_v, density_1p
, random_2p, random_2p_v, density_2p
, random_3p, random_3p_v, density_3p
, random_mp, density_mp
) where
import Data.Packed.Vector
import Data.Packed.Development
import Foreign hiding(shift)
import Foreign.C.Types(CInt(..),CUInt(..))
import Numeric.GSL.Distribution.Common
import System.IO.Unsafe(unsafePerformIO)
data OneParamDist = Poisson
| Bernoulli
| Geometric
| Logarithmic
deriving Enum
data TwoParamDist = Binomial
| NegBinomial
| Pascal
deriving Enum
data ThreeParamDist = HyperGeometric
deriving Enum
data MultiParamDist = Multinomial
deriving Enum
fromei x = fromIntegral (fromEnum x) :: CInt
random_1p :: OneParamDist
-> Int
-> Double
-> Int
random_1p d s p = unsafePerformIO $
alloca $ \r -> do
check "random1p" $ distribution_discrete_one_param (fromIntegral s) (fromei d) p r
r' <- peek r
return $ fromIntegral r'
random_1p_v :: OneParamDist
-> Int
-> Double
-> Int
-> Vector Int
random_1p_v d s p l = unsafePerformIO $ do
r <- createVector l
app1 (distribution_discrete_one_param_v (fromIntegral s) (fromei d) p) vec r "random_1p_v"
return (mapVector fromIntegral r)
density_1p :: OneParamDist
-> DistFunc
-> Double
-> Int
-> Double
density_1p d f p x = unsafePerformIO $ do
case d of
Poisson -> no_inverse f d p x
Geometric -> no_inverse f d p x
Logarithmic -> pdf_only f d p x
Bernoulli -> pdf_only f d p x
_ -> distribution_dist_one_param (fromei f) (fromei d) (fromIntegral x) p
where pdf_only f' d' p' x' = if f' /= Density
then error "no CDF"
else distribution_dist_one_param (fromei f') (fromei d') (fromIntegral x') p'
no_inverse f' d' p' x' = if (f' == LowInv || f' == UppInv)
then error "No inverse CDF"
else distribution_dist_one_param (fromei f') (fromei d') (fromIntegral x') p'
foreign import ccall "distribution-aux.h discrete1" distribution_discrete_one_param :: CInt -> CInt -> Double -> Ptr CUInt -> IO CInt
foreign import ccall "distribution-aux.h discrete1_v" distribution_discrete_one_param_v :: CInt -> CInt -> Double -> CInt -> Ptr CUInt -> IO CInt
foreign import ccall "distribution-aux.h discrete1_dist" distribution_dist_one_param :: CInt -> CInt -> CUInt -> Double -> IO Double
random_2p :: TwoParamDist
-> Int
-> Double
-> Int
-> Int
random_2p d s p1 p2 = unsafePerformIO $
alloca $ \r -> do
check "random2p" $ distribution_discrete_two_param (fromIntegral s) (fromei d) p1 (fromIntegral p2) r
r' <- peek r
return $ fromIntegral r'
random_2p_v :: TwoParamDist
-> Int
-> Double
-> Int
-> Int
-> Vector Int
random_2p_v d s p1 p2 l = unsafePerformIO $ do
r <- createVector l
app1 (distribution_discrete_two_param_v (fromIntegral s) (fromei d) p1 (fromIntegral p2)) vec r "random_2p_v"
return (mapVector fromIntegral r)
density_2p :: TwoParamDist
-> DistFunc
-> Double
-> Int
-> Int
-> Double
density_2p d f p1 p2 x = unsafePerformIO $ do
case d of
_ -> no_inverse f d p1 p2 x
where no_inverse f' d' p1' p2' x' = if (f' == LowInv || f' == UppInv)
then error "distribution has no inverse CDF"
else distribution_dist_two_param (fromei f') (fromei d') (fromIntegral x') p1' (fromIntegral p2')
foreign import ccall "distribution-aux.h discrete2" distribution_discrete_two_param :: CInt -> CInt -> Double -> CUInt -> Ptr CUInt -> IO CInt
foreign import ccall "distribution-aux.h discrete2_v" distribution_discrete_two_param_v :: CInt -> CInt -> Double -> CUInt -> CInt -> Ptr CUInt -> IO CInt
foreign import ccall "distribution-aux.h discrete2_dist" distribution_dist_two_param :: CInt -> CInt -> CUInt -> Double -> CUInt -> IO Double
random_3p :: ThreeParamDist
-> Int
-> Int
-> Int
-> Int
-> Int
random_3p d s p1 p2 p3 = unsafePerformIO $
alloca $ \r -> do
check "random_3p" $ distribution_discrete_three_param (fromIntegral s) (fromei d) (fromIntegral p1) (fromIntegral p2) (fromIntegral p3) r
r' <- peek r
return $ fromIntegral r'
random_3p_v :: ThreeParamDist
-> Int
-> Int
-> Int
-> Int
-> Int
-> Vector Int
random_3p_v d s p1 p2 p3 l = unsafePerformIO $ do
r <- createVector l
app1 (distribution_discrete_three_param_v (fromIntegral s) (fromei d) (fromIntegral p1) (fromIntegral p2) (fromIntegral p3)) vec r "random_3p_v"
return (mapVector fromIntegral r)
density_3p :: ThreeParamDist
-> DistFunc
-> Int
-> Int
-> Int
-> Int
-> Double
density_3p d f p1 p2 p3 x = unsafePerformIO $ do
case d of
HyperGeometric -> no_inverse f d p1 p2 p3 x
where no_inverse f' d' p1' p2' p3' x' = if (f' == LowInv || f' == UppInv)
then error "No inverse CDF"
else distribution_dist_three_param (fromei f') (fromei d') (fromIntegral x') (fromIntegral p1') (fromIntegral p2') (fromIntegral p3')
foreign import ccall "distribution-aux.h discrete3" distribution_discrete_three_param :: CInt -> CInt -> CUInt -> CUInt -> CUInt -> Ptr CUInt -> IO CInt
foreign import ccall "distribution-aux.h discrete3_v" distribution_discrete_three_param_v :: CInt -> CInt -> CUInt -> CUInt -> CUInt -> CInt -> Ptr CUInt -> IO CInt
foreign import ccall "distribution-aux.h discrete3_dist" distribution_dist_three_param :: CInt -> CInt -> CUInt -> CUInt -> CUInt -> CUInt -> IO Double
random_mp :: MultiParamDist
-> Int
-> Int
-> Vector Double
-> Vector Int
random_mp d s t p = unsafePerformIO $ do
r <- createVector $ dim p
app2 (distribution_discrete_multi_param (fromIntegral s) (fromei d) (fromIntegral t)) vec p vec r "random_mp"
return $ mapVector (\x -> (fromIntegral x) :: Int) r
density_mp :: MultiParamDist
-> DistFunc
-> Vector Double
-> Vector Int
-> Double
density_mp d f p q = unsafePerformIO $ do
case d of
Multinomial -> density_only f d p q
where density_only f' d' p' q' = if f' /= Density
then error "distribution has no CDF"
else alloca $ \r -> do
app2 (distribution_dist_multi_param (fromei f') (fromei d') r) vec p' vec (mapVector (\x -> (fromIntegral x) :: CUInt) q') "density_mp"
r' <- peek r
return r'
foreign import ccall "distribution-aux.h discrete_mp" distribution_discrete_multi_param :: CInt -> CInt -> CUInt -> CInt -> Ptr Double -> CInt -> Ptr CUInt -> IO CInt
foreign import ccall "distribution-aux.h discrete_mp_dist" distribution_dist_multi_param :: CInt -> CInt -> Ptr Double -> CInt -> Ptr Double -> CInt -> Ptr CUInt -> IO CInt