module Data.BloomFilter.Blocked (
Hash,
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,
freeze,
thaw,
unsafeFreeze,
Hashes,
hashes,
insertHashes,
elemHashes,
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
import Data.BloomFilter.Blocked.Internal hiding (deserialise)
import qualified Data.BloomFilter.Blocked.Internal as Internal
import Data.BloomFilter.Hash
import Prelude hiding (elem, notElem)
create :: BloomSize
-> (forall s. (MBloom s a -> ST s ()))
-> Bloom a
{-# INLINE create #-}
create :: forall a. BloomSize -> (forall s. MBloom s a -> ST s ()) -> Bloom a
create BloomSize
bloomsize 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 -> ST s (MBloom s a)
forall s a. BloomSize -> ST s (MBloom s a)
new BloomSize
bloomsize
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 (a -> Hashes a
forall a. Hashable a => a -> Hashes a
hashes 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 (a -> Hashes a
forall a. Hashable a => a -> Hashes a
hashes 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)
unfold :: forall a b.
Hashable a
=> BloomSize
-> (b -> Maybe (a, b))
-> b
-> Bloom a
{-# INLINE unfold #-}
unfold :: forall a b.
Hashable a =>
BloomSize -> (b -> Maybe (a, b)) -> b -> Bloom a
unfold BloomSize
bloomsize b -> Maybe (a, b)
f b
k =
BloomSize -> (forall s. MBloom s a -> ST s ()) -> Bloom a
forall a. BloomSize -> (forall s. MBloom s a -> ST s ()) -> Bloom a
create BloomSize
bloomsize 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'
fromList :: (Foldable t, Hashable a)
=> BloomPolicy
-> t a
-> Bloom a
fromList :: forall (t :: * -> *) a.
(Foldable t, Hashable a) =>
BloomPolicy -> t a -> Bloom a
fromList BloomPolicy
policy t a
xs =
BloomSize -> (forall s. MBloom s a -> ST s ()) -> Bloom a
forall a. BloomSize -> (forall s. MBloom s a -> ST s ()) -> Bloom a
create BloomSize
bsize (\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
-> (MutableByteArray RealWorld -> Int -> Int -> IO ())
-> IO (Bloom a) #-}
deserialise :: PrimMonad m
=> BloomSize
-> (MutableByteArray (PrimState m) -> Int -> Int -> m ())
-> m (Bloom a)
deserialise :: forall (m :: * -> *) a.
PrimMonad m =>
BloomSize
-> (MutableByteArray (PrimState m)
-> NumEntries -> NumEntries -> m ())
-> m (Bloom a)
deserialise BloomSize
bloomsize 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 -> ST (PrimState m) (MBloom (PrimState m) a)
forall s a. BloomSize -> ST s (MBloom s a)
new BloomSize
bloomsize
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 = a -> Hashes a
forall a. Hashable a => a -> Hashes a
hashes 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 = a -> Hashes a
forall a. Hashable a => a -> Hashes a
hashes 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 ()