Dish 0.0.0.4 → 0.0.0.5
raw patch · 3 files changed
+83/−27 lines, 3 filesdep +Dishdep ~basenew-component:exe:Dish
Dependencies added: Dish
Dependency ranges changed: base
Files
- Dish.cabal +15/−5
- examples/Main.hs +28/−0
- src/Data/Dish/Murmur3.hs +40/−22
Dish.cabal view
@@ -1,5 +1,5 @@ name: Dish-version: 0.0.0.4+version: 0.0.0.5 homepage: http://github.com/zcourts/Dish license: BSD3 license-file: LICENSE@@ -22,11 +22,21 @@ build-depends: base >=4.6.0 && <4.7, bytestring >=0.10.0 && <0.11- hs-source-dirs: src+ hs-source-dirs: src, examples c-sources: cbits/murmur3.c include-dirs: cbits- extra-libraries: - --cc-options: -O3+ extra-libraries: extensions: ForeignFunctionInterface- other-modules: + other-modules: exposed-modules: Data.Dish.Murmur3++executable Dish+ build-depends: base >= 4,+ bytestring >=0.10.0 && <0.11,+ Dish >= 0.0.0.5+ hs-source-dirs: examples+ ghc-options: -Wall -rtsopts+ c-sources: cbits/murmur3.c+ include-dirs: cbits+ main-is: Main.hs+
+ examples/Main.hs view
@@ -0,0 +1,28 @@+module Main where+import Data.Dish.Murmur3+import qualified Data.ByteString.Char8 as B++main :: IO ()+main = do let val = Str "abc 123"+ let valByteString = B.pack $ strCon val+ print $ murmur3Int val 42+ print $ murmur3IntegerX86 val 42+ print $ murmur3IntegerX64 valByteString 42+ --+ d <- murmur3Raw valByteString 42 X86_32+ print d+ e <- murmur3Raw val 42 X86_128+ print e+ f <- murmur3Raw val 42 X64_128+ print f+ --+ print $ murmur3 val 42 X86_32+ print $ murmur3 valByteString 42 X86_128+ print $ murmur3 val 42 X64_128+ --+ j <- murmur3Int' val 42+ print j+ k <- murmur3IntegerX86' val 42+ print k+ l <- murmur3IntegerX64' valByteString 42+ print l
src/Data/Dish/Murmur3.hs view
@@ -9,6 +9,12 @@ and about the speed of unaligned reads. -} module Data.Dish.Murmur3(+ -- * Murmur3 Hash Version+ MHV(..),+ -- * Hashable+ -- If a value can be represented as a 'CString' then it can be hashed+ Murmur3Hashable(..),+ Str(..), -- * Default/Direct Map -- $default murmur3,@@ -26,32 +32,44 @@ murmur3IntegerX64, murmur3IntegerX64', -- * FFI- murmur3Raw,- -- * Murmur3 Hash Version- MHV(..)+ murmur3Raw ) where import Foreign.C import Foreign.Ptr import Foreign import qualified Data.List as L-import qualified Data.Bits as B+import qualified Data.Bits as BITS import qualified System.IO.Unsafe as US+import qualified Data.ByteString as B -- Murmur Hash version, one of data MHV = X86_32 | X86_128 | X64_128 +--http://www.haskell.org/haskellwiki/List_instance+-- | Because String isn't a \'real\' type :(+newtype Str = Str{ strCon :: String } +-- | Provides an interface for any value which is capable of being represented as a 'CString'+class Murmur3Hashable a where+ toCstring :: a -> IO CStringLen+ +instance Murmur3Hashable Str where+ toCstring val = withCAStringLen (strCon val) $ \x -> return x+ +instance Murmur3Hashable B.ByteString where+ toCstring val = B.useAsCStringLen val $ \x -> return x + {-$default Simple, verbose interface for generating hashes -} -- | Base function, which allows you to choose which 'MHV' to use -murmur3 :: String -- ^ The string to be hashed+murmur3 :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function -> MHV -- ^ Which Murmur Hash version to use 'X86_32', 'X86_128' or 'X64_128' -> [Int] -- ^ returns 4, 32 bit ints, if 'X86_32' is used only the first has a value and the other 3 are 0 murmur3 v s ver = US.unsafePerformIO $ murmur3' v s ver -murmur3' :: String -- ^ The string to be hashed+murmur3' :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function -> MHV -- ^ Which Murmur Hash version to use 'X86_32', 'X86_128' or 'X64_128' -> IO [Int] -- ^ returns 4, 32 bit ints, if 'X86_32' is used only the first has a value and the other 3 are 0@@ -68,9 +86,9 @@ {-$32 Generate 32 bit hash values -} -murmur3Int' :: String -- ^ The string to be hashed+murmur3Int' :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function- -> IO Int -- ^ 32 bit number generated from the string+ -> IO Int -- ^ 32 bit number generated from the hashable murmur3Int' val seed = do v <- murmur3Raw val seed X86_32 -- safe to use L.head, list is never empty even if all vals are 0 return $ fromIntegral (L.head v)@@ -78,18 +96,18 @@ {- | has the lowest throughput, but also the lowest latency. If you're making a hash table that usually has small keys, this is probably the one you want to use on 32-bit machines. It has a 32-bit output. -} -murmur3Int :: String -- ^ The string to be hashed+murmur3Int :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function- -> Int -- ^ 32 bit number generated from the string+ -> Int -- ^ 32 bit number generated from the hashable murmur3Int val seed = US.unsafePerformIO $ murmur3Int' val seed {-$x128 Generate 128 bit hash values, optimized for 32 bit systems -}-murmur3IntegerX86' :: String -- ^ The string to be hashed+murmur3IntegerX86' :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function- -> IO Integer -- ^ 128 bit number generated from the string+ -> IO Integer -- ^ 128 bit number generated from the hashable murmur3IntegerX86' val seed = x128 val seed X86_128 {- | Generate a 128 bit hash from the given value, this function's implementation @@ -97,17 +115,17 @@ Has about 30% higher throughput than 'murmur3Int'. Be warned, though, that its latency for a single 16-byte key is about 86% longer! -}-murmur3IntegerX86 :: String -- ^ The string to be hashed+murmur3IntegerX86 :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function- -> Integer -- ^ 128 bit number generated from the string+ -> Integer -- ^ 128 bit number generated from the hashable murmur3IntegerX86 val seed = US.unsafePerformIO $ murmur3IntegerX86' val seed {-$64_128 Generate 128 bit hash values, optimized for 64 bit systems -}-murmur3IntegerX64' :: String -- ^ The string to be hashed+murmur3IntegerX64' :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function- -> IO Integer -- ^ 128 bit number generated from the string+ -> IO Integer -- ^ 128 bit number generated from the hashable murmur3IntegerX64' val seed = x128 val seed X64_128 {- | Generate a 128 bit hash from the given value, this function's implementation @@ -115,9 +133,9 @@ Its throughput is 250% higher than 'murmur3IntegerX86', but it has roughly the same latency. -}-murmur3IntegerX64 :: String -- ^ The string to be hashed+murmur3IntegerX64 :: Murmur3Hashable a => a -- ^ The hashable to be hashed -> Int -- ^ A seed value for the hash function- -> Integer -- ^ 128 bit number generated from the string+ -> Integer -- ^ 128 bit number generated from the hashable murmur3IntegerX64 val seed = US.unsafePerformIO $ murmur3IntegerX64' val seed foreign import ccall "MurmurHash3_x86_32" c_x86_32@@ -130,9 +148,9 @@ :: CString -> CInt -> CUInt -> Ptr CUInt -> IO () -- | all murmur functions use this and manipulate its response to return a different format -murmur3Raw :: String -> Int -> MHV -> IO [CUInt]+murmur3Raw :: Murmur3Hashable a => a -> Int -> MHV -> IO [CUInt] murmur3Raw val seed ver = do- val' <- withCAStringLen val $ \x -> return x+ val' <- toCstring val let cstr = strFromCStr val' let strLength = strLFromCStr val' outPtr <- mallocArray arrSize@@ -149,7 +167,7 @@ doHash X86_128 v s se o = c_x86_128 v s se o doHash X64_128 v s se o = c_x64_128 v s se o -x128 :: String -> Int -> MHV -> IO Integer+x128 :: Murmur3Hashable a => a -> Int -> MHV -> IO Integer x128 val seed ver= do v <- hash ver return $ twiddle 0 v @@ -160,4 +178,4 @@ twiddle :: Integer -> [CUInt] -> Integer twiddle i [] = i twiddle i (0:xs) = twiddle i xs -- don't shift when val is 0- twiddle i (x:xs) = twiddle (B.shift i (B.bitSize x) `B.xor` fromIntegral x) xs+ twiddle i (x:xs) = twiddle (BITS.shift i (BITS.bitSize x) `BITS.xor` fromIntegral x) xs