direct-murmur-hash (empty) → 1.0
raw patch · 4 files changed
+177/−0 lines, 4 filesdep +basedep +bytestringsetup-changed
Dependencies added: base, bytestring
Files
- Data/Digest/Murmur3.hs +120/−0
- LICENSE +22/−0
- Setup.hs +2/−0
- direct-murmur-hash.cabal +33/−0
+ Data/Digest/Murmur3.hs view
@@ -0,0 +1,120 @@+module Data.Digest.Murmur3+ (Hash,+ asByteString,+ hash)+ where++import Control.Monad+import Data.Bits+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.Word+++data Hash = Hash Word64 Word64+ deriving (Eq, Ord)+++newtype Identity a = MakeIdentity { identityAction :: a }+instance Monad Identity where+ return a = MakeIdentity a+ (>>=) x f = f $ identityAction x+++asByteString :: Hash -> ByteString+asByteString (Hash h1 h2) =+ BS.pack [fromIntegral $ shiftR h1 0 .&. 0xFF,+ fromIntegral $ shiftR h1 8 .&. 0xFF,+ fromIntegral $ shiftR h1 16 .&. 0xFF,+ fromIntegral $ shiftR h1 24 .&. 0xFF,+ fromIntegral $ shiftR h1 32 .&. 0xFF,+ fromIntegral $ shiftR h1 40 .&. 0xFF,+ fromIntegral $ shiftR h1 48 .&. 0xFF,+ fromIntegral $ shiftR h1 56 .&. 0xFF,+ fromIntegral $ shiftR h2 0 .&. 0xFF,+ fromIntegral $ shiftR h2 8 .&. 0xFF,+ fromIntegral $ shiftR h2 16 .&. 0xFF,+ fromIntegral $ shiftR h2 24 .&. 0xFF,+ fromIntegral $ shiftR h2 32 .&. 0xFF,+ fromIntegral $ shiftR h2 40 .&. 0xFF,+ fromIntegral $ shiftR h2 48 .&. 0xFF,+ fromIntegral $ shiftR h2 56 .&. 0xFF]+++hash :: ByteString -> Hash+hash input = identityAction $ do+ let c1 = 0x87c37b91114253d5+ let c2 = 0x4cf5ad432745937f+ seed = 0+ totalLength = fromIntegral $ BS.length input+ let step :: Word64 -> Word64+ -> Word64 -> Word64+ -> Identity (Word64, Word64)+ step h1 h2 k1 k2 = do+ -- First line+ k1 <- return $ k1 * c1+ k1 <- return $ rotateL k1 31+ k1 <- return $ k1 * c2+ h1 <- return $ xor h1 k1+ -- Second line+ h1 <- return $ rotateL h1 27+ h1 <- return $ h1 + h2+ h1 <- return $ h1 * 5 + 0x52dce729+ -- Third line+ k2 <- return $ k2 * c2+ k2 <- return $ rotateL k2 33+ k2 <- return $ k2 * c1+ h2 <- return $ xor h2 k2+ -- Fourth line+ h2 <- return $ rotateL h2 31+ h2 <- return $ h2 + h1+ h2 <- return $ h2 * 5 + 0x38495ab5+ return (h1, h2)+ finish :: Word64 -> Word64+ -> Word64 -> Word64+ -> Identity Hash+ finish h1 h2 k1 k2 = do+ -- First line+ k1 <- return $ k1 * c1+ k1 <- return $ rotateL k1 31+ k1 <- return $ k1 * c2+ h1 <- return $ xor h1 k1+ -- Third line+ k2 <- return $ k2 * c2+ k2 <- return $ rotateL k2 33+ k2 <- return $ k2 * c1+ h2 <- return $ xor h2 k2+ -- Finalization+ h1 <- return $ xor h1 totalLength+ h2 <- return $ xor h2 totalLength+ h1 <- mix h1+ h2 <- mix h2+ h1 <- return $ h1 + h2+ h2 <- return $ h2 + h1+ return $ Hash h1 h2+ mix :: Word64 -> Identity Word64+ mix k = do+ k <- return $ xor k (shiftR k 33)+ k <- return $ k * 0xff51afd7ed558ccd+ k <- return $ xor k (shiftR k 33)+ k <- return $ k * 0xc4ceb9fe1a85ec53+ k <- return $ xor k (shiftR k 33)+ return k+ loop :: Word64 -> Word64 -> ByteString -> Identity Hash+ loop h1 h2 input = do+ (k1, input) <- takeWord64 input+ (k2, input) <- takeWord64 input+ if BS.null input+ then finish h1 h2 k1 k2+ else do+ (h1, h2) <- step h1 h2 k1 k2+ loop h1 h2 input+ takeWord64 :: ByteString -> Identity (Word64, ByteString)+ takeWord64 input = do+ let (front, rest) = BS.splitAt 8 input+ word <- foldM (\sum (byte, offset) -> do+ return $ sum + (shiftL (fromIntegral byte) offset))+ 0+ (zip (BS.unpack front) [0, 8 .. 56])+ return (word, rest)+ loop seed seed input
+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2012 Irene Knapp++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ direct-murmur-hash.cabal view
@@ -0,0 +1,33 @@+name: direct-murmur-hash+version: 1.0+cabal-version: >= 1.12+build-type: Simple+license: BSD3+license-file: LICENSE+copyright: Copyright (c) 2013 Irene Knapp+author: Irene Knapp <irene.knapp@icloud.com>+maintainer: irene.knapp@icloud.com+homepage: http://ireneknapp.com/software/+bug-reports: https://github.com/IreneKnapp/direct-murmur-hash/issues+category: Data+synopsis: An implementation of the MurmurHash3 algorithm+description:++Source-Repository head+ type: git+ location: https://github.com/IreneKnapp/direct-murmur-hash.git++Library+ exposed-modules: Data.Digest.Murmur3+ build-depends: base >= 4.1 && < 5,+ bytestring >= 0.9.1.5 && < 1+ default-language: Haskell2010++-- Executable test+-- main-is: Main.hs+-- other-modules: Data.Digest.Murmur3+-- build-depends: base >= 4.1 && < 5,+-- bytestring >= 0.9.1.5 && < 1,+-- utf8-string >= 0.3.7 && < 1+-- default-language: Haskell2010+