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  }