diff --git a/roaring/roaring.go b/roaring/roaring.go index 86ee64fc5..ac49ee2f3 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -2033,18 +2033,18 @@ func (c *Container) runCountRange(start, end int32) (n int32) { break } // iv is superset of range - if int32(iv.start) < start && int32(iv.last) > end { + if int32(iv.start) <= start && int32(iv.last) >= end { return end - start } // iv is subset of range - if int32(iv.start) >= start && int32(iv.last) < end { + if int32(iv.start) >= start && int32(iv.last) <= end { n += iv.runlen() } - // iv overlaps beginning of range + // iv overlaps beginning of range without being a subset if int32(iv.start) < start && int32(iv.last) < end { n += int32(iv.last) - start + 1 } - // iv overlaps end of range + // iv overlaps end of range without being a subset if int32(iv.start) > start && int32(iv.last) >= end { n += end - int32(iv.start) } diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index 0ecd73021..27fbe8f29 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -147,6 +147,16 @@ func TestRunCountRange(t *testing.T) { c.add(10) c.add(11) + cnt = c.runCountRange(4, 8) + if cnt != 3 { + t.Fatalf("should get 3 from range overlaps front of interval, but got: %v", cnt) + } + + cnt = c.runCountRange(5, 8) + if cnt != 3 { + t.Fatalf("should get 3 from range within interval, but got: %v", cnt) + } + cnt = c.runCountRange(6, 8) if cnt != 2 { t.Fatalf("should get 2 from range within interval, but got: %v", cnt) @@ -162,6 +172,31 @@ func TestRunCountRange(t *testing.T) { t.Fatalf("should get 3 from range overlaps back of interval, but got: %v", cnt) } + cnt = c.runCountRange(8, 10) + if cnt != 2 { + t.Fatalf("should get 2 from range within interval, but got: %v", cnt) + } + + cnt = c.runCountRange(8, 11) + if cnt != 3 { + t.Fatalf("should get 3 from range within interval, but got: %v", cnt) + } + + cnt = c.runCountRange(8, 12) + if cnt != 4 { + t.Fatalf("should get 4 from range overlaps back of interval, but got: %v", cnt) + } + + cnt = c.runCountRange(5, 12) + if cnt != 7 { + t.Fatalf("should get 7 from interval within range, but got: %v", cnt) + } + + cnt = c.runCountRange(5, 11) + if cnt != 6 { + t.Fatalf("should get 6 from interval equal to range, but got: %v", cnt) + } + c.add(17) c.add(19) c.add(18) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index 836fd8de3..fbe952737 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -457,6 +457,12 @@ func TestBitmap_RunCountRange(t *testing.T) { if n := bm2.CountRange(3, 2); n != 0 { t.Fatalf("unexpected n: %d", n) } + + bm3 := roaring.NewFileBitmap(1, 2, 3, 4) + bm3.Optimize() // convert to runs + if n := bm3.CountRange(1, 3); n != 2 { + t.Fatalf("unexpected n: %d", n) + } } func TestBitmap_Intersection(t *testing.T) {