packages feed

bloomfilter 1.2.3 → 1.2.4

raw patch · 7 files changed

+421/−137 lines, 7 filesdep +parallelPVP ok

version bump matches the API change (PVP)

Dependencies added: parallel

API changes (from Hackage documentation)

+ Data.BloomFilter: instance NFData (Bloom a)

Files

Data/BloomFilter.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE Rank2Types, TypeOperators #-}+{-# LANGUAGE BangPatterns, Rank2Types, TypeOperators #-} {-# OPTIONS_GHC -fglasgow-exts #-}  -- |@@ -89,6 +89,7 @@  import Control.Monad (liftM, forM_) import Control.Monad.ST (ST, runST)+import Control.Parallel.Strategies (NFData(..)) import Data.Array.Base (unsafeAt, unsafeRead, unsafeWrite) import Data.Array.ST (STUArray, thaw, unsafeFreeze) import Data.Array.Unboxed (UArray)@@ -135,6 +136,9 @@  instance Show (Bloom a) where     show ub = "Bloom { " ++ show (lengthB ub) ++ " bits } "++instance NFData (Bloom a) where+    rnf !_ = ()  -- | Create a new mutable Bloom filter.  For efficiency, the number of -- bits used may be larger than the number requested.  It is always
Data/BloomFilter/Easy.hs view
@@ -27,7 +27,7 @@     , suggestSizing     ) where -import Data.BloomFilter (Bloom, elemB, emptyB, fromListB, lengthB, notElemB)+import Data.BloomFilter (Bloom, elemB, fromListB, lengthB, notElemB) import Data.BloomFilter.Hash (Hashable, cheapHashes) import Data.BloomFilter.Util (nextPowerOfTwo) import qualified Data.ByteString as SB@@ -43,7 +43,6 @@ {-# SPECIALIZE easyList :: Double -> [String] -> Bloom String #-} {-# SPECIALIZE easyList :: Double -> [LB.ByteString] -> Bloom LB.ByteString #-} {-# SPECIALIZE easyList :: Double -> [SB.ByteString] -> Bloom SB.ByteString #-}-{-# INLINE easyList #-} easyList errRate xs = fromListB (cheapHashes numHashes) numBits xs     where capacity = length xs           (numBits, numHashes)
Data/BloomFilter/Hash.hs view
@@ -42,12 +42,15 @@ import Data.List (unfoldr) import Data.Int (Int8, Int16, Int32, Int64) import Data.Word (Word8, Word16, Word32, Word64)+import Foreign.C.String (CString) import Foreign.C.Types (CInt, CSize)-import Foreign.Marshal.Array (withArrayLen)-import Foreign.Marshal.Utils (with)-import Foreign.Ptr (Ptr, castPtr, plusPtr)-import Foreign.Storable (Storable, peek, sizeOf)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Marshal.Array (allocaArray, withArrayLen)+import Foreign.Ptr (Ptr, castPtr, nullPtr, plusPtr)+import Foreign.Storable (Storable, peek, poke, sizeOf) import System.IO.Unsafe (unsafePerformIO)+import Data.ByteString.Internal (ByteString(..)) import qualified Data.ByteString as SB import qualified Data.ByteString.Lazy.Internal as LB import qualified Data.ByteString.Lazy as LB@@ -101,18 +104,14 @@            -> a                 -- ^ value to hash            -> Word32 {-# INLINE hashSalt32 #-}-hashSalt32 salt k =-    let !r = unsafePerformIO $ hashIO32 k salt-    in r+hashSalt32 salt k = unsafePerformIO $ hashIO32 k salt  -- | Compute a salted 64-bit hash. hashSalt64 :: Hashable a => Word64  -- ^ salt            -> a                 -- ^ value to hash            -> Word64 {-# INLINE hashSalt64 #-}-hashSalt64 salt k =-    let !r = unsafePerformIO $ hashIO64 k salt-    in r+hashSalt64 salt k = unsafePerformIO $ hashIO64 k salt  -- | Compute a list of 32-bit hashes.  The value to hash may be -- inspected as many times as there are hashes requested.@@ -230,38 +229,46 @@ cast32 :: CInt -> IO Word32 cast32 = return . fromIntegral +-- Inlined from Foreign.Marshal.Utils, for performance reasons.+with :: Storable a => a -> (Ptr a -> IO b) -> IO b+with val f  =+  alloca $ \ptr -> do+    poke ptr val+    f ptr+ alignedHash2 :: Ptr a -> CSize -> Word64 -> IO Word64 alignedHash2 ptr bytes salt =     with (fromIntegral salt) $ \sp -> do       let p1 = castPtr sp           p2 = castPtr sp `plusPtr` 4-      go p1 p2+      doubleHash ptr bytes p1 p2       peek sp-  where go p1 p2++doubleHash :: Ptr a -> CSize -> Ptr CInt -> Ptr CInt -> IO ()+doubleHash ptr bytes p1 p2           | bytes .&. 3 == 0 = hashWord2 (castPtr ptr) (div4 bytes) p1 p2           | otherwise        = hashLittle2 ptr bytes p1 p2  instance Hashable SB.ByteString where-    hashIO32 bs salt = SB.useAsCStringLen bs $ \(ptr, len) -> do-                     alignedHash ptr (fromIntegral len) salt+    hashIO32 bs salt = unsafeUseAsCStringLen bs $ \ptr len ->+                       alignedHash ptr (fromIntegral len) salt      {-# INLINE hashIO64 #-}-    hashIO64 bs salt = SB.useAsCStringLen bs $ \(ptr, len) -> do-                      alignedHash2 ptr (fromIntegral len) salt+    hashIO64 bs salt = unsafeUseAsCStringLen bs $ \ptr len ->+                       alignedHash2 ptr (fromIntegral len) salt  rechunk :: LB.ByteString -> [SB.ByteString] rechunk s | LB.null s = []           | otherwise = let (pre,suf) = LB.splitAt chunkSize s                         in  repack pre : rechunk suf-           where repack = SB.concat . LB.toChunks-                 chunkSize = fromIntegral LB.defaultChunkSize+    where repack    = SB.concat . LB.toChunks+          chunkSize = fromIntegral LB.defaultChunkSize  instance Hashable LB.ByteString where     hashIO32 bs salt = foldM (flip hashIO32) salt (rechunk bs)      {-# INLINE hashIO64 #-}-    hashIO64 bs salt = foldM go salt (rechunk bs)-        where go a s = hashIO64 s a+    hashIO64 = hashChunks  instance Hashable a => Hashable (Maybe a) where     hashIO32 Nothing salt = return salt@@ -319,3 +326,55 @@ hashList64 xs salt =     withArrayLen xs $ \len ptr ->         alignedHash2 ptr (fromIntegral (len * sizeOf (head xs))) salt++unsafeUseAsCStringLen :: SB.ByteString -> (CString -> Int -> IO a) -> IO a+unsafeUseAsCStringLen (PS fp o l) action =+    withForeignPtr fp $ \p -> action (p `plusPtr` o) l++type HashState = Ptr Word32++foreign import ccall unsafe "lookup3.h _jenkins_little2_begin" c_begin+    :: Ptr Word32 -> Ptr Word32 -> HashState -> IO ()++foreign import ccall unsafe "lookup3.h _jenkins_little2_frag" c_frag+    :: Ptr a -> CSize -> HashState -> CSize -> IO CSize++foreign import ccall unsafe "lookup3.h _jenkins_little2_step" c_step+    :: Ptr a -> CSize -> HashState -> IO CSize++foreign import ccall unsafe "lookup3.h _jenkins_little2_end" c_end+    :: CInt -> Ptr Word32 -> Ptr Word32 -> HashState -> IO ()++unsafeAdjustCStringLen :: SB.ByteString -> Int -> (CString -> Int -> IO a)+                       -> IO a+unsafeAdjustCStringLen (PS fp o l) d action+  | d > l     = action nullPtr 0+  | otherwise = withForeignPtr fp $ \p -> action (p `plusPtr` (o + d)) (l - d)++hashChunks :: LB.ByteString -> Word64 -> IO Word64+hashChunks s salt = do+    with (fromIntegral salt) $ \sp -> do+      let p1 = castPtr sp+          p2 = castPtr sp `plusPtr` 4+      allocaArray 3 $ \st -> do+        let step :: LB.ByteString -> Int -> IO Int+            step (LB.Chunk x xs) off = do+              unread <- unsafeAdjustCStringLen x off $ \ptr len ->+                        c_step ptr (fromIntegral len) st+              if unread > 0+                then frag xs unread+                else step xs 0+            step _ _ = return 0++            frag :: LB.ByteString -> CSize -> IO Int+            frag c@(LB.Chunk x xs) stoff = do+              nstoff <- unsafeUseAsCStringLen x $ \ptr len -> do+                c_frag ptr (fromIntegral len) st stoff+              if nstoff == 12+                then step c (fromIntegral (nstoff - stoff))+                else frag xs nstoff+            frag LB.Empty stoff = return (fromIntegral (12 - stoff))+        c_begin p1 p2 st +        unread <- step s 0+        c_end (fromIntegral unread) p1 p2 st+      peek sp
bloomfilter.cabal view
@@ -1,5 +1,5 @@ name:            bloomfilter-version:         1.2.3+version:         1.2.4 license:         BSD3 license-file:    LICENSE author:          Bryan O'Sullivan <bos@serpentine.com>@@ -28,7 +28,7 @@     build-depends: base < 2.0 || >= 3, bytestring >= 0.9    if flag(split-base)-    build-depends:   base >= 3.0, containers, array+    build-depends:   base >= 3.0, containers, array, parallel   else     build-depends:   base < 3.0 
cbits/lookup3.c view
@@ -51,119 +51,8 @@  #include "lookup3.h" -/*- * My best guess at if you are big-endian or little-endian.  This may- * need adjustment.- */-#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \-     __BYTE_ORDER == __LITTLE_ENDIAN) || \-    (defined(i386) || defined(__i386__) || defined(__i486__) || \-     defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))-# define HASH_LITTLE_ENDIAN 1-# define HASH_BIG_ENDIAN 0-#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \-       __BYTE_ORDER == __BIG_ENDIAN) || \-      (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))-# define HASH_LITTLE_ENDIAN 0-# define HASH_BIG_ENDIAN 1-#else-# define HASH_LITTLE_ENDIAN 0-# define HASH_BIG_ENDIAN 0-#endif- #define hashsize(n) ((uint32_t)1<<(n)) #define hashmask(n) (hashsize(n)-1)-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))--/*---------------------------------------------------------------------------------mix -- mix 3 32-bit values reversibly.--This is reversible, so any information in (a,b,c) before mix() is-still in (a,b,c) after mix().--If four pairs of (a,b,c) inputs are run through mix(), or through-mix() in reverse, there are at least 32 bits of the output that-are sometimes the same for one pair and different for another pair.-This was tested for:-* pairs that differed by one bit, by two bits, in any combination-  of top bits of (a,b,c), or in any combination of bottom bits of-  (a,b,c).-* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed-  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as-  is commonly produced by subtraction) look like a single 1-bit-  difference.-* the base values were pseudorandom, all zero but one bit set, or -  all zero plus a counter that starts at zero.--Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that-satisfy this are-    4  6  8 16 19  4-    9 15  3 18 27 15-   14  9  3  7 17  3-Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing-for "differ" defined as + with a one-bit base and a two-bit delta.  I-used http://burtleburtle.net/bob/hash/avalanche.html to choose -the operations, constants, and arrangements of the variables.--This does not achieve avalanche.  There are input bits of (a,b,c)-that fail to affect some output bits of (a,b,c), especially of a.  The-most thoroughly mixed value is c, but it doesn't really even achieve-avalanche in c.--This allows some parallelism.  Read-after-writes are good at doubling-the number of bits affected, so the goal of mixing pulls in the opposite-direction as the goal of parallelism.  I did what I could.  Rotates-seem to cost as much as shifts on every machine I could lay my hands-on, and rotates are much kinder to the top and bottom bits, so I used-rotates.---------------------------------------------------------------------------------*/-#define mix(a,b,c) \-{ \-  a -= c;  a ^= rot(c, 4);  c += b; \-  b -= a;  b ^= rot(a, 6);  a += c; \-  c -= b;  c ^= rot(b, 8);  b += a; \-  a -= c;  a ^= rot(c,16);  c += b; \-  b -= a;  b ^= rot(a,19);  a += c; \-  c -= b;  c ^= rot(b, 4);  b += a; \-}--/*---------------------------------------------------------------------------------final -- final mixing of 3 32-bit values (a,b,c) into c--Pairs of (a,b,c) values differing in only a few bits will usually-produce values of c that look totally different.  This was tested for-* pairs that differed by one bit, by two bits, in any combination-  of top bits of (a,b,c), or in any combination of bottom bits of-  (a,b,c).-* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed-  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as-  is commonly produced by subtraction) look like a single 1-bit-  difference.-* the base values were pseudorandom, all zero but one bit set, or -  all zero plus a counter that starts at zero.--These constants passed:- 14 11 25 16 4 14 24- 12 14 25 16 4 14 24-and these came close:-  4  8 15 26 3 22 24- 10  8 15 26 3 22 24- 11  8 15 26 3 22 24---------------------------------------------------------------------------------*/-#define final(a,b,c) \-{ \-  c ^= b; c -= rot(b,14); \-  a ^= c; a -= rot(c,11); \-  b ^= a; b -= rot(a,25); \-  c ^= b; c -= rot(b,16); \-  a ^= c; a -= rot(c,4);  \-  b ^= a; b -= rot(a,14); \-  c ^= b; c -= rot(b,24); \-}  /* --------------------------------------------------------------------
cbits/lookup3.h view
@@ -4,6 +4,118 @@ #include <stdint.h> #include <sys/types.h> +/*+ * My best guess at if you are big-endian or little-endian.  This may+ * need adjustment.+ */+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \+     __BYTE_ORDER == __LITTLE_ENDIAN) || \+    (defined(i386) || defined(__i386__) || defined(__i486__) || \+     defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))+# define HASH_LITTLE_ENDIAN 1+# define HASH_BIG_ENDIAN 0+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \+       __BYTE_ORDER == __BIG_ENDIAN) || \+      (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))+# define HASH_LITTLE_ENDIAN 0+# define HASH_BIG_ENDIAN 1+#else+# define HASH_LITTLE_ENDIAN 0+# define HASH_BIG_ENDIAN 0+#endif++#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))++/*+-------------------------------------------------------------------------------+mix -- mix 3 32-bit values reversibly.++This is reversible, so any information in (a,b,c) before mix() is+still in (a,b,c) after mix().++If four pairs of (a,b,c) inputs are run through mix(), or through+mix() in reverse, there are at least 32 bits of the output that+are sometimes the same for one pair and different for another pair.+This was tested for:+* pairs that differed by one bit, by two bits, in any combination+  of top bits of (a,b,c), or in any combination of bottom bits of+  (a,b,c).+* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed+  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as+  is commonly produced by subtraction) look like a single 1-bit+  difference.+* the base values were pseudorandom, all zero but one bit set, or +  all zero plus a counter that starts at zero.++Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that+satisfy this are+    4  6  8 16 19  4+    9 15  3 18 27 15+   14  9  3  7 17  3+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing+for "differ" defined as + with a one-bit base and a two-bit delta.  I+used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables.++This does not achieve avalanche.  There are input bits of (a,b,c)+that fail to affect some output bits of (a,b,c), especially of a.  The+most thoroughly mixed value is c, but it doesn't really even achieve+avalanche in c.++This allows some parallelism.  Read-after-writes are good at doubling+the number of bits affected, so the goal of mixing pulls in the opposite+direction as the goal of parallelism.  I did what I could.  Rotates+seem to cost as much as shifts on every machine I could lay my hands+on, and rotates are much kinder to the top and bottom bits, so I used+rotates.+-------------------------------------------------------------------------------+*/+#define mix(a,b,c) \+{ \+  a -= c;  a ^= rot(c, 4);  c += b; \+  b -= a;  b ^= rot(a, 6);  a += c; \+  c -= b;  c ^= rot(b, 8);  b += a; \+  a -= c;  a ^= rot(c,16);  c += b; \+  b -= a;  b ^= rot(a,19);  a += c; \+  c -= b;  c ^= rot(b, 4);  b += a; \+}++/*+-------------------------------------------------------------------------------+final -- final mixing of 3 32-bit values (a,b,c) into c++Pairs of (a,b,c) values differing in only a few bits will usually+produce values of c that look totally different.  This was tested for+* pairs that differed by one bit, by two bits, in any combination+  of top bits of (a,b,c), or in any combination of bottom bits of+  (a,b,c).+* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed+  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as+  is commonly produced by subtraction) look like a single 1-bit+  difference.+* the base values were pseudorandom, all zero but one bit set, or +  all zero plus a counter that starts at zero.++These constants passed:+ 14 11 25 16 4 14 24+ 12 14 25 16 4 14 24+and these came close:+  4  8 15 26 3 22 24+ 10  8 15 26 3 22 24+ 11  8 15 26 3 22 24+-------------------------------------------------------------------------------+*/+#define final(a,b,c) \+{ \+  c ^= b; c -= rot(b,14); \+  a ^= c; a -= rot(c,11); \+  b ^= a; b -= rot(a,25); \+  c ^= b; c -= rot(b,16); \+  a ^= c; a -= rot(c,4);  \+  b ^= a; b -= rot(a,14); \+  c ^= b; c -= rot(b,24); \+}+ uint32_t _jenkins_hashword(const uint32_t *k, size_t length, uint32_t initval);  uint32_t _jenkins_hashlittle(const void *key, size_t length, uint32_t initval);@@ -13,5 +125,224 @@  void _jenkins_hashlittle2(const void *key, size_t length, 			  uint32_t *pc, uint32_t *pb);++static inline void _jenkins_little2_begin(const uint32_t *pc,+					  const uint32_t *pb,+					  uint32_t st[3])+{+  uint32_t a,b,c;++  /* Set up the internal state */+  a = b = c = 0xdeadbeef + *pc;+  c += *pb;++  st[0] = a;+  st[1] = b;+  st[2] = c;+}++static inline size_t _jenkins_little2_frag(const void *key,+					   size_t length,+					   uint32_t st[4],+					   size_t offset)+{+  const uint8_t *k = key;+  size_t i;++  for (i = 0; i < length && offset < 12; i++, offset++) {+    st[offset >> 2] += k[i] << (8 * (offset & 3));+  }++  if (offset == 12) {+    uint32_t a = st[0], b = st[1], c = st[2];++    mix(a,b,c);++    st[0] = a;+    st[1] = b;+    st[2] = c;+  }+  +  return offset;+}++static inline size_t _jenkins_little2_step(const void *key,+					   size_t length,+					   uint32_t st[3])+{+  uint32_t a = st[0], b = st[1], c = st[2];   /* internal state */+  union { const void *ptr; size_t i; } u;     /* needed for Mac Powerbook G4 */++  u.ptr = key;+  if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {+    const uint32_t *k = (const uint32_t *)key;         /* read 32-bit chunks */++    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */+    while (length >= 12)+    {+      a += k[0];+      b += k[1];+      c += k[2];+      mix(a,b,c);+      length -= 12;+      k += 3;+    }++    /*----------------------------- handle the last (probably partial) block */+    /* +     * "k[2]&0xffffff" actually reads beyond the end of the string, but+     * then masks off the part it's not allowed to read.  Because the+     * string is aligned, the masked-off tail is in the same word as the+     * rest of the string.  Every machine with memory protection I've seen+     * does it on word boundaries, so is OK with this.  But VALGRIND will+     * still catch it and complain.  The masking trick does make the hash+     * noticably faster for short strings (like English words).+     */+#ifndef VALGRIND++    switch(length)+    {+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;+    case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;+    case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;+    case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;+    case 8 : b+=k[1]; a+=k[0]; break;+    case 7 : b+=k[1]&0xffffff; a+=k[0]; break;+    case 6 : b+=k[1]&0xffff; a+=k[0]; break;+    case 5 : b+=k[1]&0xff; a+=k[0]; break;+    case 4 : a+=k[0]; break;+    case 3 : a+=k[0]&0xffffff; break;+    case 2 : a+=k[0]&0xffff; break;+    case 1 : a+=k[0]&0xff; break;+    }++#else /* make valgrind happy */++    k8 = (const uint8_t *)k;+    switch(length)+    {+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;+    case 11: c+=((uint32_t)k8[10])<<16;  /* fall through */+    case 10: c+=((uint32_t)k8[9])<<8;    /* fall through */+    case 9 : c+=k8[8];                   /* fall through */+    case 8 : b+=k[1]; a+=k[0]; break;+    case 7 : b+=((uint32_t)k8[6])<<16;   /* fall through */+    case 6 : b+=((uint32_t)k8[5])<<8;    /* fall through */+    case 5 : b+=k8[4];                   /* fall through */+    case 4 : a+=k[0]; break;+    case 3 : a+=((uint32_t)k8[2])<<16;   /* fall through */+    case 2 : a+=((uint32_t)k8[1])<<8;    /* fall through */+    case 1 : a+=k8[0]; break;+    }++#endif /* !valgrind */++  } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {+    const uint16_t *k = (const uint16_t *)key;         /* read 16-bit chunks */+    const uint8_t  *k8;++    /*--------------- all but last block: aligned reads and different mixing */+    while (length >= 12)+    {+      a += k[0] + (((uint32_t)k[1])<<16);+      b += k[2] + (((uint32_t)k[3])<<16);+      c += k[4] + (((uint32_t)k[5])<<16);+      mix(a,b,c);+      length -= 12;+      k += 6;+    }++    /*----------------------------- handle the last (probably partial) block */+    k8 = (const uint8_t *)k;+    switch(length)+    {+    case 12: c+=k[4]+(((uint32_t)k[5])<<16);+             b+=k[2]+(((uint32_t)k[3])<<16);+             a+=k[0]+(((uint32_t)k[1])<<16);+             break;+    case 11: c+=((uint32_t)k8[10])<<16;     /* fall through */+    case 10: c+=k[4];+             b+=k[2]+(((uint32_t)k[3])<<16);+             a+=k[0]+(((uint32_t)k[1])<<16);+             break;+    case 9 : c+=k8[8];                      /* fall through */+    case 8 : b+=k[2]+(((uint32_t)k[3])<<16);+             a+=k[0]+(((uint32_t)k[1])<<16);+             break;+    case 7 : b+=((uint32_t)k8[6])<<16;      /* fall through */+    case 6 : b+=k[2];+             a+=k[0]+(((uint32_t)k[1])<<16);+             break;+    case 5 : b+=k8[4];                      /* fall through */+    case 4 : a+=k[0]+(((uint32_t)k[1])<<16);+             break;+    case 3 : a+=((uint32_t)k8[2])<<16;      /* fall through */+    case 2 : a+=k[0];+             break;+    case 1 : a+=k8[0];+             break;+    }++  } else {                        /* need to read the key one byte at a time */+    const uint8_t *k = (const uint8_t *)key;++    /*--------------- all but the last block: affect some 32 bits of (a,b,c) */+    while (length >= 12)+    {+      a += k[0];+      a += ((uint32_t)k[1])<<8;+      a += ((uint32_t)k[2])<<16;+      a += ((uint32_t)k[3])<<24;+      b += k[4];+      b += ((uint32_t)k[5])<<8;+      b += ((uint32_t)k[6])<<16;+      b += ((uint32_t)k[7])<<24;+      c += k[8];+      c += ((uint32_t)k[9])<<8;+      c += ((uint32_t)k[10])<<16;+      c += ((uint32_t)k[11])<<24;+      mix(a,b,c);+      length -= 12;+      k += 12;+    }++    /*-------------------------------- last block: affect all 32 bits of (c) */+    switch(length)                   /* all the case statements fall through */+    {+    case 12: c+=((uint32_t)k[11])<<24;+    case 11: c+=((uint32_t)k[10])<<16;+    case 10: c+=((uint32_t)k[9])<<8;+    case 9 : c+=k[8];+    case 8 : b+=((uint32_t)k[7])<<24;+    case 7 : b+=((uint32_t)k[6])<<16;+    case 6 : b+=((uint32_t)k[5])<<8;+    case 5 : b+=k[4];+    case 4 : a+=((uint32_t)k[3])<<24;+    case 3 : a+=((uint32_t)k[2])<<16;+    case 2 : a+=((uint32_t)k[1])<<8;+    case 1 : a+=k[0];+             break;+    }+  }++  st[0] = a;+  st[1] = b;+  st[2] = c;++  return length;+}+++static inline void _jenkins_little2_end(int nonempty,+					uint32_t *pc,+					uint32_t *pb,+					const uint32_t st[3])+{+  uint32_t a = st[0], b = st[1], c = st[2];++  if (nonempty)+    final(a,b,c);+  *pc=c; *pb=b;+}  #endif /* _lookup3_h */
examples/Words.hs view
@@ -2,11 +2,13 @@ -- builds a Bloom filter from a list of words, one per line, and -- queries it exhaustively. +module Main () where+ import Control.Monad (forM_, mapM_) import Data.BloomFilter (Bloom, fromListB, elemB, lengthB) import Data.BloomFilter.Hash (cheapHashes) import Data.BloomFilter.Easy (easyList, suggestSizing)-import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy.Char8 as B import Data.Time.Clock (diffUTCTime, getCurrentTime) import System.Environment (getArgs)