Merge pull request #2100 from PierreF/runCountRange-bug

Fix offset-by-1 in CountRange with continuous bits interval
This commit is contained in:
Kuba Podgórski 2020-03-17 18:57:27 +01:00 committed by GitHub
commit eb73042e82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 4 deletions

View file

@ -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)
}

View file

@ -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)

View file

@ -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) {