packages feed

iter-stats (empty) → 0.1.0.1

raw patch · 9 files changed

+323/−0 lines, 9 filesdep +HUnitdep +ListLikedep +basesetup-changed

Dependencies added: HUnit, ListLike, base, heap, iteratee, mtl, statistics, test-framework, test-framework-hunit, test-framework-quickcheck2, vector

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2012, John W. Lato++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of John W. Lato nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ iter-stats.cabal view
@@ -0,0 +1,54 @@+-- Initial iter-stats.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                iter-stats+version:             0.1.0.1+synopsis:            iteratees for statistical processing+description:         efficient statistical values of data streams+homepage:            https://github.com/JohnLato/iter-stats+license:             BSD3+license-file:        LICENSE+author:              John W. Lato+maintainer:          jwlato@gmail.com+copyright:           John W. Lato, 2012+category:            Math+build-type:          Simple+cabal-version:       >=1.8++library+  exposed-modules:     Statistics.Iteratee,+                       Statistics.Iteratee.Compat,+                       Statistics.Iteratee.Sample,+                       Statistics.Iteratee.Uniform+  -- other-modules:       +  build-depends:       base >=4.5 && < 4.7,+                       heap == 1.*,+                       iteratee >=0.8,+                       ListLike >=3,+                       mtl ==2.1.*+  hs-source-dirs:      src++Test-suite iter-stats-tests+  Hs-source-dirs: src tests+  Main-is:        TestSuite.hs+  Type:           exitcode-stdio-1.0++  Other-modules:+    Statistics.Iteratee.Tests++  Build-depends:+    HUnit                      >= 1.2 && < 1.3,+    statistics,+    test-framework             >= 0.4 && < 0.9,+    test-framework-hunit       >= 0.2 && < 0.4,+    test-framework-quickcheck2 >= 0.2 && < 0.4,+    vector                     >= 0.9,+    base,+    heap,+    iteratee,+    ListLike,+    mtl++source-repository head+  type:                git+  location:            git://github.com/JohnLato/iter-stats.git
+ src/Statistics/Iteratee.hs view
@@ -0,0 +1,6 @@+module Statistics.Iteratee (+  module S+) where++import Statistics.Iteratee.Sample as S+import Statistics.Iteratee.Uniform as S
+ src/Statistics/Iteratee/Compat.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}++module Statistics.Iteratee.Compat (+  ListLikey+)++where++import Data.Iteratee as I+import Data.ListLike (ListLike)++#if MIN_VERSION_iteratee(0,9,0)+type ListLikey s el = (ListLike s el)+#else+type ListLikey s el = (ListLike s el, Nullable s)+#endif
+ src/Statistics/Iteratee/Sample.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ConstraintKinds #-}++{-# OPTIONS -Wall #-}+module Statistics.Iteratee.Sample (+  minMaxNBy+, range+, mean+, harmonicMean+, variance+, stdDev+) where++import Statistics.Iteratee.Compat+import Control.Arrow+import Control.Monad+import Data.Iteratee as I++import Data.Heap as Heap++--  | /O(n)/ minMaxNBy. Calculate the 'n' highest and lowest elements of the+--  stream, according to the given priority function.+--  Returns /([minimum],[maximum]/ with the /(minimum,maximum)/+--  elements listed first.+minMaxNBy+  :: forall m prio s el. (Monad m, Ord prio, ListLikey s el)+  => Int+  -> (el -> prio)+  -> Iteratee s m ([(prio,el)],[(prio,el)])+minMaxNBy ns prio = finalize `liftM` I.foldl' step (Heap.empty,Heap.empty)+  where+    finalize :: (MaxPrioHeap prio el, MinPrioHeap prio el)+             -> ([(prio,el)],[(prio,el)])+    finalize = Heap.toDescList *** Heap.toDescList+    addHeap val = Heap.insert (prio val, val)+    step :: (MaxPrioHeap prio el, MinPrioHeap prio el) -> el+            -> (MaxPrioHeap prio el, MinPrioHeap prio el)+    step (!mins,!maxes) val = let sz = Heap.size mins+                                  adj hp = if sz >= ns+                                             then Heap.drop 1 hp+                                             else hp+                              in (adj $ addHeap val mins+                                 ,adj $ addHeap val maxes)+{-# INLINE minMaxNBy #-}++-- | /O(n)/ Range. The difference between the largest and smallest elements of+-- a stream.+range :: (Monad m, ListLikey s el, Num el, Ord el)+      => Iteratee s m el+range = finalize `liftM` minMaxNBy 1 id+  where+    finalize ([mins],[maxes]) = snd maxes - snd mins+    finalize _ = 0+{-# INLINE range #-}++-- | /O(n)/ Arithmetic mean.  Uses Welford's algorithm.+mean :: forall s m el. (Fractional el, Monad m, ListLikey s el)+     => Iteratee s m el+mean = fst `liftM` I.foldl' step (0,0)+  where+    step :: (el,Integer) -> el -> (el,Integer)+    step (!m,!n) x = let m' = m + (x-m) / fromIntegral n'+                         n' = n + 1+                     in  (m',n')+{-# INLINE mean #-}++-- | /O(n)/ Harmonic mean.+harmonicMean :: (Fractional el, Monad m, ListLikey s el) => Iteratee s m el+harmonicMean = finalize `liftM` I.foldl' step (0,0 :: Integer)+  where+    finalize (m,n) = fromIntegral n / m+    step (!m,!n) val = (m+(1/val),n+1)+{-# INLINE harmonicMean #-}++-- | /O(n)/ variance, using Knuth's algorithm.+var :: (Fractional el, Integral t, Monad m, ListLikey s el)+    => Iteratee s m (t, el, el)+var = I.foldl' step (0,0,0)+  where+    step (!n,!m,!s) x = let n' = n+1+                            m' = m+d/fromIntegral n'+                            s' = s+d* (x-m')+                            d  = x-m+                        in (n',m',s')+{-# INLINE var #-}++-- | /O(n)/ Maximum likelihood estimate of a sample's variance, using Knuth's+--   algorithm.+variance :: (Fractional b, Monad m, ListLikey s b) => Iteratee s m b+variance = finalize `liftM` var+  where+    finalize (n,_,s)+      | n > 1 = s / fromInteger n+      | otherwise = 0+{-# INLINE variance #-}++-- | /O(n) Standard deviation, using Knuth's algorithm.+stdDev :: (Floating b, Monad m, Functor m, ListLikey s b) => Iteratee s m b+stdDev = sqrt `liftM` variance+{-# INLINE stdDev #-}
+ src/Statistics/Iteratee/Uniform.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoMonomorphismRestriction #-}++{-# OPTIONS -Wall #-}+-- | some functions for working with uniformly-sampled data+module Statistics.Iteratee.Uniform (+  someRollingFunction+, movingAverage+) where++import Statistics.Iteratee.Compat+import Statistics.Iteratee.Sample++import Control.Monad.Identity+import Data.Iteratee as I+import Data.ListLike (ListLike)++#if MIN_VERSION_iteratee(0,9,0)+#else+import qualified Data.ListLike as LL+#endif++#if MIN_VERSION_iteratee(0,9,0)+roll'+    :: (Monad m, ListLike s el)+    => Int  -- ^ length of chunk (t)+    -> Int  -- ^ amount to consume (d)+    -> Iteratee s m [s]+roll' = roll+#else+roll'+    :: (Monad m, Nullable s, ListLike s el)+    => Int  -- ^ length of chunk (t)+    -> Int  -- ^ amount to consume (d)+    -> Iteratee s m [s]+roll' t d+  | t > d  = liftI (go LL.empty)+  | otherwise = error "Iteratee.roll: (t <= d).  Reverse the args?"+    where+        go prev (Chunk vec) =+                let withPrev = prev `LL.append` vec+                in if LL.length withPrev > t+                    then idone [LL.take t withPrev] (Chunk $ LL.drop d withPrev)+                    else liftI (go withPrev)+        go prev e = idone [prev] e+#endif++someRollingFunction+    :: (Monad m, ListLikey s el)+    => Int+    -> (s -> summary)+    -> Enumeratee s [summary] m a+someRollingFunction count mkSummary =+    convStream (roll' count 1)+    ><> mapStream mkSummary+{-# INLINABLE someRollingFunction #-}++movingAverage+    :: (Fractional el, Monad m, ListLikey s el)+    => Int+    -> Enumeratee s [el] m a+movingAverage n = someRollingFunction n chunkMean+  where+    chunkMean = runIdentity . (run <=< flip enumPure1Chunk mean)+{-# INLINABLE movingAverage #-}
+ tests/Statistics/Iteratee/Tests.hs view
@@ -0,0 +1,39 @@+module Statistics.Iteratee.Tests++where++import Data.Iteratee as I+import Statistics.Iteratee as Si+import Statistics.Sample as St+import Test.Framework+import Test.Framework.Providers.QuickCheck2 (testProperty)++import Control.Monad.Identity+import qualified Data.Vector.Unboxed as V++tests =+  [ testGroup "Sample" $ map mkUnProp uns+  ]++unsProp :: (Eq a)+        => (V.Vector Double -> a)+        -> (Iteratee [Double] Identity a)+        -> [Double]+        -> Bool+unsProp vec iter xs = if null xs then True+    else vec (V.fromList xs) == (runIdentity $ run =<< enumPure1Chunk xs iter)+    -- we're using Eq for doubles, which is always a bad idea...++    -- also not checking empty vectors, because in some cases (range,+    -- harmonicMean) we get NaN's or other funky values.++mkUnProp (lbl, st, si) = testProperty lbl $ unsProp st si++-- unary properties+uns =+  [ ("mean", St.mean, Si.mean)+  , ("range", St.range, Si.range)+  , ("harmonic_mean", St.harmonicMean, Si.harmonicMean)+  , ("variance", St.fastVariance, Si.variance)+  , ("std_dev", St.fastStdDev,   Si.stdDev)+  ]
+ tests/TestSuite.hs view
@@ -0,0 +1,6 @@+import Test.Framework (defaultMain)++import qualified Statistics.Iteratee.Tests as T++main :: IO ()+main = defaultMain T.tests