on master help sign in
Add rolling hash folds
commitf503496a4d0dfce9f05f29ebf3c8acf4ba9b6c84 authorHarendra Kumar <harendra.kumar@gmail.com> dateThu 5 Sep 2019, 20:43 (7 years ago) parent307fa9f
5 files changed+75−3
src/Streamly/Fold.hs+1 src/Streamly/Fold/Internal.hs+66 src/Streamly/Internal.hs+4−1 src/Streamly/Memory/Array.hs+3−2 streamly.cabal+1
src/Streamly/Fold.hs+1
@@ -88,6 +88,7 @@ module Streamly.Fold
8888 -- ** Partial Folds
8989 -- , drainN
9090 -- , drainWhile
91+ -- , lastN
9192 -- , (!!)
9293 -- , genericIndex
9394 , index
src/Streamly/Fold/Internal.hsnew file+66
@@ -0,0 +1,66 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE ExistentialQuantification #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE RankNTypes #-}
6+{-# LANGUAGE RecordWildCards #-}
7+{-# LANGUAGE ScopedTypeVariables #-}
8+
9+-- |
10+-- Module : Streamly.Fold.Internal
11+-- Copyright : (c) 2019 Composewell Technologies
12+-- (c) 2013 Gabriel Gonzalez
13+-- License : BSD3
14+-- Maintainer : harendra.kumar@gmail.com
15+-- Stability : experimental
16+-- Portability : GHC
17+
18+module Streamly.Fold.Internal
19+ (
20+ rollingHash
21+ , rollingHashWithSalt
22+ -- , rollingHashFirstN
23+ -- , rollingHashLastN
24+ )
25+where
26+
27+import Streamly.Fold.Types (Fold(..))
28+
29+-- | Compute an 'Int' sized polynomial rolling hash
30+--
31+-- > H = salt * k ^ n + c1 * k ^ (n - 1) + c2 * k ^ (n - 2) + ... + cn * k ^ 0
32+--
33+-- Where @c1@, @c2@, @cn@ are the elements in the input stream and @k@ is a
34+-- constant.
35+--
36+-- This hash is often used in Rabin-Karp string search algorithm.
37+--
38+-- See https://en.wikipedia.org/wiki/Rolling_hash
39+--
40+-- @since 0.7.0
41+{-# INLINABLE rollingHashWithSalt #-}
42+rollingHashWithSalt :: (Monad m, Enum a) => Int -> Fold m a Int
43+rollingHashWithSalt salt = Fold step initial extract
44+ where
45+ k = 2891336453
46+ initial = return salt
47+ step cksum a = return $ cksum * k + fromEnum a
48+ extract = return
49+
50+-- | A default salt used in the implementation of 'rollingHash'.
51+{-# INLINE defaultSalt #-}
52+defaultSalt :: Int
53+#if WORD_SIZE_IN_BITS == 64
54+defaultSalt = 0xdc36d1615b7400a4
55+#else
56+defaultSalt = 0x087fc72c
57+#endif
58+
59+-- | Compute an 'Int' sized polynomial rolling hash of a stream.
60+--
61+-- > rollingHash = rollingHashWithSalt defaultSalt
62+--
63+-- @since 0.7.0
64+{-# INLINABLE rollingHash #-}
65+rollingHash :: (Monad m, Enum a) => Fold m a Int
66+rollingHash = rollingHashWithSalt defaultSalt
src/Streamly/Internal.hs+4−1
@@ -69,6 +69,8 @@ module Streamly.Internal
6969
7070 -- * Streamly.Fold Experimental Exports
7171 , Fold (..)
72+ , rollingHash
73+ , rollingHashWithSalt
7274 , lmap
7375 , lmapM
7476 , lfilter
@@ -98,5 +100,6 @@ import Streamly.Streams.Parallel (tapAsync, parallelFst, parallelMin)
98100import Streamly.Streams.Serial (wSerialFst, wSerialMin)
99101import Streamly.Unfold.Types (Unfold(..))
100102
101−import Streamly.Prelude.Internal
103+import Streamly.Fold.Internal
102104import Streamly.Fold.Types
105+import Streamly.Prelude.Internal
src/Streamly/Memory/Array.hs+3−2
@@ -80,8 +80,9 @@ module Streamly.Memory.Array
8080
8181 -- Monadic APIs
8282 -- , newArray
83− , A.writeN
84− , write
83+ , A.writeN -- drop new
84+ , write -- full buffer
85+ -- , writeLastN -- drop old (ring buffer)
8586
8687 -- Stream Folds
8788 -- , writeNS
streamly.cabal+1
@@ -288,6 +288,7 @@ library
288288
289289 -- Folds
290290 , Streamly.Fold.Types
291+ , Streamly.Fold.Internal
291292 , Streamly.Sink.Types
292293 , Streamly.Sink
293294 , Streamly.Pipe.Types