on master help sign in
Rewrite lazy isInfixOf and count in terms of indices.

--HG-- extra : convert_revision : 3d0038ea0a53ce47acb8ed74eb4df40f9eedeaa2

commit42b89e6d0f1f7a3efda07e7d5b0afb98dd2c21d0 authorBryan O'Sullivan <bos@serpentine.com> dateFri 9 Oct 2009, 04:10 (17 years ago) parent22783d3
1 file changed+23−16
Data/Text/Lazy.hs+23−16
Data/Text/Lazy.hs+23−16
@@ -1034,13 +1034,23 @@ isSuffixOf x y = reverse x `isPrefixOf` reverse y
10341034{-# INLINE isSuffixOf #-}
10351035-- TODO: a better implementation
10361036
1037−-- | /O(n)/ The 'isInfixOf' function takes two 'Text's and returns
1037+-- | /O(n+m)/ The 'isInfixOf' function takes two 'Text's and returns
10381038-- 'True' iff the first is contained, wholly and intact, anywhere
10391039-- within the second.
1040+--
1041+-- In (unlikely) bad cases, this function's time complexity degrades
1042+-- towards /O(n*m)/.
10401043isInfixOf :: Text -> Text -> Bool
1041−isInfixOf needle haystack = L.any (isPrefixOf needle) (tails haystack)
1042−{-# INLINE isInfixOf #-}
1043−-- TODO: a better implementation
1044+isInfixOf needle haystack
1045+ | null needle = True
1046+ | isSingleton needle = S.elem (head needle) . S.stream $ haystack
1047+ | otherwise = not . L.null . indices needle $ haystack
1048+{-# INLINE [1] isInfixOf #-}
1049+
1050+{-# RULES
1051+"LAZY TEXT isInfixOf/singleton -> S.elem/S.stream" [~1] forall n h.
1052+ isInfixOf (singleton n) h = S.elem n (S.stream h)
1053+ #-}
10441054
10451055-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
10461056-- returns a 'Text' containing those characters that satisfy the
@@ -1070,21 +1080,18 @@ index :: Text -> Int64 -> Char
10701080index t n = S.index (stream t) n
10711081{-# INLINE index #-}
10721082
1073−-- | /O(n*m)/ The 'count' function returns the number of times the
1083+-- | /O(n+m)/ The 'count' function returns the number of times the
10741084-- query string appears in the given 'Text'. An empty query string is
10751085-- invalid, and will cause an error to be raised.
1086+--
1087+-- In (unlikely) bad cases, this function's time complexity degrades
1088+-- towards /O(n*m)/.
10761089count :: Text -> Text -> Int64
1077−count pat src0
1078− | l == 0 = emptyError "count"
1079− | l == 1 = countChar (head pat) src0
1080− | otherwise = go 0 src0
1081− where
1082− l = length pat
1083− go !n src = search src
1084− where
1085− search s | null s = n
1086− | pat `isPrefixOf` s = go (n+1) (drop l s)
1087− | otherwise = search (tail s)
1090+count pat src
1091+ | null pat = emptyError "count"
1092+ | otherwise = len (indices pat src)
1093+ where len [] = 0
1094+ len (_:xs) = 1 + len xs
10881095{-# INLINE [1] count #-}
10891096
10901097{-# RULES