@@ -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