{-# LANGUAGE ViewPatterns #-}
module Development.Shake.Internal.History.Bloom(
Bloom, bloomTest, bloomCreate
) where
import Data.Word
import Data.Bits
import Data.Hashable
import Data.Semigroup
import Foreign.Storable
import Foreign.Ptr
import Prelude
data Bloom a = Bloom
{-# UNPACK #-} !Word64
{-# UNPACK #-} !Word64
{-# UNPACK #-} !Word64
{-# UNPACK #-} !Word64
deriving (Eq,Show)
instance Storable (Bloom a) where
sizeOf _ = 4 * sizeOf (0 :: Word64)
alignment _ = alignment (0 :: Word64)
peek (castPtr -> ptr) = Bloom <$> peekElemOff ptr 0 <*> peekElemOff ptr 1 <*> peekElemOff ptr 2 <*> peekElemOff ptr 3
poke (castPtr -> ptr) (Bloom x1 x2 x3 x4) = do
pokeElemOff ptr 0 x1
pokeElemOff ptr 1 x2
pokeElemOff ptr 2 x3
pokeElemOff ptr 3 x4
instance Semigroup (Bloom a) where
Bloom x1 x2 x3 x4 <> Bloom y1 y2 y3 y4 =
Bloom (x1 .|. y1) (x2 .|. y2) (x3 .|. y3) (x4 .|. y4)
instance Monoid (Bloom a) where
mempty = Bloom 0 0 0 0
mappend = (<>)
bloomTest :: Hashable a => Bloom a -> a -> Bool
bloomTest bloom x = bloomCreate x <> bloom == bloom
bloomCreate :: Hashable a => a -> Bloom a
bloomCreate (fromIntegral . hash -> x) =
Bloom (f 1) (f 2) (f 3) (f 4)
where f i = x `xor` rotate x i