diff --git a/roaring/roaring.go b/roaring/roaring.go index 1a4d8d486..57825a5b2 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -907,13 +907,13 @@ func (c *container) bitmapCountRange(start, end uint32) int { // Special case when start and end fall in the same word. if i == j { offi, offj := start%64, 64-end%64 - n += popcount((c.bitmap[i] << offi) >> (offj + offi)) + n += popcount((c.bitmap[i] >> offi) << (offj + offi)) return int(n) } // Count partial starting word. if off := start % 64; off != 0 { - n += popcount(c.bitmap[i] << off) + n += popcount(c.bitmap[i] >> off) i++ } @@ -925,7 +925,7 @@ func (c *container) bitmapCountRange(start, end uint32) int { // Count partial ending word. if int(j) < len(c.bitmap) { if off := 64 - (end % 64); off != 0 { - n += popcount(c.bitmap[j] >> off) + n += popcount(c.bitmap[j] << off) } } diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index 17a35c5e1..5cff4a30f 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -5,27 +5,25 @@ import ( ) func TestBitmapCountRange(t *testing.T) { - c := container{bitmap: []uint64{1}} - cnt := c.bitmapCountRange(63, 65) - if cnt != 1 { - t.Fatalf("count of %v from 63 to 65 should be 1, but got %v", c.bitmap, cnt) + c := container{} + tests := []struct { + start uint32 + end uint32 + bitmap []uint64 + exp int + }{ + {start: 0, end: 1, bitmap: []uint64{1}, exp: 1}, + {start: 2, end: 7, bitmap: []uint64{0xFFFFFFFFFFFFFF18}, exp: 2}, + {start: 67, end: 68, bitmap: []uint64{0, 0x8}, exp: 1}, + {start: 1, end: 68, bitmap: []uint64{0x3, 0x8, 0xF}, exp: 2}, + {start: 1, end: 258, bitmap: []uint64{0xF, 0x8, 0xA, 0x4, 0xFFFFFFFFFFFFFFFF}, exp: 9}, + {start: 66, end: 71, bitmap: []uint64{0xF, 0xFFFFFFFFFFFFFF18}, exp: 2}, + {start: 63, end: 64, bitmap: []uint64{0x8000000000000000}, exp: 1}, } - - c = container{bitmap: []uint64{0, 0x8000000000000000}} - cnt = c.bitmapCountRange(65, 66) - if cnt != 0 { - t.Fatalf("count of %v from 65 to 66 should be 0, but got %v", c.bitmap, cnt) - } - - c = container{bitmap: []uint64{0, 0xF000000000000000}} - cnt = c.bitmapCountRange(65, 66) - if cnt != 1 { - t.Fatalf("count of %v from 65 to 66 should be 1, but got %v", c.bitmap, cnt) - } - - c = container{bitmap: []uint64{0x1, 0xFF00000000000000}} - cnt = c.bitmapCountRange(62, 66) - if cnt != 3 { - t.Fatalf("count of %v from 62 to 66 should be 3, but got %v", c.bitmap, cnt) + for i, test := range tests { + c.bitmap = test.bitmap + if ret := c.bitmapCountRange(test.start, test.end); ret != test.exp { + t.Fatalf("test #%v count of %v from %v to %v should be %v but got %v", i, test.bitmap, test.start, test.end, test.exp, ret) + } } }