diff --git a/roaring/roaring.go b/roaring/roaring.go index 0a91c4493..1631c7772 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -1214,7 +1214,7 @@ func intersectionCountArrayArray(a, b *container) (n uint64) { return n } -func intersectionCountArrayBitmap(a, b *container) (n uint64) { +func intersectionCountArrayBitmapOld(a, b *container) (n uint64) { // Copy array header so we can shrink it. array := a.array if len(array) == 0 { @@ -1256,6 +1256,18 @@ func intersectionCountArrayBitmap(a, b *container) (n uint64) { return n } +func intersectionCountArrayBitmap(a, b *container) (n uint64) { + for _, val := range a.array { + i := val / 64 + if i >= uint32(len(b.bitmap)) { + break + } + off := val % 64 + n += (b.bitmap[i] & (1 << off)) >> off + } + return n +} + func intersectionCountBitmapBitmap(a, b *container) (n uint64) { return popcntAndSlice(a.bitmap, b.bitmap) } diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index 5cff4a30f..8fd64cbcb 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -1,8 +1,6 @@ package roaring -import ( - "testing" -) +import "testing" func TestBitmapCountRange(t *testing.T) { c := container{} @@ -27,3 +25,48 @@ func TestBitmapCountRange(t *testing.T) { } } } + +func TestIntersectionCountArrayBitmap2(t *testing.T) { + a, b := &container{}, &container{} + tests := []struct { + array []uint32 + bitmap []uint64 + exp uint64 + }{ + { + array: []uint32{0}, + bitmap: []uint64{1}, + exp: 1, + }, + { + array: []uint32{0, 1}, + bitmap: []uint64{3}, + exp: 2, + }, + { + array: []uint32{64, 128, 129, 2000}, + bitmap: []uint64{932421, 2}, + exp: 0, + }, + { + array: []uint32{0, 65, 130, 195}, + bitmap: []uint64{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + exp: 4, + }, + { + array: []uint32{63, 120, 543, 639, 12000}, + bitmap: []uint64{0x8000000000000000, 0, 0, 0, 0, 0, 0, 0, 0, 0x8000000000000000}, + exp: 2, + }, + } + + for i, test := range tests { + a.array = test.array + b.bitmap = test.bitmap + ret1 := intersectionCountArrayBitmapOld(a, b) + ret2 := intersectionCountArrayBitmap(a, b) + if ret1 != ret2 || ret2 != test.exp { + t.Fatalf("test #%v intersectCountArrayBitmap fail orig: %v new: %v exp: %v", i, ret1, ret2, test.exp) + } + } +}