hashable 1.0.1.0 → 1.0.1.1
raw patch · 7 files changed
+148/−14 lines, 7 filesnew-uploaderPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGES +15/−4
- Data/Hashable.hs +32/−4
- README.md +7/−0
- benchmarks/Benchmarks.hs +59/−0
- benchmarks/Makefile +25/−0
- cbits/hashByteString.c +1/−2
- hashable.cabal +9/−4
CHANGES view
@@ -1,4 +1,15 @@-= Version 1.0.0, 2010-08-15 =-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-* Separating Hashable class to its own package-from hashmap 1.0.0.3.+Version 1.0.1.1++* Fixed bug in Hashable instance for lazy ByteStrings where+ differences in the internal structure of the ByteString could cause+ different hash values for ByteStrings that are equal according to+ ==.++Version 1.0.1.0++* Added two helpers for creating Hashable instances: hashPtr and+ hashByteArray.++Version 1.0.0++* Separated Hashable class to its own package from hashmap 1.0.0.3.
Data/Hashable.hs view
@@ -151,8 +151,21 @@ B.unsafeUseAsCStringLen bs $ \(p, len) -> hashPtr p (fromIntegral len) -instance Hashable BL.ByteString where hash = BL.foldlChunks hashAndCombine 0+-- The arguments to this function are flipped to make the function+-- easier to use with a left fold. +-- | Compute a hash value for this 'B.ByteString', using an initial+-- salt.+hashByteStringWithSalt :: Int -- ^ salt+ -> B.ByteString -- ^ data to hash+ -> Int -- ^ hash value+hashByteStringWithSalt salt bs =+ B.inlinePerformIO $ B.unsafeUseAsCStringLen bs $ \(p, len) ->+ hashPtrWithSalt p (fromIntegral len) salt++instance Hashable BL.ByteString where+ hash = BL.foldlChunks hashByteStringWithSalt 0+ ------------------------------------------------------------------------ -- * Creating new instances @@ -192,9 +205,23 @@ hashPtr :: Ptr a -- ^ pointer to the data to hash -> Int -- ^ length, in bytes -> IO Int -- ^ hash value-hashPtr p len =- fromIntegral `fmap` hashByteString (castPtr p) (fromIntegral len)+hashPtr p len = hashPtrWithSalt p len 0 +-- | Compute a hash value for the content of this pointer, using an+-- initial salt.+--+-- This function can for example be used to hash non-contiguous+-- segments of memory as if they were one contiguous segment, by using+-- the output of one hash as the salt for the next.+hashPtrWithSalt :: Ptr a -- ^ pointer to the data to hash+ -> Int -- ^ length, in bytes+ -> Int -- ^ salt+ -> IO Int -- ^ hash value+hashPtrWithSalt p len salt =+ fromIntegral `fmap` hashCString (castPtr p) (fromIntegral len)+ (fromIntegral salt)++ #if defined(__GLASGOW_HASKELL__) -- | Compute a hash value for the content of this 'ByteArray#', -- beginning at the specified offset, using specified number of bytes.@@ -229,4 +256,5 @@ ------------------------------------------------------------------------ -- * Foreign imports -foreign import ccall unsafe hashByteString :: CString -> CInt -> IO CInt+foreign import ccall unsafe "djb_hash" hashCString+ :: CString -> CInt -> CInt -> IO CInt
+ README.md view
@@ -0,0 +1,7 @@+The hashable package+====================++This package defines a class, `Hashable`, for types that can be+converted to a hash value. This class exists for the benefit of+hashing-based data structures. The package provides instances for+basic types and a way to combine hash values.
+ benchmarks/Benchmarks.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE MagicHash, UnboxedTuples #-}++module Main (main) where++import Control.Monad.ST+import Criterion.Main+import Data.Hashable+import Foreign.ForeignPtr+import GHC.Exts+import GHC.ST (ST(..))++-- Benchmark English words (5 and 8), base64 encoded integers (11),+-- SHA1 hashes as hex (40), and large blobs (1 Mb).+main :: IO ()+main = do+ -- We do not actually care about the contents of these pointers.+ fp5 <- mallocForeignPtrBytes 5+ fp8 <- mallocForeignPtrBytes 8+ fp11 <- mallocForeignPtrBytes 11+ fp40 <- mallocForeignPtrBytes 40+ let !mb = 2^(20 :: Int) -- 1 Mb+ fp1Mb <- mallocForeignPtrBytes mb+ + -- We don't care about the contents of these either.+ let !ba5 = new 5+ !ba8 = new 8+ !ba11 = new 11+ !ba40 = new 40+ !ba1Mb = new mb+ + withForeignPtr fp5 $ \ p5 ->+ withForeignPtr fp8 $ \ p8 ->+ withForeignPtr fp11 $ \ p11 ->+ withForeignPtr fp40 $ \ p40 ->+ withForeignPtr fp1Mb $ \ p1Mb ->+ defaultMain+ [ bgroup "hashPtr"+ [ bench "5" $ hashPtr p5 5+ , bench "8" $ hashPtr p8 8+ , bench "11" $ hashPtr p11 11+ , bench "40" $ hashPtr p40 40+ , bench "2^20" $ hashPtr p1Mb mb+ ]+ , bgroup "hashByteArray"+ [ bench "5" $ whnf (hashByteArray ba5 0) 5+ , bench "8" $ whnf (hashByteArray ba8 0) 8+ , bench "11" $ whnf (hashByteArray ba11 0) 11+ , bench "40" $ whnf (hashByteArray ba40 0) 40+ , bench "2^20" $ whnf (hashByteArray ba1Mb 0) mb+ ]+ ]++data ByteArray = BA { unBA :: !ByteArray# }++new :: Int -> ByteArray#+new (I# n#) = unBA $ runST $ ST $ \s1 ->+ case newByteArray# n# s1 of+ (# s2, ary #) -> case unsafeFreezeByteArray# ary s2 of+ (# s3, ba #) -> (# s3, BA ba #)
+ benchmarks/Makefile view
@@ -0,0 +1,25 @@+package := hashable+version := $(shell awk '/^Version:/{print $$2}' ../$(package).cabal)+lib := ../dist/build/libHS$(package)-$(version).a+ghc := ghc+ghc-flags := -Wall -O -hide-all-packages \+ -package-conf ../dist/package.conf.inplace -package base \+ -package hashable -package criterion \+ -package deepseq -package ghc-prim++%.o: %.hs+ $(ghc) $(ghc-flags) -c -o $@ $<++programs := bench++.PHONY: all+all: $(programs)++bench: $(lib) Benchmarks.o+ ranlib $(lib)+ $(ghc) $(ghc-flags) -threaded -o $@ $(filter %.o,$^) $(lib)++.PHONY: clean+clean:+ -find . \( -name '*.o' -o -name '*.hi' \) -exec rm {} \;+ -rm -f $(programs)
cbits/hashByteString.c view
@@ -1,6 +1,5 @@ /* Bernstein's hash */-int hashByteString(const char* str, int len) {- int hash = 0;+int djb_hash(const char* str, int len, int hash) { while (len--) { hash = (hash * 33) ^ *str++;
hashable.cabal view
@@ -1,5 +1,5 @@ Name: hashable-Version: 1.0.1.0+Version: 1.0.1.1 Synopsis: A class for types that can be converted to a hash value Description: This package defines a class, 'Hashable', for types that can be converted to a hash value. This class@@ -16,8 +16,11 @@ Category: Data Build-type: Simple Cabal-version: >=1.10-Extra-source-files: CHANGES-+-- tests/Properties.hs shouldn't have to go here, but the source files+-- for the test-suite stanzas don't get picked up by `cabal sdist`.+Extra-source-files:+ CHANGES, README.md, tests/Properties.hs, benchmarks/Benchmarks.hs+ benchmarks/Makefile Library Default-language: Haskell98@@ -27,6 +30,8 @@ C-sources: cbits/hashByteString.c Ghc-options: -Wall+ if impl(ghc >= 6.8)+ Ghc-options: -fwarn-tabs Test-suite tests Default-language: Haskell98@@ -42,4 +47,4 @@ source-repository head type: git- location: http://github.com/tibbe/hashable.git+ location: https://github.com/tibbe/hashable.git