module Amby.Numeric
( contDistrDomain
, contDistrRange
, linspace
, arange
) where
import Data.Either.Combinators
import Data.Scientific
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector as V
import Statistics.Distribution
contDistrDomain :: (ContDistr d) => d -> Int -> U.Vector Double
contDistrDomain d num = linspace (quantile d 0.0001) (quantile d 0.9999) num
contDistrRange :: (ContDistr d) => d -> U.Vector Double -> U.Vector Double
contDistrRange d x = U.map (density d) x
linspace :: Double -> Double -> Int -> U.Vector Double
linspace start stop num
| num < 0 = error ("Number of samples, " ++ show num ++ ", must be non-negative.")
| num == 0 || num == 1 = addStart $ U.generate num ((* delta) . fromIntegral)
| otherwise = addStart $ U.generate num ((* step) . fromIntegral)
where
delta = stop start
step = delta / fromIntegral (num 1)
addStart = U.map (realToFrac . (+ start))
arange :: Double -> Double -> Double -> U.Vector Double
arange start stop step = U.fromList [start,(start + step)..stop]