module Data.BloomFilter.Blocked (
Hash,
Salt,
Hashable,
Bloom,
create,
unfold,
fromList,
formatVersion,
serialise,
deserialise,
NumEntries,
BloomSize (..),
FPR,
sizeForFPR,
BitsPerEntry,
sizeForBits,
sizeForPolicy,
BloomPolicy (..),
policyFPR,
policyForFPR,
policyForBits,
size,
elem,
notElem,
(?),
MBloom,
new,
maxSizeBits,
insert,
insertMany,
read,
freeze,
thaw,
unsafeFreeze,
Hashes,
hashesWithSalt,
insertHashes,
elemHashes,
readHashes,
prefetchInsert,
prefetchElem,
) where
import Control.Monad.Primitive (PrimMonad, PrimState, RealWorld,
stToPrim)
import Control.Monad.ST (ST, runST)
import Data.Bits ((.&.))
import Data.Primitive.ByteArray (MutableByteArray)
import qualified Data.Primitive.PrimArray as P
import Data.BloomFilter.Blocked.Calc (BitsPerEntry, BloomPolicy (..),
BloomSize (..), FPR, NumEntries, policyFPR, policyForBits,
policyForFPR, sizeForBits, sizeForFPR, sizeForPolicy)
import Data.BloomFilter.Blocked.Internal hiding (deserialise)
import qualified Data.BloomFilter.Blocked.Internal as Internal
import Data.BloomFilter.Hash
import Prelude hiding (elem, notElem, read)
create :: BloomSize
-> Salt
-> (forall s. (MBloom s a -> ST s ()))
-> Bloom a
{-# INLINE create #-}
create :: forall a.
BloomSize -> Salt -> (forall s. MBloom s a -> ST s ()) -> Bloom a
create BloomSize
bloomsize Salt
bloomsalt forall s. MBloom s a -> ST s ()
body =
(forall s. ST s (Bloom a)) -> Bloom a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (Bloom a)) -> Bloom a)
-> (forall s. ST s (Bloom a)) -> Bloom a
forall a b. (a -> b) -> a -> b
$ do
MBloom s a
mb <- BloomSize -> Salt -> ST s (MBloom s a)
forall s a. BloomSize -> Salt -> ST s (MBloom s a)
new BloomSize
bloomsize Salt
bloomsalt
MBloom s a -> ST s ()
forall s. MBloom s a -> ST s ()
body MBloom s a
mb
MBloom s a -> ST s (Bloom a)
forall s a. MBloom s a -> ST s (Bloom a)
unsafeFreeze MBloom s a
mb
{-# INLINEABLE insert #-}
insert :: Hashable a => MBloom s a -> a -> ST s ()
insert :: forall a s. Hashable a => MBloom s a -> a -> ST s ()
insert = \ !MBloom s a
mb !a
x -> MBloom s a -> Hashes a -> ST s ()
forall s a. MBloom s a -> Hashes a -> ST s ()
insertHashes MBloom s a
mb (Salt -> a -> Hashes a
forall a. Hashable a => Salt -> a -> Hashes a
hashesWithSalt (MBloom s a -> Salt
forall s a. MBloom s a -> Salt
mbHashSalt MBloom s a
mb) a
x)
{-# INLINE elem #-}
elem :: Hashable a => a -> Bloom a -> Bool
elem :: forall a. Hashable a => a -> Bloom a -> Bool
elem = \ !a
x !Bloom a
b -> Bloom a -> Hashes a -> Bool
forall a. Bloom a -> Hashes a -> Bool
elemHashes Bloom a
b (Salt -> a -> Hashes a
forall a. Hashable a => Salt -> a -> Hashes a
hashesWithSalt (Bloom a -> Salt
forall a. Bloom a -> Salt
hashSalt Bloom a
b) a
x)
(?) :: Hashable a => Bloom a -> a -> Bool
? :: forall a. Hashable a => Bloom a -> a -> Bool
(?) = (a -> Bloom a -> Bool) -> Bloom a -> a -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> Bloom a -> Bool
forall a. Hashable a => a -> Bloom a -> Bool
elem
{-# INLINE notElem #-}
notElem :: Hashable a => a -> Bloom a -> Bool
notElem :: forall a. Hashable a => a -> Bloom a -> Bool
notElem = \a
x Bloom a
b -> Bool -> Bool
not (a
x a -> Bloom a -> Bool
forall a. Hashable a => a -> Bloom a -> Bool
`elem` Bloom a
b)
read :: Hashable a => MBloom s a -> a -> ST s Bool
read :: forall a s. Hashable a => MBloom s a -> a -> ST s Bool
read !MBloom s a
mb !a
x = MBloom s a -> Hashes a -> ST s Bool
forall s a. MBloom s a -> Hashes a -> ST s Bool
readHashes MBloom s a
mb (Salt -> a -> Hashes a
forall a. Hashable a => Salt -> a -> Hashes a
hashesWithSalt (MBloom s a -> Salt
forall s a. MBloom s a -> Salt
mbHashSalt MBloom s a
mb) a
x)
unfold :: forall a b.
Hashable a
=> BloomSize
-> Salt
-> (b -> Maybe (a, b))
-> b
-> Bloom a
{-# INLINE unfold #-}
unfold :: forall a b.
Hashable a =>
BloomSize -> Salt -> (b -> Maybe (a, b)) -> b -> Bloom a
unfold BloomSize
bloomsize Salt
bloomsalt b -> Maybe (a, b)
f b
k =
BloomSize -> Salt -> (forall s. MBloom s a -> ST s ()) -> Bloom a
forall a.
BloomSize -> Salt -> (forall s. MBloom s a -> ST s ()) -> Bloom a
create BloomSize
bloomsize Salt
bloomsalt MBloom s a -> ST s ()
forall s. MBloom s a -> ST s ()
body
where
body :: forall s. MBloom s a -> ST s ()
body :: forall s. MBloom s a -> ST s ()
body MBloom s a
mb = b -> ST s ()
loop b
k
where
loop :: b -> ST s ()
loop :: b -> ST s ()
loop !b
j = case b -> Maybe (a, b)
f b
j of
Maybe (a, b)
Nothing -> () -> ST s ()
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just (a
a, b
j') -> MBloom s a -> a -> ST s ()
forall a s. Hashable a => MBloom s a -> a -> ST s ()
insert MBloom s a
mb a
a ST s () -> ST s () -> ST s ()
forall a b. ST s a -> ST s b -> ST s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> ST s ()
loop b
j'
{-# INLINEABLE fromList #-}
fromList :: (Foldable t, Hashable a)
=> BloomPolicy
-> Salt
-> t a
-> Bloom a
fromList :: forall (t :: * -> *) a.
(Foldable t, Hashable a) =>
BloomPolicy -> Salt -> t a -> Bloom a
fromList BloomPolicy
policy Salt
bloomsalt t a
xs =
BloomSize -> Salt -> (forall s. MBloom s a -> ST s ()) -> Bloom a
forall a.
BloomSize -> Salt -> (forall s. MBloom s a -> ST s ()) -> Bloom a
create BloomSize
bsize Salt
bloomsalt (\MBloom s a
b -> (a -> ST s ()) -> t a -> ST s ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (MBloom s a -> a -> ST s ()
forall a s. Hashable a => MBloom s a -> a -> ST s ()
insert MBloom s a
b) t a
xs)
where
bsize :: BloomSize
bsize = BloomPolicy -> NumEntries -> BloomSize
sizeForPolicy BloomPolicy
policy (t a -> NumEntries
forall a. t a -> NumEntries
forall (t :: * -> *) a. Foldable t => t a -> NumEntries
length t a
xs)
{-# SPECIALISE deserialise ::
BloomSize
-> Salt
-> (MutableByteArray RealWorld -> Int -> Int -> IO ())
-> IO (Bloom a) #-}
deserialise :: PrimMonad m
=> BloomSize
-> Salt
-> (MutableByteArray (PrimState m) -> Int -> Int -> m ())
-> m (Bloom a)
deserialise :: forall (m :: * -> *) a.
PrimMonad m =>
BloomSize
-> Salt
-> (MutableByteArray (PrimState m)
-> NumEntries -> NumEntries -> m ())
-> m (Bloom a)
deserialise BloomSize
bloomsize Salt
bloomsalt MutableByteArray (PrimState m) -> NumEntries -> NumEntries -> m ()
fill = do
MBloom (PrimState m) a
mbloom <- ST (PrimState m) (MBloom (PrimState m) a)
-> m (MBloom (PrimState m) a)
forall (m :: * -> *) a. PrimMonad m => ST (PrimState m) a -> m a
stToPrim (ST (PrimState m) (MBloom (PrimState m) a)
-> m (MBloom (PrimState m) a))
-> ST (PrimState m) (MBloom (PrimState m) a)
-> m (MBloom (PrimState m) a)
forall a b. (a -> b) -> a -> b
$ BloomSize -> Salt -> ST (PrimState m) (MBloom (PrimState m) a)
forall s a. BloomSize -> Salt -> ST s (MBloom s a)
new BloomSize
bloomsize Salt
bloomsalt
MBloom (PrimState m) a
-> (MutableByteArray (PrimState m)
-> NumEntries -> NumEntries -> m ())
-> m ()
forall (m :: * -> *) a.
PrimMonad m =>
MBloom (PrimState m) a
-> (MutableByteArray (PrimState m)
-> NumEntries -> NumEntries -> m ())
-> m ()
Internal.deserialise MBloom (PrimState m) a
mbloom MutableByteArray (PrimState m) -> NumEntries -> NumEntries -> m ()
fill
ST (PrimState m) (Bloom a) -> m (Bloom a)
forall (m :: * -> *) a. PrimMonad m => ST (PrimState m) a -> m a
stToPrim (ST (PrimState m) (Bloom a) -> m (Bloom a))
-> ST (PrimState m) (Bloom a) -> m (Bloom a)
forall a b. (a -> b) -> a -> b
$ MBloom (PrimState m) a -> ST (PrimState m) (Bloom a)
forall s a. MBloom s a -> ST s (Bloom a)
unsafeFreeze MBloom (PrimState m) a
mbloom
{-# INLINABLE insertMany #-}
insertMany ::
forall a s.
Hashable a
=> MBloom s a
-> (Int -> ST s a)
-> Int
-> ST s ()
insertMany :: forall a s.
Hashable a =>
MBloom s a -> (NumEntries -> ST s a) -> NumEntries -> ST s ()
insertMany MBloom s a
bloom NumEntries -> ST s a
key NumEntries
n =
NumEntries -> ST s (MutablePrimArray (PrimState (ST s)) (Hashes a))
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
NumEntries -> m (MutablePrimArray (PrimState m) a)
P.newPrimArray NumEntries
0x10 ST s (MutablePrimArray s (Hashes a))
-> (MutablePrimArray s (Hashes a) -> ST s ()) -> ST s ()
forall a b. ST s a -> (a -> ST s b) -> ST s b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MutablePrimArray s (Hashes a) -> ST s ()
body
where
body :: P.MutablePrimArray s (Hashes a) -> ST s ()
body :: MutablePrimArray s (Hashes a) -> ST s ()
body !MutablePrimArray s (Hashes a)
buf = NumEntries -> NumEntries -> ST s ()
prepareProbes NumEntries
0 NumEntries
0
where
prepareProbes :: Int -> Int -> ST s ()
prepareProbes :: NumEntries -> NumEntries -> ST s ()
prepareProbes !NumEntries
i !NumEntries
i_w
| NumEntries
i_w NumEntries -> NumEntries -> Bool
forall a. Ord a => a -> a -> Bool
< NumEntries
0x0f Bool -> Bool -> Bool
&& NumEntries
i NumEntries -> NumEntries -> Bool
forall a. Ord a => a -> a -> Bool
< NumEntries
n = do
a
k <- NumEntries -> ST s a
key NumEntries
i
let !kh :: Hashes a
kh = Salt -> a -> Hashes a
forall a. Hashable a => Salt -> a -> Hashes a
hashesWithSalt (MBloom s a -> Salt
forall s a. MBloom s a -> Salt
mbHashSalt MBloom s a
bloom) a
k
MBloom s a -> Hashes a -> ST s ()
forall s a. MBloom s a -> Hashes a -> ST s ()
prefetchInsert MBloom s a
bloom Hashes a
kh
MutablePrimArray (PrimState (ST s)) (Hashes a)
-> NumEntries -> Hashes a -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> NumEntries -> a -> m ()
P.writePrimArray MutablePrimArray s (Hashes a)
MutablePrimArray (PrimState (ST s)) (Hashes a)
buf NumEntries
i_w Hashes a
kh
NumEntries -> NumEntries -> ST s ()
prepareProbes (NumEntries
iNumEntries -> NumEntries -> NumEntries
forall a. Num a => a -> a -> a
+NumEntries
1) (NumEntries
i_wNumEntries -> NumEntries -> NumEntries
forall a. Num a => a -> a -> a
+NumEntries
1)
| NumEntries
n NumEntries -> NumEntries -> Bool
forall a. Ord a => a -> a -> Bool
> NumEntries
0 = NumEntries -> NumEntries -> NumEntries -> ST s ()
insertProbe NumEntries
0 NumEntries
0 NumEntries
i_w
| Bool
otherwise = () -> ST s ()
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
insertProbe :: Int -> Int -> Int -> ST s ()
insertProbe :: NumEntries -> NumEntries -> NumEntries -> ST s ()
insertProbe !NumEntries
i !NumEntries
i_r !NumEntries
i_w = do
Hashes a
kh <- MutablePrimArray (PrimState (ST s)) (Hashes a)
-> NumEntries -> ST s (Hashes a)
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> NumEntries -> m a
P.readPrimArray MutablePrimArray s (Hashes a)
MutablePrimArray (PrimState (ST s)) (Hashes a)
buf NumEntries
i_r
MBloom s a -> Hashes a -> ST s ()
forall s a. MBloom s a -> Hashes a -> ST s ()
insertHashes MBloom s a
bloom Hashes a
kh
NumEntries -> NumEntries -> NumEntries -> ST s ()
nextProbe NumEntries
i NumEntries
i_r NumEntries
i_w
nextProbe :: Int -> Int -> Int -> ST s ()
nextProbe :: NumEntries -> NumEntries -> NumEntries -> ST s ()
nextProbe !NumEntries
i !NumEntries
i_r !NumEntries
i_w
| NumEntries
i NumEntries -> NumEntries -> Bool
forall a. Ord a => a -> a -> Bool
< NumEntries
n = do
a
k <- NumEntries -> ST s a
key NumEntries
i
let !kh :: Hashes a
kh = Salt -> a -> Hashes a
forall a. Hashable a => Salt -> a -> Hashes a
hashesWithSalt (MBloom s a -> Salt
forall s a. MBloom s a -> Salt
mbHashSalt MBloom s a
bloom) a
k
MBloom s a -> Hashes a -> ST s ()
forall s a. MBloom s a -> Hashes a -> ST s ()
prefetchInsert MBloom s a
bloom Hashes a
kh
MutablePrimArray (PrimState (ST s)) (Hashes a)
-> NumEntries -> Hashes a -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> NumEntries -> a -> m ()
P.writePrimArray MutablePrimArray s (Hashes a)
MutablePrimArray (PrimState (ST s)) (Hashes a)
buf NumEntries
i_w Hashes a
kh
NumEntries -> NumEntries -> NumEntries -> ST s ()
insertProbe
(NumEntries
iNumEntries -> NumEntries -> NumEntries
forall a. Num a => a -> a -> a
+NumEntries
1)
((NumEntries
i_r NumEntries -> NumEntries -> NumEntries
forall a. Num a => a -> a -> a
+ NumEntries
1) NumEntries -> NumEntries -> NumEntries
forall a. Bits a => a -> a -> a
.&. NumEntries
0x0f)
((NumEntries
i_w NumEntries -> NumEntries -> NumEntries
forall a. Num a => a -> a -> a
+ NumEntries
1) NumEntries -> NumEntries -> NumEntries
forall a. Bits a => a -> a -> a
.&. NumEntries
0x0f)
| ((NumEntries
i_r NumEntries -> NumEntries -> NumEntries
forall a. Num a => a -> a -> a
+ NumEntries
1) NumEntries -> NumEntries -> NumEntries
forall a. Bits a => a -> a -> a
.&. NumEntries
0x0f) NumEntries -> NumEntries -> Bool
forall a. Eq a => a -> a -> Bool
/= NumEntries
i_w =
NumEntries -> NumEntries -> NumEntries -> ST s ()
insertProbe
NumEntries
i
((NumEntries
i_r NumEntries -> NumEntries -> NumEntries
forall a. Num a => a -> a -> a
+ NumEntries
1) NumEntries -> NumEntries -> NumEntries
forall a. Bits a => a -> a -> a
.&. NumEntries
0x0f)
NumEntries
i_w
| Bool
otherwise = () -> ST s ()
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()