sloane-5.0.0: Sloane/Bloom.hs
-- |
-- Copyright : Anders Claesson 2015
-- Maintainer : Anders Claesson <anders.claesson@gmail.com>
-- License : BSD-3
--
module Sloane.Bloom
( mkBloomFilter
, isFactorOf
) where
import Data.ByteString.Char8 (ByteString)
import Data.BloomFilter (Bloom)
import qualified Data.BloomFilter as F
import Data.BloomFilter.Hash
import Sloane.OEIS
import Sloane.DB
newtype T9 = T9 ( ByteString, ByteString, ByteString
, ByteString, ByteString, ByteString
, ByteString, ByteString, ByteString )
type BF = Bloom T9
instance Hashable T9 where
hashIO32 (T9 (a,b,c,d,e,f,g,h,i)) salt =
hashIO32 a salt >>= hashIO32 b >>= hashIO32 c >>= hashIO32 d >>= hashIO32 e
>>= hashIO32 f >>= hashIO32 g >>= hashIO32 h >>= hashIO32 i
zip9 :: [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]->[i] -> [(a,b,c,d,e,f,g,h,i)]
zip9 (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs) (h:hs) (i:is)
= (a,b,c,d,e,f,g,h,i) : zip9 as bs cs ds es fs gs hs is
zip9 _ _ _ _ _ _ _ _ _ = []
ninegrams :: [ByteString] -> [T9]
ninegrams xs = map T9 $ zip9 xs (drop 1 xs) (drop 2 xs) (drop 3 xs) (drop 4 xs)
(drop 5 xs) (drop 6 xs) (drop 7 xs) (drop 8 xs)
-- | Make a Bloom filter of all nine integer segments of all sequences
-- in the given data base.
mkBloomFilter :: DB Seqs -> BF
mkBloomFilter (DB db) = F.fromList (cheapHashes numHashes) numBits ts
where
ts = ninegrams (parseTermsOfRecords db)
numHashes = 3
numBits = 2^(26 :: Int)
-- | Are all the nine element factors of the given (packed) sequence
-- members of the Bloom filter. May give a false positive answer, but
-- never a false negative answer.
isFactorOf :: PackedSeq -> BF -> Bool
isFactorOf (PSeq s) bf = all (`F.elem` bf) $ ninegrams (parseTermsErr s)