diff --git a/roaring/roaring.go b/roaring/roaring.go index 520a5ffe8..5cb592881 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -431,6 +431,12 @@ func (b *Bitmap) Size() int { // CountRange returns the number of bits set between [start, end). func (b *Bitmap) CountRange(start, end uint64) (n uint64) { + if roaringParanoia { + if start > end { + panic(fmt.Sprintf("counting in range but %v > %v", start, end)) + } + } + if b.Containers.Size() == 0 { return } @@ -452,11 +458,7 @@ func (b *Bitmap) CountRange(start, end uint64) (n uint64) { // TODO remove once we've validated this stuff works panic("should be impossible for k to be less than skey") } - if roaringParanoia { - if start > end { - panic(fmt.Sprintf("counting in range but %v > %v", start, end)) - } - } + // k > ekey handles the case when start > end and where start and end // are in different containers. Same container case is already handled above. if k > ekey { @@ -1380,6 +1382,9 @@ func (itr *Iterator) Seek(seek uint64) { itr.c = nil return } + itr.key, itr.c = itr.citer.Value() + itr.j = -1 + return } // Set iterator to next value in the Bitmap. itr.j = j @@ -1387,7 +1392,7 @@ func (itr *Iterator) Seek(seek uint64) { return } - // If it's a bitmap container then move to index before the value and call next(). + // If it's a bitmap container then move to index before the value. if itr.key > hb { itr.j = -1 return @@ -1540,14 +1545,14 @@ func (c *Container) count() (n int32) { // countRange counts the number of bits set between [start, end). func (c *Container) countRange(start, end int32) (n int32) { - if c == nil { - return 0 - } if roaringParanoia { if start > end { panic(fmt.Sprintf("counting in range but %v > %v", start, end)) } } + if c == nil { + return 0 + } if c.isArray() { return c.arrayCountRange(start, end) } else if c.isRun() { diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index d064d864f..12dd73d26 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -2132,19 +2132,16 @@ func TestIteratorBitmap(t *testing.T) { // Test for seeking value not in bitmap, where next container that the iterator should // go to has values with low bits smaller than the low bits of seek. - for i := uint64(65536*3 + 2); i < 65536*3+7; i++ { - if i != 65536*3+5 { + for i := uint64(65536*3 + 2); i < 65536*3+4110; i++ { + if i != 65536*3+5 && i != 65536*3+7 { if _, err := b.Add(i); err != nil { t.Fatalf("adding bit: %v", err) } } } - for i := uint64(65536*3 + 8); i < 65536*3+4110; i++ { - if _, err := b.Add(i); err != nil { - t.Fatalf("adding bit: %v", err) - } - } + // We expect this to be a bitmap container because more than + // 4096 bits have been set, but Optimize() has not been called. if !b.Containers.Get(3).isBitmap() { t.Fatalf("wrong container type") } @@ -2214,6 +2211,15 @@ func TestIteratorRuns(t *testing.T) { t.Fatalf("iterator did not seek correctly to end of run: %v\n", itr) } + itr.Seek(1007) + if !(itr.key == 1 && itr.j == -1 && itr.k == -1) { + t.Fatalf("iterator did not seek correctly to end of run: %v\n", itr) + } + val, eof = itr.Next() + if !(val == 100000 && !eof) { + t.Fatalf("iterator did not next correctly across containers: %v, %v", val, itr) + } + itr.Seek(100005) if !(itr.key == 1 && itr.j == 0 && itr.k == 4) { t.Fatalf("iterator did not seek correctly in multiple containers: %v\n", itr)