git.iko.soy/typeable/attoparsec
on master help sign in
Update FastSet.hs
commit2bc976ce147826b6a65cc985e8377ef5e4c61bd7 authorSeanRBurton <burton.seanr@gmail.com> dateSun 30 Nov 2014, 00:13 (12 years ago) parent7bb4e8d
1 file changed+19−21
Data/Attoparsec/Text/FastSet.hs+19−21
Data/Attoparsec/Text/FastSet.hs+19−21
@@ -1,4 +1,4 @@
1−-----------------------------------------------------------------------------
1+------------------------------------------------------------------------------
22-- |
33-- Module : Data.Attoparsec.FastSet
44-- Copyright : Felipe Lessa 2010, Bryan O'Sullivan 2007-2014
@@ -8,10 +8,11 @@
88-- Stability : experimental
99-- Portability : unknown
1010--
11−-- Fast set membership tests for 'Char' values. The set
12−-- representation is unboxed for efficiency. We test for
11+-- Fast set membership tests for 'Char' values. We test for
1312-- membership using a hashtable implemented with Robin Hood
14−-- collision resolution.
13+-- collision resolution. The set representation is unboxed,
14+-- and the characters and hashes interleaved, for efficiency.
15+--
1516--
1617-----------------------------------------------------------------------------
1718module Data.Attoparsec.Text.FastSet
@@ -34,8 +35,7 @@ import qualified Data.Array.Base as AB
3435import qualified Data.Array.Unboxed as A
3536import qualified Data.Text as T
3637
37−data FastSet = FastSet {keys :: {-# UNPACK #-} !(A.UArray Int Char),
38− initialIndeces :: {-# UNPACK #-} !(A.UArray Int Int),
38+data FastSet = FastSet {table :: {-# UNPACK #-} !(A.UArray Int Int),
3939 mask :: {-# UNPACK #-} !Int}
4040 deriving (Eq, Ord, Show)
4141
@@ -58,8 +58,8 @@ resolveCollisions (a:b:entries) = a' : resolveCollisions (b':entries)
5858pad :: Int -> [Entry]-> [Entry]
5959pad = go 0
6060 where go _ m [] = replicate (max 1 m) empty
61− go k m (e:entries) = map (const empty) [k..o - 1] ++ e : go (o + 1) (m + o - k - 1) entries
62− where o = index e
61+ go k m (e:entries) = map (const empty) [k..i - 1] ++ e : go (i + 1) (m + i - k - 1) entries
62+ where i = index e
6363 empty = Entry '\0' maxBound 0
6464
6565nextPowerOf2 :: Int -> Int
@@ -72,7 +72,7 @@ fastHash :: Char -> Int
7272fastHash = fromEnum
7373
7474fromList :: String -> FastSet
75−fromList s = FastSet (arr key) (arr initialIndex) mask'
75+fromList s = FastSet (AB.listArray (0, length interleaved - 1) interleaved) mask'
7676 where s' = nub $ sort s
7777 l = length s'
7878 mask' = nextPowerOf2 ((5 * l) `div` 4) - 1
@@ -80,26 +80,24 @@ fromList s = FastSet (arr key) (arr initialIndex) mask'
8080 entries = pad mask' .
8181 resolveCollisions .
8282 sortBy (compare `on` initialIndex) $
83− zipWith (\c o -> Entry c o o) s' indeces
84− arr :: A.IArray a e => (Entry -> e) -> a Int e
85− arr f = AB.listArray (0, length entries - 1) $ map f entries
86−
83+ zipWith (\c i -> Entry c i i) s' indeces
84+ interleaved = concatMap (\(c, i) -> [c,i]) $ zip (map (fromEnum . key) entries) (map initialIndex entries)
85+
8786set :: T.Text -> FastSet
8887set = fromList . T.unpack
8988
9089-- | Check the set for membership.
9190member :: Char -> FastSet -> Bool
92−member c a = go i
93− where i = (fastHash c .&. mask a)
94− go j
95− | i' > i = False
96− | i' == i && c == c' = True
97− | otherwise = go (j + 1)
98− where i' = AB.unsafeAt (initialIndeces a) j
99− c' = AB.unsafeAt (keys a) j
91+member c a = go (2 * i)
92+ where i = fastHash c .&. mask a
93+ lookupAt j b = (i' <= i) && (c == c' || b)
94+ where c' = toEnum $ AB.unsafeAt (table a) j
95+ i' = AB.unsafeAt (table a) $ j + 1
96+ go j = lookupAt j $ lookupAt (j + 2) $ lookupAt (j + 4) $ lookupAt (j + 6) $ go (j + 8)
10097
10198charClass :: String -> FastSet
10299charClass = fromList . go
103100 where go (a:'-':b:xs) = [a..b] ++ go xs
104101 go (x:xs) = x : go xs
105102 go _ = ""
103+