Skip to content
Browse files

Add check for filter compatiblity

When computing union and intersection of filters a check of filter
compatibility is performed. Also a valid instance of Native filter is
returned for this methods.
  • Loading branch information...
1 parent 43a62e2 commit 504427b68567aac78c6cab300dd25823e6b6aaae @apohllo apohllo committed Mar 12, 2012
Showing with 60 additions and 10 deletions.
  1. +7 −4 ext/cbloomfilter/cbloomfilter.c
  2. +29 −2 lib/bloomfilter/native.rb
  3. +24 −4 spec/native_spec.rb
View
11 ext/cbloomfilter/cbloomfilter.c
@@ -170,6 +170,12 @@ static VALUE bf_r(VALUE self) {
return bf->r == 0 ? Qfalse : Qtrue;
}
+static VALUE bf_s(VALUE self) {
+ struct BloomFilter *bf;
+ Data_Get_Struct(self, struct BloomFilter, bf);
+ return INT2FIX(bf->s);
+}
+
static VALUE bf_num_set(VALUE self) {
struct BloomFilter *bf;
Data_Get_Struct(self, struct BloomFilter, bf);
@@ -233,8 +239,6 @@ static VALUE bf_and(VALUE self, VALUE other) {
klass = rb_funcall(self,rb_intern("class"),0);
obj = bf_s_new(5,args,klass);
Data_Get_Struct(obj, struct BloomFilter, target);
- // we assume that the parameters of both filters are the same
- // TODO check if this is true
for (i = 0; i < bf->bytes; i++){
target->ptr[i] = bf->ptr[i] & bf_other->ptr[i];
}
@@ -257,8 +261,6 @@ static VALUE bf_or(VALUE self, VALUE other) {
klass = rb_funcall(self,rb_intern("class"),0);
obj = bf_s_new(5,args,klass);
Data_Get_Struct(obj, struct BloomFilter, target);
- // we assume that the parameters of both filters are the same
- // TODO check if this is true
for (i = 0; i < bf->bytes; i++){
target->ptr[i] = bf->ptr[i] | bf_other->ptr[i];
}
@@ -388,6 +390,7 @@ void Init_cbloomfilter(void) {
rb_define_method(cBloomFilter, "k", bf_k, 0);
rb_define_method(cBloomFilter, "b", bf_b, 0);
rb_define_method(cBloomFilter, "r", bf_r, 0);
+ rb_define_method(cBloomFilter, "s", bf_s, 0);
rb_define_method(cBloomFilter, "num_set", bf_num_set, 0);
rb_define_method(cBloomFilter, "insert", bf_insert, 1);
rb_define_method(cBloomFilter, "delete", bf_delete, 1);
View
31 lib/bloomfilter/native.rb
@@ -35,8 +35,26 @@ def delete(key); @bf.delete(key); end
def clear; @bf.clear; end
def size; @bf.num_set; end
def merge!(o); @bf.merge!(o.bf); end
- def &(o); @bf.&(o.bf); end
- def |(o); @bf.|(o.bf); end
+
+ # Computes the intersection of two Bloom filters.
+ # It assumes that both filters have the same size -
+ # if this is not true +ArgumentError+ is raised.
+ def &(o)
+ raise ArgumentError.new() unless same_parameters?(o)
+ result = self.class.new
+ result.instance_variable_set(:@bf,@bf.&(o.bf))
+ result
+ end
+
+ # Computes the union of two Bloom filters.
+ # It assumes that both filters have the same size -
+ # if this is not true +ArgumentError+ is raised.
+ def |(o)
+ raise ArgumentError.new() unless same_parameters?(o)
+ result = self.class.new
+ result.instance_variable_set(:@bf,@bf.|(o.bf))
+ result
+ end
def bitmap
@bf.bitmap
@@ -63,5 +81,14 @@ def save(filename)
end
end
+ protected
+
+ # Returns true if parameters of the +o+ther filter are
+ # the same.
+ def same_parameters?(o)
+ @bf.m == o.bf.m && @bf.k == o.bf.k &&
+ @bf.s == o.bf.s && @bf.b == o.bf.b
+ end
+
end
end
View
28 spec/native_spec.rb
@@ -44,11 +44,11 @@
end
it "should return intersection with other filter" do
- bf1 = Native.new
+ bf1 = Native.new(:seed => 1)
bf1.insert("test")
bf1.insert("test1")
- bf2 = Native.new
+ bf2 = Native.new(:seed => 1)
bf2.insert("test")
bf2.insert("test2")
@@ -58,12 +58,22 @@
bf3.include?("test2").should be_false
end
+ it "should raise an exception when intersection is to be computed for incompatible filters" do
+ bf1 = Native.new(:size => 10)
+ bf1.insert("test")
+
+ bf2 = Native.new(:size => 20)
+ bf2.insert("test")
+
+ proc {bf1 & bf2}.should raise_error(ArgumentError)
+ end
+
it "should return union with other filter" do
- bf1 = Native.new
+ bf1 = Native.new(:seed => 1)
bf1.insert("test")
bf1.insert("test1")
- bf2 = Native.new
+ bf2 = Native.new(:seed => 1)
bf2.insert("test")
bf2.insert("test2")
@@ -72,6 +82,16 @@
bf3.include?("test1").should be_true
bf3.include?("test2").should be_true
end
+
+ it "should raise an exception when union is to be computed for incompatible filters" do
+ bf1 = Native.new(:size => 10)
+ bf1.insert("test")
+
+ bf2 = Native.new(:size => 20)
+ bf2.insert("test")
+
+ proc {bf1 | bf2}.should raise_error(ArgumentError)
+ end
end
context "behave like counting bloom filter" do

0 comments on commit 504427b

Please sign in to comment.
Something went wrong with that request. Please try again.