{-# LANGUAGE BangPatterns #-}
module Data.Histogram.ST (
MHistogram
, newMHistogram
, fill
, unsafeFreezeHist
, freezeHist
) where
import Control.Monad
import Control.Monad.Primitive
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as M
import Data.Histogram.Generic
data MHistogram s v bin a =
MHistogram
{-# UNPACK #-} !Int
!bin
!(v s a)
newMHistogram :: (PrimMonad m, Bin bin, M.MVector v a) => a -> bin -> m (MHistogram (PrimState m) v bin a)
newMHistogram zero bin = do
let n = nBins bin
when (n < 0) $
error "Data.Histogram.ST.newMHistogram: negative number of bins"
a <- M.replicate (n + 2) zero
return $ MHistogram n bin a
{-# INLINE newMHistogram #-}
fill :: (PrimMonad m, M.MVector v a, Bin bin)
=> MHistogram (PrimState m) v bin a
-> BinValue bin
-> (a -> b -> a)
-> b
-> m ()
fill (MHistogram n bin arr) !x f val = do
a <- M.unsafeRead arr ix
M.unsafeWrite arr ix $! f a val
where
i = toIndex bin x
ix | i < 0 = n
| i >= n = n+1
| otherwise = i
{-# INLINE fill #-}
unsafeFreezeHist :: (PrimMonad m, G.Vector v a, Bin bin)
=> MHistogram (PrimState m) (G.Mutable v) bin a
-> m (Histogram v bin a)
unsafeFreezeHist (MHistogram n bin arr) = do
u <- M.unsafeRead arr n
o <- M.unsafeRead arr (n+1)
a <- G.unsafeFreeze $ M.slice 0 n arr
return $ histogramUO bin (Just (u,o)) a
{-# INLINE unsafeFreezeHist #-}
freezeHist :: (PrimMonad m, G.Vector v a, Bin bin)
=> MHistogram (PrimState m) (G.Mutable v) bin a
-> m (Histogram v bin a)
freezeHist (MHistogram n bin arr) = do
u <- M.unsafeRead arr n
o <- M.unsafeRead arr (n+1)
a <- G.freeze $ M.slice 0 n arr
return $ histogramUO bin (Just (u,o)) a
{-# INLINE freezeHist #-}