histogram-fill 0.7.4.0 → 0.8.0.0
raw patch · 3 files changed
+163/−84 lines, 3 filesdep +criteriondep +monad-primitivedep +mwc-randomdep ~basedep ~vectorPVP ok
version bump matches the API change (PVP)
Dependencies added: criterion, monad-primitive, mwc-random
Dependency ranges changed: base, vector
API changes (from Hackage documentation)
+ Data.Histogram.Fill: toHBuilderM :: PrimMonad m => HBuilder a b -> m (HBuilderM m a b)
- Data.Histogram.Fill: HBuilder :: (forall s. ST s (HBuilderM (ST s) a b)) -> HBuilder a b
+ Data.Histogram.Fill: HBuilder :: (forall m. PrimMonad m => m (HBuilderM m a b)) -> HBuilder a b
- Data.Histogram.Fill: fromContainer :: (HistBuilder h, Foldable f) => h a b -> h (f a) b
+ Data.Histogram.Fill: fromContainer :: HistBuilder h => (forall m. Monad m => (a -> m ()) -> f a -> m ()) -> h a b -> h (f a) b
Files
- Data/Histogram/Fill.hs +71/−56
- benchmarks/benchmark.hs +41/−0
- histogram-fill.cabal +51/−28
Data/Histogram/Fill.hs view
@@ -23,14 +23,11 @@ , HBuilderM , feedOne , freezeHBuilderM- , joinHBuilderM- , treeHBuilderM -- ** Stateless , HBuilder(HBuilder) , toHBuilderST , toHBuilderIO- , joinHBuilder- , treeHBuilder+ , toHBuilderM -- * Histogram constructors -- ** Using unboxed vectors , module Data.Histogram.Bin@@ -57,6 +54,11 @@ , forceFloat -- * Examples -- $examples+ -- * Deprecated functions+ , joinHBuilder+ , joinHBuilderM+ , treeHBuilderM+ , treeHBuilder ) where import Control.Applicative@@ -64,12 +66,12 @@ import Control.Monad.ST import Control.Monad.Primitive -import Data.STRef+import Data.PrimRef import Data.Monoid (Monoid(..)) import Data.Vector.Unboxed (Unbox) import qualified Data.Vector.Generic as G-import qualified Data.Foldable as F (Foldable,mapM_)-import qualified Data.Traversable as F (Traversable,mapM)+import qualified Data.Foldable as F+import qualified Data.Traversable as F import Data.Histogram import qualified Data.Histogram.Generic as H@@ -96,7 +98,9 @@ -- | Change input of builder by applying function to it. modifyIn :: (a' -> a) -> h a b -> h a' b -- | Put all values in container into builder - fromContainer :: F.Foldable f => h a b -> h (f a) b+ fromContainer :: (forall m. Monad m => (a -> m ()) -> f a -> m ())+ -- ^ @mapM_@ function for container+ -> h a b -> h (f a) b -- | Add cut to histogram. Value would be putted into histogram -- only if condition is true. addCut :: (a -> Bool) -> h a b -> h a b@@ -109,7 +113,7 @@ -- | Modify input of builder to use composite input (<<-|) :: (HistBuilder h, F.Foldable f) => h a b -> (a' -> f a) -> h a' b-h <<-| f = fromContainer h <<- f+h <<-| f = fromContainer F.mapM_ h <<- f {-# INLINE (<<-|) #-} -- | Add cut for input@@ -176,10 +180,10 @@ -- > (forceInt -<< mkSimple (BinI 0 4) <<? even) -- > (forceInt -<< mkSimple (BinI 0 4) <<? odd) ----- Another approach is to use 'joinHBuilder' to simultaneously fill+-- Another approach is to use 'F.sequenceA' to simultaneously fill -- list (or any other 'Travesable'). ----- > joinHBuilder [+-- > Data.Traversable.sequenceA [ -- > forceInt -<< mkSimple (BinI 0 4) <<? even -- > , forceInt -<< mkSimple (BinI 0 4) <<? odd -- > ]@@ -211,10 +215,10 @@ -- | Builders modified using 'HistBuilder' API will share same buffer. instance PrimMonad m => HistBuilder (HBuilderM m) where- modifyIn f h = h { hbInput = hbInput h . f }- addCut f h = h { hbInput = \x -> when (f x) (hbInput h x) }- fromContainer h = h { hbInput = F.mapM_ (hbInput h) }- modifyOut f h = h { hbOutput = f `liftM` hbOutput h }+ modifyIn f h = h { hbInput = hbInput h . f }+ addCut f h = h { hbInput = \x -> when (f x) (hbInput h x) }+ fromContainer fmapM_ h = h { hbInput = fmapM_ (hbInput h) }+ modifyOut f h = h { hbOutput = f `liftM` hbOutput h } instance PrimMonad m => Functor (HBuilderM m a) where fmap = modifyOut@@ -233,10 +237,11 @@ , hbOutput = return mempty } mappend h1 h2 = mappend <$> h1 <*> h2- mconcat = fmap mconcat . joinHBuilderM+ mconcat = fmap mconcat . F.sequenceA {-# INLINE mempty #-} {-# INLINE mconcat #-} + -- | Put one item into histogram feedOne :: PrimMonad m => HBuilderM m a b -> a -> m () feedOne = hbInput@@ -248,47 +253,36 @@ freezeHBuilderM = hbOutput {-# INLINE freezeHBuilderM #-} --- | Join histogram builders in container-joinHBuilderM :: (F.Traversable f, PrimMonad m) => f (HBuilderM m a b) -> HBuilderM m a (f b)-joinHBuilderM hs = HBuilderM { hbInput = \x -> F.mapM_ (flip hbInput x) hs- , hbOutput = F.mapM hbOutput hs- }-{-# INLINE joinHBuilderM #-} --- | Apply functions to builder-treeHBuilderM :: (PrimMonad m, F.Traversable f) => f (HBuilderM m a b -> HBuilderM m a' b') -> HBuilderM m a b -> HBuilderM m a' (f b')-treeHBuilderM fs h = joinHBuilderM $ fmap ($ h) fs-{-# INLINE treeHBuilderM #-} -- ---------------------------------------------------------------- -- Stateless ---------------------------------------------------------------- -- | Wrapper around stateful histogram builder. It is much more -- convenient to work with than 'HBuilderM'.-newtype HBuilder a b = HBuilder (forall s . ST s (HBuilderM (ST s) a b))+newtype HBuilder a b = HBuilder (forall m. PrimMonad m => m (HBuilderM m a b)) +-- | Convert builder to stateful builder in primitive monad+toHBuilderM :: PrimMonad m => HBuilder a b -> m (HBuilderM m a b)+{-# INLINE toHBuilderM #-}+toHBuilderM (HBuilder hb) = hb+ -- | Convert builder to stateful builder in ST monad toHBuilderST :: HBuilder a b -> ST s (HBuilderM (ST s) a b) {-# INLINE toHBuilderST #-}-toHBuilderST (HBuilder hb) = hb+toHBuilderST = toHBuilderM -- | Convert builder to builder in IO monad toHBuilderIO :: HBuilder a b -> IO (HBuilderM IO a b) {-# INLINE toHBuilderIO #-}-toHBuilderIO (HBuilder h) = do- builder <- stToIO h- return (HBuilderM- (stToIO . hbInput builder)- (stToIO $ hbOutput builder))+toHBuilderIO = toHBuilderM instance HistBuilder (HBuilder) where- modifyIn f (HBuilder h) = HBuilder (modifyIn f <$> h)- addCut f (HBuilder h) = HBuilder (addCut f <$> h)- fromContainer (HBuilder h) = HBuilder (fromContainer <$> h)- modifyOut f (HBuilder h) = HBuilder (modifyOut f <$> h)+ modifyIn f (HBuilder h) = HBuilder (modifyIn f `liftM` h)+ addCut f (HBuilder h) = HBuilder (addCut f `liftM` h)+ fromContainer fmapM_ (HBuilder h) = HBuilder (fromContainer fmapM_ `liftM` h)+ modifyOut f (HBuilder h) = HBuilder (modifyOut f `liftM` h) instance Functor (HBuilder a) where fmap = modifyOut@@ -298,23 +292,13 @@ instance Monoid b => Monoid (HBuilder a b) where mempty = HBuilder (return mempty) mappend h g = mappend <$> h <*> g- mconcat = fmap mconcat . joinHBuilder+ mconcat = fmap mconcat . F.sequenceA {-# INLINE mempty #-} {-# INLINE mappend #-} {-# INLINE mconcat #-} --- | Join hitogram builders in container.-joinHBuilder :: F.Traversable f => f (HBuilder a b) -> HBuilder a (f b)-joinHBuilder hs = HBuilder (joinHBuilderM <$> F.mapM toHBuilderST hs)-{-# INLINE joinHBuilder #-} --- | Apply function to builder-treeHBuilder :: F.Traversable f => f (HBuilder a b -> HBuilder a' b') -> HBuilder a b -> HBuilder a' (f b')-treeHBuilder fs h = joinHBuilder $ fmap ($ h) fs-{-# INLINE treeHBuilder #-} -- ---------------------------------------------------------------- -- Constructors ----------------------------------------------------------------@@ -396,11 +380,9 @@ mkFolder :: b -> (a -> b -> b) -> HBuilder a b {-# INLINE mkFolder #-} mkFolder a f = HBuilder $ do- ref <- newSTRef a- return HBuilderM { hbInput = \x -> do acc <- readSTRef ref- let !acc' = f x acc- writeSTRef ref acc'- , hbOutput = readSTRef ref+ ref <- newPrimRef a+ return HBuilderM { hbInput = \x -> modifyPrimRef' ref (f x)+ , hbOutput = readPrimRef ref } @@ -429,7 +411,8 @@ -- | Fill histogram builder. fillBuilderVec :: G.Vector v a => HBuilder a b -> v a -> b-fillBuilderVec hb vec =+{-# INLINE fillBuilderVec #-}+fillBuilderVec hb = \vec -> runST $ do h <- toHBuilderST hb G.mapM_ (feedOne h) vec freezeHBuilderM h@@ -457,3 +440,35 @@ forceFloat :: H.Histogram v bin Float -> H.Histogram v bin Float forceFloat = id++++----------------------------------------------------------------+-- Deprecated+----------------------------------------------------------------++-- | Join histogram builders in container+joinHBuilderM :: (F.Traversable f, PrimMonad m) => f (HBuilderM m a b) -> HBuilderM m a (f b)+joinHBuilderM = F.sequenceA+{-# INLINE joinHBuilderM #-}+{-# DEPRECATED joinHBuilderM "Use Data.Traversable.sequenceA instead" #-}++-- | Apply functions to builder+treeHBuilderM :: (PrimMonad m, F.Traversable f) => f (HBuilderM m a b -> HBuilderM m a' b') -> HBuilderM m a b -> HBuilderM m a' (f b')+treeHBuilderM fs h = F.traverse ($ h) fs+{-# INLINE treeHBuilderM #-}+{-# DEPRECATED treeHBuilderM+ "Use Data.Traversable.traverse. treeHBuilderM fs h = F.traverse ($ h) fs" #-}++-- | Join hitogram builders in container.+joinHBuilder :: F.Traversable f => f (HBuilder a b) -> HBuilder a (f b)+joinHBuilder = F.sequenceA+{-# INLINE joinHBuilder #-}+{-# DEPRECATED joinHBuilder "Use Data.Traversable.sequenceA instead" #-}++-- | Apply function to builder+treeHBuilder :: F.Traversable f => f (HBuilder a b -> HBuilder a' b') -> HBuilder a b -> HBuilder a' (f b')+treeHBuilder fs h = F.traverse ($ h) fs+{-# INLINE treeHBuilder #-}+{-# DEPRECATED treeHBuilder+ "Use Data.Traversable.traverse. treeHBuilderM fs h = F.traverse ($ h) fs" #-}
+ benchmarks/benchmark.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+import Control.Monad+import Control.Monad.ST+import qualified Data.Vector.Unboxed as U+import System.Random.MWC+import Criterion.Main++import Data.Histogram.Fill+import Data.Histogram+++main :: IO ()+main =+ defaultMain+ [ bgroup "bin"+ [ bench "BinI" $ nf (toIndex (binI0 10)) 4+ , bench "BinInt" $ nf (toIndex (BinInt 4 4 4)) 12+ , bench "BinD" $ nf (toIndex (binD 0 10 1)) 0.33+ , bench "BinF::F" $ nf (toIndex (binF 0 10 1)) (0.33 :: Float)+ , bench "BinF::D" $ nf (toIndex (binF 0 10 1)) (0.33 :: Double)+ , bench "BinI><BinI" $ nf (toIndex (binI0 10 >< binI0 10 )) (3,5)+ , bench "BinD><BinD" $ nf (toIndex (binD 0 10 1 >< binD 0 10 1)) (0.3,0.5)+ ]+ , bgroup "hist"+ [ bench "BinI-2" $ nf (fillBuilderVec (forceInt -<< mkSimple (binI0 100))) (mkRange 100)+ , bench "BinI-3" $ nf (fillBuilderVec (forceInt -<< mkSimple (binI0 100))) (mkRange 1000)+ , bench "BinI-4" $ nf (fillBuilderVec (forceInt -<< mkSimple (binI0 100))) (mkRange 10000)+ , bench "BinI-w2" $ nf (fillBuilderVec (forceDouble -<< mkWeighted (binI0 100))) (mkRangeW 100)+ , bench "BinI-w3" $ nf (fillBuilderVec (forceDouble -<< mkWeighted (binI0 100))) (mkRangeW 1000)+ , bench "BinI-w4" $ nf (fillBuilderVec (forceDouble -<< mkWeighted (binI0 100))) (mkRangeW 10000)+ ]+ ]++mkRange n = runST $ do+ gen <- create+ U.replicateM n (uniform gen)++mkRangeW n = runST $ do+ gen <- create+ U.replicateM n $ liftM2 (,) (uniformR (-10,110) gen) (uniformR (0,10) gen)
histogram-fill.cabal view
@@ -1,10 +1,17 @@ Name: histogram-fill-Version: 0.7.4.0+Version: 0.8.0.0 Synopsis: Library for histograms creation. Description: This is library for histograms filling. Its aim to provide convenient way to create and fill histograms. .+ Changes in 0.8.0.0+ .+ * @toHBuilderM@ added and internal definition of @HBuilder@ is+ changed. It required adding dependency on @monad-primitive@.+ .+ * @joinHBuilder@ and @treeHBuilder@ are deprecated.+ . Changes in 0.7.3.0 . * Function for searching for minimum/maximum added.@@ -27,7 +34,7 @@ . Changes in 0.7.0.0 .- * mkFoldBuilder is added to @Data.Histogram.Fill@+ * @mkFoldBuilder@ is added to @Data.Histogram.Fill@ . * fill functions in @Data.Histogram.ST@ are replaced with generic variant.@@ -66,7 +73,8 @@ License-File: LICENSE Author: Alexey Khudyakov Maintainer: Alexey Khudyakov <alexey.skladnoy@gmail.com>-Homepage: http://bitbucket.org/Shimuuar/histogram-fill/+Homepage: https://bitbucket.org/Shimuuar/histogram-fill/+Bug-reports: https://github.com/Shimuuar/histogram-fill/issues Category: Data Build-Type: Simple extra-source-files:@@ -80,27 +88,30 @@ location: http://github.com/Shimuuar/histogram-fill Library- Build-Depends: base >=3 && <5,- deepseq,- primitive,- vector >= 0.10.0.1- Exposed-modules: Data.Histogram- Data.Histogram.Generic- Data.Histogram.Fill- Data.Histogram.Bin- Data.Histogram.Bin.Classes- Data.Histogram.Bin.BinI- Data.Histogram.Bin.BinInt- Data.Histogram.Bin.BinEnum- Data.Histogram.Bin.BinF- Data.Histogram.Bin.LogBinD- Data.Histogram.Bin.MaybeBin- Data.Histogram.Bin.Bin2D- Data.Histogram.Bin.Extra- Data.Histogram.Bin.Read- Data.Histogram.ST Ghc-options: -O2 -Wall Ghc-prof-options: -auto-all+ Build-Depends:+ base >=3 && <5,+ deepseq,+ primitive,+ monad-primitive >= 0.1,+ vector >= 0.10.0.1+ Exposed-modules:+ Data.Histogram+ Data.Histogram.Generic+ Data.Histogram.Fill+ Data.Histogram.Bin+ Data.Histogram.Bin.Classes+ Data.Histogram.Bin.BinI+ Data.Histogram.Bin.BinInt+ Data.Histogram.Bin.BinEnum+ Data.Histogram.Bin.BinF+ Data.Histogram.Bin.LogBinD+ Data.Histogram.Bin.MaybeBin+ Data.Histogram.Bin.Bin2D+ Data.Histogram.Bin.Extra+ Data.Histogram.Bin.Read+ Data.Histogram.ST test-suite tests type: exitcode-stdio-1.0@@ -108,9 +119,21 @@ main-is: QC.hs other-modules: QC.Instances ghc-options: -Wall- build-depends: base >=3 && < 5,- histogram-fill,- vector,- QuickCheck >= 2,- test-framework,- test-framework-quickcheck2+ build-depends:+ base >=3 && < 5,+ histogram-fill,+ vector,+ QuickCheck >= 2,+ test-framework,+ test-framework-quickcheck2++Benchmark benchmarks+ Type: exitcode-stdio-1.0+ Main-is: benchmark.hs+ hs-source-dirs: benchmarks+ build-depends:+ base >=3 && <5,+ histogram-fill,+ mwc-random,+ vector,+ criterion