diff --git a/roaring/roaring.go b/roaring/roaring.go index a42c09e4e..903a04946 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -3152,8 +3152,11 @@ func xorArrayRun(a, b *container) *container { } else if va > vb.start { if va < vb.last { output.n += output.runAppendInterval(interval16{start: vb.start, last: va - 1}) - vb.start = va + 1 i++ + // candidate for overflow + // but no va must be less than max-1 + vb.start = va + 1 + if vb.start > vb.last { j++ } @@ -3162,15 +3165,19 @@ func xorArrayRun(a, b *container) *container { j++ } else { // va == vb.last vb.last-- - if vb.start < vb.last { + if vb.start <= vb.last { output.n += output.runAppendInterval(vb) } j++ i++ } - } else { - vb.start++ + } else { // we know va == vb.start + if vb.start == maxContainerVal { // protect overflow + j++ + } else { + vb.start++ + } i++ } } diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index 74dcc8992..6ee171fb4 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -1736,6 +1736,31 @@ func TestXorArrayRun(t *testing.T) { if !reflect.DeepEqual(ret.runs, expr) { t.Fatalf("test #4 expected %v, but got %v", exp, ret.array) } + + a = &container{array: []uint16{65535}, container_type: ContainerArray} + b = &container{runs: []interval16{{start: 65534, last: 65535}}, container_type: ContainerRun} + exp = []uint16{65534} + ret = xor(a, b) + if !reflect.DeepEqual(ret.array, exp) { + t.Fatalf("test #5 expected %v, but got %v", exp, ret.array) + } + + ret = xor(b, a) + if !reflect.DeepEqual(ret.array, exp) { + t.Fatalf("test #6 expected %v, but got %v", exp, ret.array) + } + + b = &container{runs: []interval16{{start: 65535, last: 65535}}, container_type: ContainerRun} + exp = []uint16{} + ret = xor(a, b) + if !reflect.DeepEqual(ret.array, exp) { + t.Fatalf("test #7 expected %v, but got %v", exp, ret.array) + } + + ret = xor(b, a) + if !reflect.DeepEqual(ret.array, exp) { + t.Fatalf("test #8 expected %v, but got %v", exp, ret.array) + } } //special case that didn't fit the xorrunrun table testing below.