Skip to content

Tip #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 8, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove intersection
  • Loading branch information
korthaj committed May 8, 2017
commit 0d2fa998377d7c7a1211d29d115c507b48f74d13
26 changes: 11 additions & 15 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,25 @@ func Example_falsePositives() {
// Output: 26 mistakes were made.
}

// Compute the intersection and union of two filters.
func ExampleFilter_And() {
// Compute the union of two filters.
func ExampleFilter_Or() {
// Create two Bloom filter with room for 1000 elements
// at a false-positives rate less than 1/100.
n := 1000
p := 100
f1, f2 := bloom.New(n, p), bloom.New(n, p)
n, p := 1000, 100
f1 := bloom.New(n, p)
f2 := bloom.New(n, p)

// Add "0", "1", …, "499" to f1
for i := 0; i < n/2; i++ {
// Add "0", "2", …, "498" to f1
for i := 0; i < n/2; i += 2 {
f1.Add(strconv.Itoa(i))
}

// Add "250", "251", …, "749" to f2
for i := n / 4; i < 3*n/4; i++ {
// Add "1", "3", …, "499" to f2
for i := 1; i < n/2; i += 2 {
f2.Add(strconv.Itoa(i))
}

// Compute the approximate size of f1 ∩ f2 and f1 ∪ f2.
fmt.Println("f1 ∩ f2:", f1.And(f2).Count())
// Compute the approximate size of f1 ∪ f2.
fmt.Println("f1 ∪ f2:", f1.Or(f2).Count())
// Output:
// f1 ∩ f2: 276
// f1 ∪ f2: 758

// Output: f1 ∪ f2: 505
}
37 changes: 3 additions & 34 deletions filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,43 +122,12 @@ func (f *Filter) Count() int64 {
return f.count
}

// And returns a new Bloom filter that consists of all elements
// that belong to both f1 and f2. The two filters must be of
// the same size and have the same false-positives rate.
//
// The false-positive rate of the resulting filter is bounded by
// the maximum false-positive rate of f1 and f2, but it may be larger
// than the rate of the filter created from scratch using
// the intersection of the two sets.
func (f1 *Filter) And(f2 *Filter) *Filter {
if len(f1.data) != len(f2.data) || f1.lookups != f2.lookups {
panic("operation requires filters of the same type")
}
len := len(f1.data)
res := &Filter{
data: make([]uint64, len),
lookups: f1.lookups,
}
bitCount := 0
for i := 0; i < len; i++ {
w := f1.data[i] & f2.data[i]
res.data[i] = w
bitCount += count(w)
}
// Estimate the number of elements from the bitCount.
m := 64 * float64(len)
bits := float64(bitCount)
n := m / float64(f1.lookups) * math.Log(m/(m-bits))
res.count = int64(n)
return res
}

// Or returns a new Bloom filter that consists of all elements
// that belong to either f1 or f2. The two filters must be of
// the same size and have the same false-positives rate.
// the same size n and have the same false-positives rate p.
//
// The resulting filter is the same as the filter created from scratch
// using the union of the two sets.
// The resulting filter is the same as the filter created
// from scratch using the union of the two sets.
func (f1 *Filter) Or(f2 *Filter) *Filter {
if len(f1.data) != len(f2.data) || f1.lookups != f2.lookups {
panic("operation requires filters of the same type")
Expand Down
22 changes: 5 additions & 17 deletions filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func TestFilter(t *testing.T) {
}
}

func TestAndOr(t *testing.T) {
func TestOr(t *testing.T) {
s1 := "asöldkgjaösldkgaösldkasldgjkaösldkgjöasgkdjg"
s2 := "elasödlnkgaölsdkfgaölsdkjfaölsdkgaölskgnaösl"
s3 := "aölsdgkaösldkgaösldkgjaölsdkjgaölsdkgjaösldk"
Expand All @@ -69,20 +69,8 @@ func TestAndOr(t *testing.T) {
f1.Add(s2)
f2.Add(s2)
f2.Add(s3)
and, or := f1.And(f2), f1.Or(f2)
member := and.Test(s1)
if member {
t.Errorf("and.Test(s1) = %v; want false\n", member)
}
member = and.Test(s2)
if !member {
t.Errorf("and.Test(s2) = %v; want true\n", member)
}
member = and.Test(s3)
if member {
t.Errorf("and.Test(s3) = %v; want false\n", member)
}
member = or.Test(s1)
or := f1.Or(f2)
member := or.Test(s1)
if !member {
t.Errorf("or.Test(s1) = %v; want true\n", member)
}
Expand Down Expand Up @@ -138,13 +126,13 @@ func BenchmarkTestByte(b *testing.B) {
}
}

func BenchmarkTestAnd(b *testing.B) {
func BenchmarkTestOr(b *testing.B) {
n := 1000
b.StopTimer()
f1 := New(n, 200)
f2 := New(n, 200)
b.StartTimer()
for i := 0; i < b.N; i++ {
_ = f1.And(f2)
_ = f1.Or(f2)
}
}