{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-} -- | -- Module : Statistics.Distribution.Uniform -- Copyright : (c) 2011 Aleksey Khudyakov -- License : BSD3 -- -- Maintainer : bos@serpentine.com -- Stability : experimental -- Portability : portable -- -- Variate distributed uniformly in the interval. module Statistics.Distribution.Uniform ( UniformDistribution -- * Constructors , uniformDistr , uniformDistrE -- ** Accessors , uniformA , uniformB ) where import Control.Applicative import Data.Aeson (FromJSON(..), ToJSON, Value(..), (.:)) import Data.Binary (Binary(..)) import Data.Data (Data, Typeable) import GHC.Generics (Generic) import qualified System.Random.MWC as MWC import qualified Statistics.Distribution as D import Statistics.Internal -- | Uniform distribution from A to B data UniformDistribution = UniformDistribution { uniformA :: {-# UNPACK #-} !Double -- ^ Low boundary of distribution , uniformB :: {-# UNPACK #-} !Double -- ^ Upper boundary of distribution } deriving (Eq, Typeable, Data, Generic) instance Show UniformDistribution where showsPrec i (UniformDistribution a b) = defaultShow2 "uniformDistr" a b i instance Read UniformDistribution where readPrec = defaultReadPrecM2 "uniformDistr" uniformDistrE instance ToJSON UniformDistribution instance FromJSON UniformDistribution where parseJSON (Object v) = do a <- v .: "uniformA" b <- v .: "uniformB" maybe (fail errMsg) return $ uniformDistrE a b parseJSON _ = empty instance Binary UniformDistribution where put (UniformDistribution x y) = put x >> put y get = do a <- get b <- get maybe (fail errMsg) return $ uniformDistrE a b -- | Create uniform distribution. uniformDistr :: Double -> Double -> UniformDistribution uniformDistr a b = maybe (error errMsg) id $ uniformDistrE a b -- | Create uniform distribution. uniformDistrE :: Double -> Double -> Maybe UniformDistribution uniformDistrE a b | b < a = Just $ UniformDistribution b a | a < b = Just $ UniformDistribution a b | otherwise = Nothing -- NOTE: failure is in default branch to guard againist NaNs. errMsg :: String errMsg = "Statistics.Distribution.Uniform.uniform: wrong parameters" instance D.Distribution UniformDistribution where cumulative (UniformDistribution a b) x | x < a = 0 | x > b = 1 | otherwise = (x - a) / (b - a) instance D.ContDistr UniformDistribution where density (UniformDistribution a b) x | x < a = 0 | x > b = 0 | otherwise = 1 / (b - a) quantile (UniformDistribution a b) p | p >= 0 && p <= 1 = a + (b - a) * p | otherwise = error $ "Statistics.Distribution.Uniform.quantile: p must be in [0,1] range. Got: "++show p complQuantile (UniformDistribution a b) p | p >= 0 && p <= 1 = b + (a - b) * p | otherwise = error $ "Statistics.Distribution.Uniform.complQuantile: p must be in [0,1] range. Got: "++show p instance D.Mean UniformDistribution where mean (UniformDistribution a b) = 0.5 * (a + b) instance D.Variance UniformDistribution where -- NOTE: 1/sqrt 12 is not constant folded (#4101) so it's written as -- numerical constant. (Also FIXME!) stdDev (UniformDistribution a b) = 0.2886751345948129 * (b - a) variance (UniformDistribution a b) = d * d / 12 where d = b - a instance D.MaybeMean UniformDistribution where maybeMean = Just . D.mean instance D.MaybeVariance UniformDistribution where maybeStdDev = Just . D.stdDev instance D.Entropy UniformDistribution where entropy (UniformDistribution a b) = log (b - a) instance D.MaybeEntropy UniformDistribution where maybeEntropy = Just . D.entropy instance D.ContGen UniformDistribution where genContVar (UniformDistribution a b) gen = MWC.uniformR (a,b) gen