X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Data%2FHashTable.hs;h=9fbe7353c19ca0362e6bcee0b7f93fe8b1a72f19;hb=b8ac498face4c8b16c06d30fbc86666b7dc28173;hp=917daab56d5d3247233a11639e02c4d53c6f42ee;hpb=2f5bf602269f058edb24c9e5010c5a288fd7e5b7;p=ghc-base.git diff --git a/Data/HashTable.hs b/Data/HashTable.hs index 917daab..9fbe735 100644 --- a/Data/HashTable.hs +++ b/Data/HashTable.hs @@ -1,3 +1,5 @@ +{-# OPTIONS -fno-implicit-prelude #-} + ----------------------------------------------------------------------------- -- | -- Module : Data.HashTable @@ -23,29 +25,55 @@ module Data.HashTable ( -- * Hash functions -- $hash_functions hashInt, hashString, + prime, -- * Diagnostics longestChain ) where -import Data.Char ( ord ) -import Data.Int ( Int32 ) -import Data.Array.IO -import Data.Array.Base -import Data.List ( maximumBy ) -import Data.IORef +-- This module is imported by Data.Dynamic, which is pretty low down in the +-- module hierarchy, so don't import "high-level" modules + +#ifdef __GLASGOW_HASKELL__ +import GHC.Base +#else +import Prelude hiding ( lookup ) +#endif +import Data.Tuple ( fst ) import Data.Bits -import Control.Monad ( when ) -import Prelude hiding (lookup) ---import Debug.Trace +import Data.Maybe +import Data.List ( maximumBy, filter, length, concat ) +import Data.Int ( Int32 ) + +#if defined(__GLASGOW_HASKELL__) +import GHC.Num +import GHC.Real ( Integral(..), fromIntegral ) + +import GHC.IOBase ( IO, IOArray, newIOArray, readIOArray, writeIOArray, + unsafeReadIOArray, unsafeWriteIOArray, + IORef, newIORef, readIORef, writeIORef ) +import GHC.Err ( undefined ) +#else +import Data.Char ( ord ) +import Data.IORef ( IORef, newIORef, readIORef, writeIORef ) +# if defined(__HUGS__) +import Hugs.IOArray ( IOArray, newIOArray, readIOArray, writeIOArray, + unsafeReadIOArray, unsafeWriteIOArray ) +# elif defined(__NHC__) +import NHC.IOExtras ( IOArray, newIOArray, readIOArray, writeIOArray) +# endif +#endif +import Control.Monad ( when, mapM, sequence_ ) + +----------------------------------------------------------------------- myReadArray :: IOArray Int32 a -> Int32 -> IO a myWriteArray :: IOArray Int32 a -> Int32 -> a -> IO () -#ifdef DEBUG -myReadArray = readArray -myWriteArray = writeArray +#if defined(DEBUG) || defined(__NHC__) +myReadArray = readIOArray +myWriteArray = writeIOArray #else -myReadArray arr i = unsafeRead arr (fromIntegral i) -myWriteArray arr i x = unsafeWrite arr (fromIntegral i) x +myReadArray arr i = unsafeReadIOArray arr (fromIntegral i) +myWriteArray arr i x = unsafeWriteIOArray arr (fromIntegral i) x #endif -- | A hash table mapping keys of type @key@ to values of type @val@. @@ -128,8 +156,9 @@ hashString :: String -> Int32 hashString = fromIntegral . foldr f 0 where f c m = ord c + (m * 128) `rem` fromIntegral prime --- a prime larger than the maximum hash table size -prime = 1500007 :: Int32 +-- | A prime larger than the maximum hash table size +prime :: Int32 +prime = 1500007 -- ----------------------------------------------------------------------------- -- Parameters @@ -146,16 +175,20 @@ hLOAD = 4 :: Int32 -- Maximum average load of a single hash bucket -- ----------------------------------------------------------------------------- -- Creating a new hash table --- | Creates a new hash table +-- | Creates a new hash table. The following property should hold for the @eq@ +-- and @hash@ functions passed to 'new': +-- +-- > eq A B => hash A == hash B +-- new - :: (key -> key -> Bool) -- ^ An equality comparison on keys - -> (key -> Int32) -- ^ A hash function on keys + :: (key -> key -> Bool) -- ^ @eq@: An equality comparison on keys + -> (key -> Int32) -- ^ @hash@: A hash function on keys -> IO (HashTable key val) -- ^ Returns: an empty hash table new cmp hash_fn = do -- make a new hash table with a single, empty, segment - dir <- newArray (0,dIR_SIZE) undefined - segment <- newArray (0,sEGMENT_SIZE-1) [] + dir <- newIOArray (0,dIR_SIZE) undefined + segment <- newIOArray (0,sEGMENT_SIZE-1) [] myWriteArray dir 0 segment let @@ -231,7 +264,7 @@ expandHashTable newindex = newbucket .&. sEGMENT_MASK -- when (newindex == 0) $ - do segment <- newArray (0,sEGMENT_SIZE-1) [] + do segment <- newIOArray (0,sEGMENT_SIZE-1) [] myWriteArray dir newsegment segment -- let table' =