module Data.BloomFilter.Classic.Calc (
NumEntries,
BloomSize (..),
FPR,
sizeForFPR,
BitsPerEntry,
sizeForBits,
sizeForPolicy,
BloomPolicy (..),
policyFPR,
policyForFPR,
policyForBits,
) where
import Numeric
type FPR = Double
type BitsPerEntry = Double
type NumEntries = Int
data BloomPolicy = BloomPolicy {
BloomPolicy -> Double
policyBits :: !Double,
BloomPolicy -> Int
policyHashes :: !Int
}
deriving stock Int -> BloomPolicy -> ShowS
[BloomPolicy] -> ShowS
BloomPolicy -> String
(Int -> BloomPolicy -> ShowS)
-> (BloomPolicy -> String)
-> ([BloomPolicy] -> ShowS)
-> Show BloomPolicy
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BloomPolicy -> ShowS
showsPrec :: Int -> BloomPolicy -> ShowS
$cshow :: BloomPolicy -> String
show :: BloomPolicy -> String
$cshowList :: [BloomPolicy] -> ShowS
showList :: [BloomPolicy] -> ShowS
Show
policyForFPR :: FPR -> BloomPolicy
policyForFPR :: Double -> BloomPolicy
policyForFPR Double
fpr | Double
fpr Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0 Bool -> Bool -> Bool
|| Double
fpr Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
1 =
String -> BloomPolicy
forall a. HasCallStack => String -> a
error String
"bloomPolicyForFPR: fpr out of range (0,1)"
policyForFPR Double
fpr =
BloomPolicy {
policyBits :: Double
policyBits = Double
c,
policyHashes :: Int
policyHashes = Int
k
}
where
k :: Int; k' :: Double
k :: Int
k = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round ((-Double
recip_log2) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
log_fpr))
k' :: Double
k' = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
k
c :: Double
c = Double -> Double
forall a. Num a => a -> a
negate Double
k' Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
forall a. Floating a => a -> a
log1mexp (Double
log_fpr Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k')
log_fpr :: Double
log_fpr = Double -> Double
forall a. Floating a => a -> a
log Double
fpr
policyForBits :: BitsPerEntry -> BloomPolicy
policyForBits :: Double -> BloomPolicy
policyForBits Double
c | Double
c Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0 =
String -> BloomPolicy
forall a. HasCallStack => String -> a
error String
"policyForBits: bits per entry must be > 0"
policyForBits Double
c =
BloomPolicy {
policyBits :: Double
policyBits = Double
c,
policyHashes :: Int
policyHashes = Int
k
}
where
k :: Int
k = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
c Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
log2))
policyFPR :: BloomPolicy -> FPR
policyFPR :: BloomPolicy -> Double
policyFPR BloomPolicy {
policyBits :: BloomPolicy -> Double
policyBits = Double
c,
policyHashes :: BloomPolicy -> Int
policyHashes = Int
k
} =
Double -> Double
forall a. Num a => a -> a
negate (Double -> Double
forall a. Floating a => a -> a
expm1 (Double -> Double
forall a. Num a => a -> a
negate (Double
k' Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
c))) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
k'
where
k' :: Double
k' = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
k
data BloomSize = BloomSize {
BloomSize -> Int
sizeBits :: !Int,
BloomSize -> Int
sizeHashes :: !Int
}
deriving stock Int -> BloomSize -> ShowS
[BloomSize] -> ShowS
BloomSize -> String
(Int -> BloomSize -> ShowS)
-> (BloomSize -> String)
-> ([BloomSize] -> ShowS)
-> Show BloomSize
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BloomSize -> ShowS
showsPrec :: Int -> BloomSize -> ShowS
$cshow :: BloomSize -> String
show :: BloomSize -> String
$cshowList :: [BloomSize] -> ShowS
showList :: [BloomSize] -> ShowS
Show
sizeForFPR :: FPR -> NumEntries -> BloomSize
sizeForFPR :: Double -> Int -> BloomSize
sizeForFPR = BloomPolicy -> Int -> BloomSize
sizeForPolicy (BloomPolicy -> Int -> BloomSize)
-> (Double -> BloomPolicy) -> Double -> Int -> BloomSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> BloomPolicy
policyForFPR
sizeForBits :: BitsPerEntry -> NumEntries -> BloomSize
sizeForBits :: Double -> Int -> BloomSize
sizeForBits = BloomPolicy -> Int -> BloomSize
sizeForPolicy (BloomPolicy -> Int -> BloomSize)
-> (Double -> BloomPolicy) -> Double -> Int -> BloomSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> BloomPolicy
policyForBits
sizeForPolicy :: BloomPolicy -> NumEntries -> BloomSize
sizeForPolicy :: BloomPolicy -> Int -> BloomSize
sizeForPolicy BloomPolicy {
policyBits :: BloomPolicy -> Double
policyBits = Double
c,
policyHashes :: BloomPolicy -> Int
policyHashes = Int
k
} Int
n =
BloomSize {
sizeBits :: Int
sizeBits = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
c)),
sizeHashes :: Int
sizeHashes = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 Int
k
}
log2, recip_log2 :: Double
log2 :: Double
log2 = Double -> Double
forall a. Floating a => a -> a
log Double
2
recip_log2 :: Double
recip_log2 = Double -> Double
forall a. Fractional a => a -> a
recip Double
log2