From: Date: Thu, 22 Jul 2010 21:07:26 +0000 (+0000) Subject: Allow Data.HashTable construction with user-supplied size X-Git-Tag: ghc-darcs-git-switchover~119 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=34f2d1b3a8e85e5310f78a84e189f98729af28c9;p=ghc-base.git Allow Data.HashTable construction with user-supplied size This avoids some resizing for users who know they will be inserting a lot of data. http://hackage.haskell.org/trac/ghc/ticket/4193 --- diff --git a/Data/HashTable.hs b/Data/HashTable.hs index 8680602..c407abf 100644 --- a/Data/HashTable.hs +++ b/Data/HashTable.hs @@ -19,7 +19,7 @@ module Data.HashTable ( -- * Basic hash table operations - HashTable, new, insert, delete, lookup, update, + HashTable, new, newHint, insert, delete, lookup, update, -- * Converting to and from lists fromList, toList, -- * Hash functions @@ -283,6 +283,55 @@ new cmpr hash = do table <- newIORef ht return (HashTable { tab=table, hash_fn=hash, cmp=cmpr }) +{- + bitTwiddleSameAs takes as arguments positive Int32s less than maxBound/2 and + returns the smallest power of 2 that is greater than or equal to the + argument. + http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 +-} +bitTwiddleSameAs :: Int32 -> Int32 +bitTwiddleSameAs v0 = + let v1 = v0-1 + v2 = v1 .|. (v1`shiftR`1) + v3 = v2 .|. (v2`shiftR`2) + v4 = v3 .|. (v3`shiftR`4) + v5 = v4 .|. (v4`shiftR`8) + v6 = v5 .|. (v5`shiftR`16) + in v6+1 + +{- + powerOver takes as arguments Int32s and returns the smallest power of 2 + that is greater than or equal to the argument if that power of 2 is + within [tABLE_MIN,tABLE_MAX] +-} +powerOver :: Int32 -> Int32 +powerOver n = + if n <= tABLE_MIN + then tABLE_MIN + else if n >= tABLE_MAX + then tABLE_MAX + else bitTwiddleSameAs n + +-- | Creates a new hash table with the given minimum size. +newHint + :: (key -> key -> Bool) -- ^ @eq@: An equality comparison on keys + -> (key -> Int32) -- ^ @hash@: A hash function on keys + -> Int -- ^ @minSize@: initial table size + -> IO (HashTable key val) -- ^ Returns: an empty hash table + +newHint cmpr hash minSize = do + recordNew + -- make a new hash table with a single, empty, segment + let mask = powerOver $ fromIntegral minSize + bkts <- newMutArray (0,mask) [] + + let + kcnt = 0 + ht = HT { buckets=bkts, kcount=kcnt, bmask=mask } + + table <- newIORef ht + return (HashTable { tab=table, hash_fn=hash, cmp=cmpr }) + -- ----------------------------------------------------------------------------- -- Inserting a key\/value pair into the hash table