module Stochastic.Distributions(
UniformBase(rDouble)
,stdBase
,seededBase
,Empirical(..)
,mkEmpirical
) where
import Stochastic.Uniform
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy as LBS
import System.Random
import Control.Monad.State.Lazy
import Stochastic.Tools
import System.IO
import Data.Word
import Data.Binary.Get
data UniformBase = UniformBase {
rDouble :: (Double, UniformBase)
}
readWord64 :: Handle -> IO Word64
readWord64 h = do
w1 <- hGetChar h
w2 <- hGetChar h
w3 <- hGetChar h
w4 <- hGetChar h
w5 <- hGetChar h
w6 <- hGetChar h
w7 <- hGetChar h
w8 <- hGetChar h
let words = [w1,w2,w3,w4,w5,w6,w7,w8] :: String
return $ runGet getWord64host $ LBS.fromStrict $ B.pack words
stdBase :: Integer -> UniformRandom
stdBase s = xorshift128plus s
seededBase :: IO UniformRandom
seededBase = do
word <- withBinaryFile "/dev/random/" ReadMode (readWord64)
let seed = toInteger word
return $ stdBase seed
data Empirical = Empirical {
degreesOfFreedom :: Int,
cdf :: Double -> Double,
cdf' :: Double -> Double
}
empiricalCDF' hist x = u ((c x)/s)
where
interval = head $ filter (\y -> cum_frequence y > x) $ hist
u = upper_bound interval
s = slope interval
c = cum_frequence interval
empiricalCDF hist x
| x < (lower_bound $ head hist) = 0
| x >= (upper_bound $ head $ reverse hist) = 1
| otherwise =
f $ filter (\y -> lower_bound y <= x && upper_bound y >= x) hist
where
f [] =
error $ "x "++(show x)++" not in histogram range\n" ++
(foldr (\h str -> (show (lower_bound h, upper_bound h, frequency h)) ++ "\n" ++ str) "" hist)
f (y:ys) =
let part = (x (lower_bound y)) in
let step = part * slope y in
(cum_frequence y) + (step * (rel_frequence y))
mkEmpirical :: [Double] -> Empirical
mkEmpirical samples = Empirical {
degreesOfFreedom = length h,
cdf = empiricalCDF h,
cdf' = empiricalCDF' h
}
where
h = fIHistogram samples
count :: Double
count = fromInteger . toInteger $ length samples