diff --git a/roaring/roaring.go b/roaring/roaring.go index 2210da15f..a18a0ae09 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -2479,7 +2479,7 @@ func differenceArrayRun(a, b *container) *container { j := 0 // run index // keep all array elements before beginning of runs - for ; i < int(b.runs[j].start); i++ { + for ; i < len(a.array) && a.array[i] < b.runs[j].start; i++ { output.array = append(output.array, a.array[i]) } @@ -2490,7 +2490,7 @@ func differenceArrayRun(a, b *container) *container { output.array = append(output.array, a.array[i]) } // update current run - if i >= int(b.runs[j].last) { + if a.array[i] >= b.runs[j].last { j++ if j == len(b.runs) { break @@ -2498,10 +2498,10 @@ func differenceArrayRun(a, b *container) *container { } } i++ - - // keep all array elements after end of runs - output.array = append(output.array, a.array[i:]...) - + if i < len(a.array) { + // keep all array elements after end of runs + output.array = append(output.array, a.array[i:]...) + } return output } diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index 0b103ae5f..2a79a95b8 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -615,6 +615,140 @@ func TestIntersectBitmapRunArray(t *testing.T) { } +func TestUnionMixed(t *testing.T) { + a := &container{} + b := &container{} + c := &container{} + + a.runs = []interval32{{start: 5, last: 10}} + a.n = 6 + b.array = []uint32{1, 4, 5, 7, 10, 11, 12} + b.n = 7 + res := union(a, b) + if !reflect.DeepEqual(res.array, []uint32{1, 4, 5, 6, 7, 8, 9, 10, 11, 12}) { + t.Fatalf("test #1 expected %v, but got %v", []uint32{1, 4, 5, 6, 7, 8, 9, 10, 11, 12}, res.array) + } + res = union(b, a) + if !reflect.DeepEqual(res.array, []uint32{1, 4, 5, 6, 7, 8, 9, 10, 11, 12}) { + t.Fatalf("test #2 expected %v, but got %v", []uint32{1, 4, 5, 6, 7, 8, 9, 10, 11, 12}, res.array) + } + + res = union(a, a) + if !reflect.DeepEqual(res.runs, []interval32{{start: 5, last: 10}}) { + t.Fatalf("test #3 expected %v, but got %v", []interval32{{start: 5, last: 10}}, res.runs) + } + c.bitmap = []uint64{0x3} + c.n = 2 + res = union(c, a) + if !reflect.DeepEqual(res.bitmap, []uint64{2019}) { + t.Fatalf("test #4 expected %v, but got %v", []uint64{2019}, res.bitmap) + } + res = union(a, c) + if !reflect.DeepEqual(res.bitmap, []uint64{2019}) { + t.Fatalf("test #5 expected %v, but got %v", []uint64{2019}, res.bitmap) + } + res = union(b, c) + if !reflect.DeepEqual(res.array, []uint32{0, 1, 4, 5, 7, 10, 11, 12}) { + t.Fatalf("test #6 expected %v, but got %v", []uint32{0, 1, 4, 5, 7, 10, 11, 12}, res.array) + } + res = union(c, b) + if !reflect.DeepEqual(res.array, []uint32{0, 1, 4, 5, 7, 10, 11, 12}) { + t.Fatalf("test #6 expected %v, but got %v", []uint32{0, 1, 4, 5, 7, 10, 11, 12}, res.array) + } + +} +func TestIntersectMixed(t *testing.T) { + a := &container{} + b := &container{} + c := &container{} + + a.runs = []interval32{{start: 5, last: 10}} + a.n = 6 + b.array = []uint32{1, 4, 5, 7, 10, 11, 12} + b.n = 7 + res := intersect(a, b) + if !reflect.DeepEqual(res.array, []uint32{5, 7, 10}) { + t.Fatalf("test #1 expected %v, but got %v", []uint32{5, 7, 10}, res.array) + } + res = intersect(b, a) + if !reflect.DeepEqual(res.array, []uint32{5, 7, 10}) { + t.Fatalf("test #1 expected %v, but got %v", []uint32{5, 7, 10}, res.array) + } + + res = intersect(a, a) + if !reflect.DeepEqual(res.runs, []interval32{{start: 5, last: 10}}) { + t.Fatalf("test #3 expected %v, but got %v", []interval32{{start: 5, last: 10}}, res.runs) + } + c.bitmap = []uint64{0x60} + c.n = 2 + res = intersect(c, a) + if !reflect.DeepEqual(res.array, []uint32{5, 6}) { + t.Fatalf("test #4 expected %v, but got %v", []uint32{6}, res.array) + } + + res = intersect(a, c) + if !reflect.DeepEqual(res.array, []uint32{5, 6}) { + t.Fatalf("test #5 expected %v, but got %v", []uint32{6}, res.array) + } + + res = intersect(b, c) + if !reflect.DeepEqual(res.array, []uint32{5}) { + t.Fatalf("test #6 expected %v, but got %v", []uint32{5}, res.array) + } + res = intersect(c, b) + if !reflect.DeepEqual(res.array, []uint32{5}) { + t.Fatalf("test #7 expected %v, but got %v", []uint32{5}, res.array) + } + +} +func TestDifferenceMixed(t *testing.T) { + a := &container{} + b := &container{} + c := &container{} + + a.runs = []interval32{{start: 5, last: 10}} + a.n = a.runCountRange(0, 100) + + b.array = []uint32{1, 4, 5, 7, 10, 11, 12} + b.n = len(b.array) + res := difference(a, b) + + if !reflect.DeepEqual(res.array, []uint32{6, 8, 9}) { + t.Fatalf("test #1 expected %v, but got %v", []uint32{6, 8, 9}, res.runs) + } + res = difference(b, a) + if !reflect.DeepEqual(res.array, []uint32{1, 4, 11, 12}) { + t.Fatalf("test #2 expected %v, but got %v", []uint32{1, 4, 11, 12}, res.array) + } + + res = difference(a, a) + if !reflect.DeepEqual(res.runs, []interval32{}) { + t.Fatalf("test #3 expected empty but got %v", res.runs) + } + c.bitmap = []uint64{0x64} + c.n = c.countRange(0, 100) + res = difference(c, a) + + if !reflect.DeepEqual(res.bitmap, []uint64{0x4}) { + t.Fatalf("test #4 expected %v, but got %v", []uint32{4}, res.bitmap) + } + + res = difference(a, c) + if !reflect.DeepEqual(res.runs, []interval32{{start: 7, last: 10}}) { + t.Fatalf("test #5 expected %v, but got %v", []interval32{{start: 7, last: 10}}, res.runs) + } + + res = difference(b, c) + if !reflect.DeepEqual(res.array, []uint32{1, 4, 7, 10, 11, 12}) { + t.Fatalf("test #6 expected %v, but got %v", []uint32{1, 4, 7, 10, 11, 12}, res.array) + } + res = difference(c, b) + if !reflect.DeepEqual(res.array, []uint32{2, 6}) { + t.Fatalf("test #7 expected %v, but got %v", []uint32{2, 6}, res.array) + } + +} + func TestUnionRunRun(t *testing.T) { a := &container{} b := &container{} diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index ba24ecd22..a86f636cb 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -194,6 +194,11 @@ func TestBitmap_Union1(t *testing.T) { if n := result.Count(); n != 2682675 { t.Fatalf("unexpected n: %d", n) } + bm := testBM() + result = bm.Union(bm0) + if n := result.Count(); n != 75009 { + t.Fatalf("unexpected n: %d", n) + } } @@ -237,6 +242,15 @@ func TestBitmap_Union(t *testing.T) { } } +func TestBitmap_Xor(t *testing.T) { + bm0 := testBM() + bm1 := roaring.NewBitmap(0, 1, 2, 3) + result := bm1.Xor(bm0) + if n := result.Count(); n != 75011 { + t.Fatalf("unexpected n: %d", n) + } +} + func TestBitmap_Xor_ArrayArray(t *testing.T) { bm0 := roaring.NewBitmap(0, 1000001, 1000002, 1000003) bm1 := roaring.NewBitmap(0, 50000, 1000001, 1000002) @@ -601,6 +615,7 @@ func TestIterator(t *testing.T) { //testBM creates a bitmap with 3 containers(an array,bitmap, and run) func testBM() *roaring.Bitmap { + bm := roaring.NewBitmap() //the array for i := uint64(0); i < 1024; i += 4 { @@ -618,6 +633,7 @@ func testBM() *roaring.Bitmap { for i := uint64(0); i < 65535; i += 1 { bm.Add((4 << 16) + i) } + //count 75007 return bm } @@ -635,6 +651,10 @@ func TestBitmapOffsetRange(t *testing.T) { } +func TestBitmapBufIterator(t *testing.T) { + +} + var benchmarkBitmapIntersectionCountData struct { a, b *roaring.Bitmap } @@ -706,3 +726,11 @@ func diff(a, b []uint64) string { } return "" } + +func TestBitmap_Intersect(t *testing.T) { + bm0 := testBM() + result := bm0.Intersect(bm0) + if bm0.Count() != result.Count() { + t.Fatalf("Counts do not match %d %d", bm0.Count(), result.Count()) + } +}