diff --git a/roaring/roaring.go b/roaring/roaring.go index 66ce116eb..ccbc3fc3c 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -2751,12 +2751,24 @@ func xor(a, b *container) *container { if a.isArray() { if b.isArray() { return xorArrayArray(a, b) + } else if b.isRun() { + return xorArrayRun(a, b) } else { return xorArrayBitmap(a, b) } + } else if a.isRun() { + if b.isArray() { + return xorArrayRun(b, a) + } else if b.isRun() { + return xorRunRun(a, b) + } else { + return xorBitmapRun(b, a) + } } else { if b.isArray() { return xorArrayBitmap(b, a) + } else if b.isRun() { + return xorBitmapRun(a, b) } else { return xorBitmapBitmap(a, b) } @@ -2813,7 +2825,6 @@ func xorBitmapBitmap(a, b *container) *container { output := &container{ bitmap: make([]uint64, bitmapN), } - for i := 0; i < bitmapN; i++ { v := a.bitmap[i] ^ b.bitmap[i] output.bitmap[i] = v @@ -3232,7 +3243,7 @@ func xorCompare(x *xorstm) (r1 interval32, has_data bool) { has_data = true } else if x.vb.last < x.va.start { //vb before x.vb_valid = false - r1 = x.va + r1 = x.vb has_data = true } else if x.va.start == x.vb.start && x.va.last == x.vb.last { // Equal x.va_valid = false diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index 48b9268e0..3cb9742c5 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -1624,9 +1624,41 @@ func TestXorArrayRun(t *testing.T) { b := &container{runs: []interval32{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}} exp := []uint32{1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 15, 16} - ret := xorArrayRun(a, b) + //ret := xorArrayRun(a, b) + ret := xor(a, b) if !reflect.DeepEqual(ret.array, exp) { - t.Fatalf("test expected %v, but got %v", exp, ret.array) + t.Fatalf("test #1 expected %v, but got %v", exp, ret.array) + } + + ret = xor(b, a) + if !reflect.DeepEqual(ret.array, exp) { + t.Fatalf("test #2 expected %v, but got %v", exp, ret.array) + } + c := &container{array: []uint32{1, 5, 10, 11, 12, 13, 14}} + exp = []uint32{1, 2, 3, 4, 6, 7, 8, 9, 11, 14, 15, 16} + ret = xor(b, c) + if !reflect.DeepEqual(ret.array, exp) { + t.Fatalf("test #3 expected %v, but got %v", exp, ret.array) + } + ret = xor(c, b) + if !reflect.DeepEqual(ret.array, exp) { + t.Fatalf("test #4 expected %v, but got %v", exp, ret.array) + } +} + +//special case that didn't fit the xorrunrun table testing below. +func TestXorRunRun1(t *testing.T) { + a := &container{} + b := &container{} + a.runs = []interval32{{start: 4, last: 10}} + b.runs = []interval32{{start: 5, last: 10}} + ret := xorRunRun(a, b) + if !reflect.DeepEqual(ret.array, []uint32{4}) { + t.Fatalf("test #1 expected %v, but got %v", []uint32{4}, ret.array) + } + ret = xorRunRun(b, a) + if !reflect.DeepEqual(ret.array, []uint32{4}) { + t.Fatalf("test #1 expected %v, but got %v", []uint32{4}, ret.array) } } @@ -1716,6 +1748,10 @@ func TestXorRunRun(t *testing.T) { if !reflect.DeepEqual(ret.runs, test.exp) { t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs) } + ret = xorRunRun(b, a) + if !reflect.DeepEqual(ret.runs, test.exp) { + t.Fatalf("test #%v.1 expected %v, but got %v", i, test.exp, ret.runs) + } } } @@ -1804,11 +1840,15 @@ func TestXorBitmapRun(t *testing.T) { for i, test := range tests { a.bitmap = test.bitmap b.runs = test.runs - ret := xorBitmapRun(a, b) - + //xorBitmapRun + ret := xor(a, b) if !reflect.DeepEqual(ret.bitmap, test.exp) { t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.bitmap) } + ret = xor(b, a) + if !reflect.DeepEqual(ret.bitmap, test.exp) { + t.Fatalf("test #%v.1 expected %v, but got %v", i, test.exp, ret.bitmap) + } } } diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index bafe3daad..7414651dd 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -217,6 +217,10 @@ func TestBitmap_Union1(t *testing.T) { if n := result.Count(); n != 75009 { t.Fatalf("unexpected n: %d", n) } + result = bm.Union(bm) + if n := result.Count(); n != 75007 { + t.Fatalf("unexpected n: %d", n) + } } @@ -267,6 +271,16 @@ func TestBitmap_Xor(t *testing.T) { if n := result.Count(); n != 75011 { t.Fatalf("unexpected n: %d", n) } + + result = bm0.Xor(bm1) + if n := result.Count(); n != 75011 { + t.Fatalf("unexpected n: %d", n) + } + + result = bm0.Xor(bm0) + if n := result.Count(); n != 0 { + t.Fatalf("unexpected n: %d", n) + } } func TestBitmap_Xor_ArrayArray(t *testing.T) { @@ -304,13 +318,18 @@ func TestBitmap_Xor_ArrayBitmap(t *testing.T) { result := bm0.Xor(bm1) if n := result.Count(); n != 4999 { - t.Fatalf("unexpected n: %d", n) + t.Fatalf("test #1 unexpected n: %d", n) + } + + result = bm1.Xor(bm0) + if n := result.Count(); n != 4999 { + t.Fatalf("test #2 unexpected n: %d", n) } //equivalence bitmap test result = result.Xor(result) if n := result.Count(); n > 0 { - t.Fatalf("unexpected n: %d", n) + t.Fatalf("test 3 unexpected n: %d", n) } empty := roaring.NewBitmap()