murmur-hash-0.1.0.6/0000755000000000000000000000000012026324521012307 5ustar0000000000000000murmur-hash-0.1.0.6/LICENSE0000644000000000000000000000273612026324521013324 0ustar0000000000000000Copyright (c) 2010, Thomas Schilling All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. murmur-hash-0.1.0.6/murmur-hash.cabal0000644000000000000000000000167512026324521015554 0ustar0000000000000000Name: murmur-hash Version: 0.1.0.6 License: BSD3 License-File: LICENSE Author: Thomas Schilling Maintainer: Thomas Schilling Homepage: http://github.com/nominolo/murmur-hash Synopsis: MurmurHash2 implementation for Haskell. Description: Implements MurmurHash2, a good, fast, general-purpose, non-cryptographic hashing function. See for details. . This implementation is pure Haskell, so it might be a bit slower than a C FFI binding. Category: Data, Digest Stability: provisional Build-Type: Simple Cabal-Version: >= 1.6 Library Build-Depends: base >= 3.0 && < 4.7, bytestring >= 0.9 && < 0.11 exposed-modules: Data.Digest.Murmur32 Data.Digest.Murmur64 Source-repository head Type: git Location: git://github.com/nominolo/murmur-hash.git murmur-hash-0.1.0.6/Setup.hs0000644000000000000000000000012512026324521013741 0ustar0000000000000000#!/usr/bin/env runhaskell import Distribution.Simple main :: IO () main = defaultMainmurmur-hash-0.1.0.6/Data/0000755000000000000000000000000012026324521013160 5ustar0000000000000000murmur-hash-0.1.0.6/Data/Digest/0000755000000000000000000000000012026324521014377 5ustar0000000000000000murmur-hash-0.1.0.6/Data/Digest/Murmur64.hs0000644000000000000000000001271512026324521016402 0ustar0000000000000000{-# LANGUAGE FlexibleInstances, BangPatterns #-} {-| Module : Data.Digest.Murmur64 Copyright : (c) Thomas Schilling 2010 License : BSD-style Maintainer : nominolo@gmail.com Stability : experimental Portability : portable Type class and primitives for constructing 64 bit hashes using the MurmurHash2 algorithm. See for details on MurmurHash2. -} module Data.Digest.Murmur64 ( Hash64, asWord64, Hashable64(..), hash64AddWord64, hash64AddInt, hash64, hash64WithSeed, combine, ) where import Data.Word import Numeric ( showHex ) import Data.Bits import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import Data.Char ( ord ) import Data.Foldable import Data.List ( unfoldr ) -- | A 64 bit hash. newtype Hash64 = Hash64 Word64 deriving (Eq, Ord, Bounded) instance Show Hash64 where showsPrec _ (Hash64 w) = showString "Hash64 0x" . showHex w -- | Extract 64 bit word from hash. asWord64 :: Hash64 -> Word64 asWord64 (Hash64 w) = w class Hashable64 a where hash64Add :: a -> Hash64 -> Hash64 murmur_m :: Word64 murmur_m = 0xc6a4a7935bd1e995 murmur_r :: Int murmur_r = 47 -- | Add a 64 bit word to the hash. hash64AddWord64 :: Word64 -> Hash64 -> Hash64 hash64AddWord64 k (Hash64 h) = let k1 = k * murmur_m k2 = k1 `xor` (k1 `shiftR` murmur_r) k3 = k2 * murmur_m h1 = h * murmur_m h2 = h1 `xor` k3 in Hash64 h2 hash64AddInt :: Int -> Hash64 -> Hash64 hash64AddInt !k0 = hash64AddWord64 (fromIntegral k0) hash64AddFoldable :: (Hashable64 a, Foldable c) => c a -> Hash64 -> Hash64 hash64AddFoldable c !h0 = foldl' f h0 c where f h a = hash64Add a h -- | Create a hash using a custom seed. --h -- The seed should be non-zero, but other than that can be an -- arbitrary number. Different seeds will give different hashes, and -- thus (most likely) different hash collisions. hash64WithSeed :: Hashable64 a => Word64 -> a -> Hash64 hash64WithSeed seed a = hash64End (hash64Add a (Hash64 seed)) -- | Create a hash using the default seed. hash64 :: Hashable64 a => a -> Hash64 hash64 = hash64WithSeed defaultSeed -- | Combine two hash generators. E.g., -- -- @ -- hashFoo (Foo a) = hash64AddInt 1 `combine` hash64Add a -- @ combine :: (Hash64 -> Hash64) -> (Hash64 -> Hash64) -> (Hash64 -> Hash64) combine x y = y . x hash64End :: Hash64 -> Hash64 hash64End (Hash64 h) = let h1 = h `xor` (h `shiftR` murmur_r) h2 = h1 * murmur_m h3 = h2 `xor` (h2 `shiftR` murmur_r) in Hash64 h3 defaultSeed :: Word64 defaultSeed = 0xdeadbeef -- not 0, otherwise hash64 [0] == hash64 [] {- On a CPU with two multipliers and two ALUs, Murmur2 can process one word in every two cycles + set up (2 cycles) and finish (3 cycles). Here's the data flow graph: @ h k1 k2 k3 ... | | | | | * m | | | |\ | | | | >> r | | | / | | | xor * | | | |\ | * m * m | >> r \ / |/ | xor xor * m \ / |\ * m * m | >> r \ / |/ xor xor \ / * m * m \ / xor \ ... @ -} -- ------------------------------------------------------------------- -- Instances instance Hashable64 Char where hash64Add c = hash64AddInt (ord c) instance Hashable64 Int where hash64Add = hash64AddInt instance Hashable64 Word64 where hash64Add = hash64AddWord64 instance Hashable64 a => Hashable64 [a] where hash64Add = hash64AddFoldable instance Hashable64 Integer where -- Within Int range, make sure they hash to exactly the same value hash64Add i0 | i0 >= fromIntegral (minBound :: Int) && i0 <= fromIntegral (maxBound :: Int) = hash64AddInt (fromIntegral i0) | otherwise -- Prefix by sign, then hash the raw data words, starting with LSB = hash64Add (signum i0 > 0) `combine` hash64AddFoldable (unfoldr f (abs i0) :: [Word64]) where f i | i == 0 = Nothing f i = let (i', a) = quotRem i maxWord in Just (fromIntegral a, i') maxWord = fromIntegral (maxBound :: Word64) + 1 :: Integer instance Hashable64 Bool where hash64Add False = hash64AddWord64 1 hash64Add True = hash64AddWord64 2 instance Hashable64 a => Hashable64 (Maybe a) where hash64Add Nothing = hash64AddWord64 3 hash64Add (Just a) = hash64AddWord64 4 `combine` hash64Add a instance (Hashable64 a, Hashable64 b) => Hashable64 (Either a b) where hash64Add (Left a) = hash64AddWord64 5 `combine` hash64Add a hash64Add (Right b) = hash64AddWord64 6 `combine` hash64Add b instance Hashable64 () where hash64Add () = hash64AddWord64 7 instance (Hashable64 a, Hashable64 b) => Hashable64 (a, b) where hash64Add (a, b) = hash64Add a `combine` hash64Add b instance (Hashable64 a, Hashable64 b, Hashable64 c) => Hashable64 (a, b, c) where hash64Add (a, b, c) = hash64Add a `combine` hash64Add b `combine` hash64Add c instance (Hashable64 a, Hashable64 b, Hashable64 c, Hashable64 d) => Hashable64 (a, b, c, d) where hash64Add (a, b, c, d) = hash64Add a `combine` hash64Add b `combine` hash64Add c `combine` hash64Add d instance Hashable64 B.ByteString where hash64Add = B.foldl go (hash64AddWord64 8) where go acc b = acc `combine` hash64AddWord64 (fromIntegral b) instance Hashable64 L.ByteString where hash64Add = L.foldl go (hash64AddWord64 9) where go acc b = acc `combine` hash64AddWord64 (fromIntegral b) murmur-hash-0.1.0.6/Data/Digest/Murmur32.hs0000644000000000000000000001317612026324521016377 0ustar0000000000000000{-# LANGUAGE FlexibleInstances, BangPatterns #-} {-| Module : Data.Digest.Murmur32 Copyright : (c) Thomas Schilling 2010 License : BSD-style Maintainer : nominolo@gmail.com Stability : experimental Portability : portable Type class and primitives for constructing 32 bit hashes using the MurmurHash2 algorithm. See for details on MurmurHash2. -} module Data.Digest.Murmur32 ( Hash32, asWord32, Hashable32(..), hash32AddWord32, hash32AddInt, hash32, hash32WithSeed ) where import Data.Word import Numeric ( showHex ) import Data.Bits import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import Data.Char ( ord ) import Data.Foldable import Data.List ( unfoldr ) -- | A 32 bit hash. newtype Hash32 = Hash32 Word32 deriving (Eq, Ord, Bounded) instance Show Hash32 where showsPrec _ (Hash32 w) = showString "Hash32 0x" . showHex w -- | Extract 32 bit word from hash. asWord32 :: Hash32 -> Word32 asWord32 (Hash32 w) = w -- | Instance for class Hashable32 a where hash32Add :: a -> Hash32 -> Hash32 murmur_m :: Word32 murmur_m = 0x5bd1e995 murmur_r :: Int murmur_r = 24 hash32AddWord32 :: Word32 -> Hash32 -> Hash32 hash32AddWord32 k (Hash32 h) = let k1 = k * murmur_m k2 = k1 `xor` (k1 `shiftR` murmur_r) k3 = k2 * murmur_m h1 = h * murmur_m h2 = h1 `xor` k3 in Hash32 h2 hash32AddInt :: Int -> Hash32 -> Hash32 hash32AddInt !k0 | bitSize (undefined :: Int) <= 32 -- Int is 32 bits = hash32AddWord32 (fromIntegral k0) | otherwise -- Int is 64 bits = hash32AddWord32 (fromIntegral k0) `combine` hash32AddWord32 (fromIntegral (k0 `shiftR` 32)) hash32AddFoldable :: (Hashable32 a, Foldable c) => c a -> Hash32 -> Hash32 hash32AddFoldable c !h0 = foldl' f h0 c where f h a = hash32Add a h -- | Create a hash using a custom seed. -- -- The seed should be non-zero, but other than that can be an -- arbitrary number. Different seeds will give different hashes, and -- thus (most likely) different hash collisions. hash32WithSeed :: Hashable32 a => Word32 -> a -> Hash32 hash32WithSeed seed a = hash32End (hash32Add a (Hash32 seed)) -- | Create a hash using the default seed. hash32 :: Hashable32 a => a -> Hash32 hash32 = hash32WithSeed defaultSeed -- | Combine two hash generators. E.g., -- -- @ -- hashFoo (Foo a) = hash32AddInt 1 `combine` hash32Add a -- @ combine :: (Hash32 -> Hash32) -> (Hash32 -> Hash32) -> (Hash32 -> Hash32) combine x y = y . x hash32End :: Hash32 -> Hash32 hash32End (Hash32 h) = let h1 = h `xor` (h `shiftR` 13) h2 = h1 * murmur_m h3 = h2 `xor` (h2 `shiftR` 15) in Hash32 h3 defaultSeed :: Word32 defaultSeed = 0xdeadbeef -- not 0, otherwise hash32 [0] == hash32 [] {- On a CPU with two multipliers and two ALUs, Murmur2 can process one word in every two cycles + set up (2 cycles) and finish (3 cycles). Here's the data flow graph: @ h k1 k2 k3 ... | | | | | * m | | | |\ | | | | >> r | | | / | | | xor * | | | |\ | * m * m | >> r \ / |/ | xor xor * m \ / |\ * m * m | >> r \ / |/ xor xor \ / * m * m \ / xor \ ... @ -} -- ------------------------------------------------------------------- -- Instances instance Hashable32 Char where hash32Add c = hash32AddInt (ord c) instance Hashable32 Int where hash32Add = hash32AddInt instance Hashable32 Word32 where hash32Add = hash32AddWord32 instance Hashable32 a => Hashable32 [a] where hash32Add = hash32AddFoldable instance Hashable32 Integer where -- Within Int range, make sure they hash to exactly the same value hash32Add i0 | i0 >= fromIntegral (minBound :: Int) && i0 <= fromIntegral (maxBound :: Int) = hash32AddInt (fromIntegral i0) | otherwise -- Prefix by sign, then hash the raw data words, starting with LSB = hash32Add (signum i0 > 0) `combine` hash32AddFoldable (unfoldr f (abs i0) :: [Word32]) where f i | i == 0 = Nothing f i = let (i', a) = quotRem i maxWord in Just (fromIntegral a, i') maxWord = fromIntegral (maxBound :: Word32) + 1 :: Integer instance Hashable32 Bool where hash32Add False = hash32AddWord32 1 hash32Add True = hash32AddWord32 2 instance Hashable32 a => Hashable32 (Maybe a) where hash32Add Nothing = hash32AddWord32 3 hash32Add (Just a) = hash32AddWord32 4 `combine` hash32Add a instance (Hashable32 a, Hashable32 b) => Hashable32 (Either a b) where hash32Add (Left a) = hash32AddWord32 5 `combine` hash32Add a hash32Add (Right b) = hash32AddWord32 6 `combine` hash32Add b instance Hashable32 () where hash32Add () = hash32AddWord32 7 instance (Hashable32 a, Hashable32 b) => Hashable32 (a, b) where hash32Add (a, b) = hash32Add a `combine` hash32Add b instance (Hashable32 a, Hashable32 b, Hashable32 c) => Hashable32 (a, b, c) where hash32Add (a, b, c) = hash32Add a `combine` hash32Add b `combine` hash32Add c instance (Hashable32 a, Hashable32 b, Hashable32 c, Hashable32 d) => Hashable32 (a, b, c, d) where hash32Add (a, b, c, d) = hash32Add a `combine` hash32Add b `combine` hash32Add c `combine` hash32Add d instance Hashable32 B.ByteString where hash32Add = B.foldl go (hash32AddWord32 8) where go acc b = acc `combine` hash32AddWord32 (fromIntegral b) instance Hashable32 L.ByteString where hash32Add = L.foldl go (hash32AddWord32 9) where go acc b = acc `combine` hash32AddWord32 (fromIntegral b)