diff --git a/ext/roaring/bitmap32.c b/ext/roaring/bitmap32.c index 29f02cf..3016197 100644 --- a/ext/roaring/bitmap32.c +++ b/ext/roaring/bitmap32.c @@ -238,6 +238,16 @@ static VALUE rb_roaring32_binary_op(VALUE self, VALUE other, binary_func func) { return TypedData_Wrap_Struct(cRoaringBitmap32, &roaring_type, result); } +typedef void binary_func_inplace(roaring_bitmap_t *, const roaring_bitmap_t *); +static VALUE rb_roaring32_binary_op_inplace(VALUE self, VALUE other, binary_func_inplace func) { + roaring_bitmap_t *self_data = get_bitmap(self); + roaring_bitmap_t *other_data = get_bitmap(other); + + func(self_data, other_data); + + return self; +} + typedef bool binary_func_bool(const roaring_bitmap_t *, const roaring_bitmap_t *); static VALUE rb_roaring32_binary_op_bool(VALUE self, VALUE other, binary_func_bool func) { roaring_bitmap_t *self_data = get_bitmap(self); @@ -247,6 +257,25 @@ static VALUE rb_roaring32_binary_op_bool(VALUE self, VALUE other, binary_func_bo return RBOOL(result); } +static VALUE rb_roaring32_and_inplace(VALUE self, VALUE other) +{ + return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_and_inplace); +} + +static VALUE rb_roaring32_or_inplace(VALUE self, VALUE other) +{ + return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_or_inplace); +} + +static VALUE rb_roaring32_xor_inplace(VALUE self, VALUE other) +{ + return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_xor_inplace); +} + +static VALUE rb_roaring32_andnot_inplace(VALUE self, VALUE other) +{ + return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_andnot_inplace); +} static VALUE rb_roaring32_and(VALUE self, VALUE other) { @@ -306,6 +335,11 @@ rb_roaring32_init(void) rb_define_method(cRoaringBitmap32, "each", rb_roaring32_each, 0); rb_define_method(cRoaringBitmap32, "[]", rb_roaring32_aref, 1); + rb_define_method(cRoaringBitmap32, "and!", rb_roaring32_and_inplace, 1); + rb_define_method(cRoaringBitmap32, "or!", rb_roaring32_or_inplace, 1); + rb_define_method(cRoaringBitmap32, "xor!", rb_roaring32_xor_inplace, 1); + rb_define_method(cRoaringBitmap32, "andnot!", rb_roaring32_andnot_inplace, 1); + rb_define_method(cRoaringBitmap32, "&", rb_roaring32_and, 1); rb_define_method(cRoaringBitmap32, "|", rb_roaring32_or, 1); rb_define_method(cRoaringBitmap32, "^", rb_roaring32_xor, 1); diff --git a/ext/roaring/bitmap64.c b/ext/roaring/bitmap64.c index 92d3283..720b297 100644 --- a/ext/roaring/bitmap64.c +++ b/ext/roaring/bitmap64.c @@ -243,6 +243,16 @@ static VALUE rb_roaring64_binary_op(VALUE self, VALUE other, binary_func func) { return TypedData_Wrap_Struct(cRoaringBitmap64, &roaring64_type, result); } +typedef void binary_func_inplace(roaring64_bitmap_t *, const roaring64_bitmap_t *); +static VALUE rb_roaring64_binary_op_inplace(VALUE self, VALUE other, binary_func_inplace func) { + roaring64_bitmap_t *self_data = get_bitmap(self); + roaring64_bitmap_t *other_data = get_bitmap(other); + + func(self_data, other_data); + + return self; +} + typedef bool binary_func_bool(const roaring64_bitmap_t *, const roaring64_bitmap_t *); static VALUE rb_roaring64_binary_op_bool(VALUE self, VALUE other, binary_func_bool func) { roaring64_bitmap_t *self_data = get_bitmap(self); @@ -252,6 +262,25 @@ static VALUE rb_roaring64_binary_op_bool(VALUE self, VALUE other, binary_func_bo return RBOOL(result); } +static VALUE rb_roaring64_and_inplace(VALUE self, VALUE other) +{ + return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_and_inplace); +} + +static VALUE rb_roaring64_or_inplace(VALUE self, VALUE other) +{ + return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_or_inplace); +} + +static VALUE rb_roaring64_xor_inplace(VALUE self, VALUE other) +{ + return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_xor_inplace); +} + +static VALUE rb_roaring64_andnot_inplace(VALUE self, VALUE other) +{ + return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_andnot_inplace); +} static VALUE rb_roaring64_and(VALUE self, VALUE other) { @@ -311,6 +340,11 @@ rb_roaring64_init(void) rb_define_method(cRoaringBitmap64, "each", rb_roaring64_each, 0); rb_define_method(cRoaringBitmap64, "[]", rb_roaring64_aref, 1); + rb_define_method(cRoaringBitmap64, "and!", rb_roaring64_and_inplace, 1); + rb_define_method(cRoaringBitmap64, "or!", rb_roaring64_or_inplace, 1); + rb_define_method(cRoaringBitmap64, "xor!", rb_roaring64_xor_inplace, 1); + rb_define_method(cRoaringBitmap64, "andnot!", rb_roaring64_andnot_inplace, 1); + rb_define_method(cRoaringBitmap64, "&", rb_roaring64_and, 1); rb_define_method(cRoaringBitmap64, "|", rb_roaring64_or, 1); rb_define_method(cRoaringBitmap64, "^", rb_roaring64_xor, 1); diff --git a/test/test_bitmaps.rb b/test/test_bitmaps.rb index b27fff4..ec08485 100644 --- a/test/test_bitmaps.rb +++ b/test/test_bitmaps.rb @@ -229,6 +229,7 @@ def test_and r1 = bitmap_class[1, 2, 3, 4] r2 = bitmap_class[3, 4, 5, 6] result = r1 & r2 + refute_same r1, result assert_equal [3, 4], result.to_a end @@ -236,6 +237,7 @@ def test_or r1 = bitmap_class[1, 2, 3, 4] r2 = bitmap_class[3, 4, 5, 6] result = r1 | r2 + refute_same r1, result assert_equal [1, 2, 3, 4, 5, 6], result.to_a end @@ -243,6 +245,7 @@ def test_xor r1 = bitmap_class[1, 2, 3, 4] r2 = bitmap_class[3, 4, 5, 6] result = r1 ^ r2 + refute_same r1, result assert_equal [1, 2, 5, 6], result.to_a end @@ -250,6 +253,39 @@ def test_difference r1 = bitmap_class[1, 2, 3, 4] r2 = bitmap_class[3, 4, 5, 6] result = r1 - r2 + refute_same r1, result + assert_equal [1, 2], result.to_a + end + + def test_and_inplace + r1 = bitmap_class[1, 2, 3, 4] + r2 = bitmap_class[3, 4, 5, 6] + result = r1.and!(r2) + assert_same r1, result + assert_equal [3, 4], result.to_a + end + + def test_or_inplace + r1 = bitmap_class[1, 2, 3, 4] + r2 = bitmap_class[3, 4, 5, 6] + result = r1.or!(r2) + assert_same r1, result + assert_equal [1, 2, 3, 4, 5, 6], result.to_a + end + + def test_xor_inplace + r1 = bitmap_class[1, 2, 3, 4] + r2 = bitmap_class[3, 4, 5, 6] + result = r1.xor!(r2) + assert_same r1, result + assert_equal [1, 2, 5, 6], result.to_a + end + + def test_difference_inplace + r1 = bitmap_class[1, 2, 3, 4] + r2 = bitmap_class[3, 4, 5, 6] + result = r1.andnot!(r2) + assert_same r1, result assert_equal [1, 2], result.to_a end