github.com/andy2046/gopie@v0.7.0/pkg/bloom/bloombit.go (about) 1 package bloom 2 3 import ( 4 "math" 5 6 "github.com/andy2046/bitmap" 7 ) 8 9 type ( 10 bloomFilterBit struct { 11 bitmap *bitmap.Bitmap // bloom filter bitmap 12 k uint64 // number of hash functions 13 n uint64 // number of elements in the bloom filter 14 m uint64 // size of the bloom filter bits 15 shift uint8 // the shift to get high/low bit fragments 16 } 17 ) 18 19 // NewB creates standard bloom filter based on the provided m/k. 20 // m is the size of bloom filter bits. 21 // k is the number of hash functions. 22 func NewB(m, k uint64) Bloom { 23 mm, exponent := adjustM(m) 24 return &bloomFilterBit{ 25 bitmap: bitmap.New(mm), 26 m: mm - 1, // x % 2^i = x & (2^i - 1) 27 k: k, 28 shift: 64 - exponent, 29 } 30 } 31 32 // NewBGuess estimates m/k based on the provided n/p then creates standard bloom filter. 33 // n is the estimated number of elements in the bloom filter. 34 // p is the false positive probability. 35 func NewBGuess(n uint64, p float64) Bloom { 36 m, k := Guess(n, p) 37 return NewB(m, k) 38 } 39 40 func (bf *bloomFilterBit) Add(entry []byte) { 41 hash := sipHash(entry) 42 h := hash >> bf.shift 43 l := hash << bf.shift >> bf.shift 44 for i := uint64(0); i < bf.k; i++ { 45 bf.bitmap.SetBit((h+i*l)&bf.m, true) 46 } 47 bf.n++ 48 } 49 50 func (bf *bloomFilterBit) AddString(entry string) { 51 bf.Add([]byte(entry)) 52 } 53 54 func (bf *bloomFilterBit) Exist(entry []byte) bool { 55 hash := sipHash(entry) 56 h := hash >> bf.shift 57 l := hash << bf.shift >> bf.shift 58 59 for i := uint64(0); i < bf.k; i++ { 60 if !bf.bitmap.GetBit((h + i*l) & bf.m) { 61 return false 62 } 63 } 64 65 return true 66 } 67 68 func (bf *bloomFilterBit) ExistString(entry string) bool { 69 return bf.Exist([]byte(entry)) 70 } 71 72 func (bf *bloomFilterBit) FalsePositive() float64 { 73 return math.Pow((1 - math.Exp(-float64(bf.k*bf.n)/float64(bf.m))), 74 float64(bf.k)) 75 } 76 77 func (bf *bloomFilterBit) GuessFalsePositive(n uint64) float64 { 78 return math.Pow((1 - math.Exp(-float64(bf.k*n)/float64(bf.m))), 79 float64(bf.k)) 80 } 81 82 func (bf *bloomFilterBit) M() uint64 { 83 return bf.m + 1 84 } 85 86 func (bf *bloomFilterBit) K() uint64 { 87 return bf.k 88 } 89 90 func (bf *bloomFilterBit) N() uint64 { 91 return bf.n 92 } 93 94 func (bf *bloomFilterBit) Clear() { 95 s := bf.bitmap.Size() 96 for i := uint64(0); i < s; i++ { 97 bf.bitmap.SetBit(i, false) 98 } 99 bf.n = 0 100 } 101 102 func (bf *bloomFilterBit) estimatedFillRatio() float64 { 103 return 1 - math.Exp(-float64(bf.n)/math.Ceil(float64(bf.m)/float64(bf.k))) 104 }