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 +30/−0
- Setup.hs +2/−0
- iter-stats.cabal +54/−0
- src/Statistics/Iteratee.hs +6/−0
- src/Statistics/Iteratee/Compat.hs +17/−0
- src/Statistics/Iteratee/Sample.hs +102/−0
- src/Statistics/Iteratee/Uniform.hs +67/−0
- tests/Statistics/Iteratee/Tests.hs +39/−0
- tests/TestSuite.hs +6/−0
+ 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