From ccef8be8440ffbf3b2627608d77851bcef503758 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Wed, 14 Jun 2017 13:52:57 -0500 Subject: [PATCH] added difference for run and array containers --- roaring/roaring.go | 55 +++++++++++++++++++++++++++++++- roaring/roaring_internal_test.go | 22 +++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/roaring/roaring.go b/roaring/roaring.go index a752670c3..5fc61f835 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -2394,6 +2394,7 @@ func difference(a, b *container) *container { } } +// differenceArrayArray computes the difference bween two arrays. func differenceArrayArray(a, b *container) *container { output := &container{} na, nb := len(a.array), len(b.array) @@ -2418,6 +2419,7 @@ func differenceArrayArray(a, b *container) *container { return output } +// differenceArrayRun computes the difference of an array from a run. func differenceArrayRun(a, b *container) *container { // func (ac *arrayContainer) iandNotRun16(rc *runContainer16) container { @@ -2458,6 +2460,7 @@ func differenceArrayRun(a, b *container) *container { return output } +// differenceBitmapRun computes the difference of an bitmap from a run. func differenceBitmapRun(a, b *container) *container { if a.n == 0 || b.n == 0 { return a.clone() @@ -2470,16 +2473,65 @@ func differenceBitmapRun(a, b *container) *container { return output } +// differenceRunArray computes the difference of an run from a array. func differenceRunArray(a, b *container) *container { - // TODO if a.n == 0 || b.n == 0 { return a.clone() } output := &container{runs: make([]interval32, 0, a.n)} + i := 0 + j := 0 + vr := a.runs[j] + working := true + for working { + switch { + case b.array[i] < vr.start: //before + case b.array[i] > vr.last: //after + if vr.start <= vr.last { + output.n += output.runAppendInterval(vr) + } + j++ + if j < len(a.runs) { + vr = a.runs[j] + } else { + working = false + } + case b.array[i] == vr.start: //begining of run + vr.start++ + case b.array[i] == a.runs[j].last: //end of run + vr.last-- + if vr.last >= vr.start { + output.n += output.runAppendInterval(vr) + } + j++ + if j < len(a.runs) { + vr = a.runs[j] + } else { + working = false + } + case b.array[i] > vr.start: //inside run + output.n += output.runAppendInterval(interval32{start: vr.start, last: b.array[i] - 1}) + vr.start = b.array[i] + 1 + + } + i++ + if i >= len(b.array) { + working = false + } + } + if vr.start <= vr.last { + output.n += output.runAppendInterval(vr) + } + if output.n < ArrayMaxSize && len(output.runs) > output.n/2 { + output.runToArray() + } else if len(output.runs) > RunMaxSize { + output.runToBitmap() + } return output } +// differenceRunBitmap computes the difference of an run from a bitmap. func differenceRunBitmap(a, b *container) *container { // TODO if a.n == 0 || b.n == 0 { @@ -2502,6 +2554,7 @@ func differenceRunBitmap(a, b *container) *container { return output } +// differenceRunRun computes the difference of two runs. func differenceRunRun(a, b *container) *container { if a.n == 0 || b.n == 0 { return a.clone() diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index c3d0c5ac8..ae1e2ccce 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -1113,7 +1113,6 @@ func TestDifferenceArrayRun(t *testing.T) { } } -/* func TestDifferenceRunArray(t *testing.T) { a := &container{} b := &container{} @@ -1127,6 +1126,21 @@ func TestDifferenceRunArray(t *testing.T) { array: []uint32{5, 6, 7, 8, 9, 10}, exp: []interval32{{start: 0, last: 4}, {start: 11, last: 12}}, }, + { + runs: []interval32{{start: 0, last: 12}}, + array: []uint32{0, 1, 2, 3}, + exp: []interval32{{start: 4, last: 12}}, + }, + { + runs: []interval32{{start: 0, last: 12}}, + array: []uint32{9, 10, 11, 12, 13}, + exp: []interval32{{start: 0, last: 8}}, + }, + { + runs: []interval32{{start: 1, last: 12}}, + array: []uint32{0, 9, 10, 11, 12, 13}, + exp: []interval32{{start: 1, last: 8}}, + }, } for i, test := range tests { a.runs = test.runs @@ -1134,12 +1148,14 @@ func TestDifferenceRunArray(t *testing.T) { b.array = test.array b.n = len(b.array) ret := differenceRunArray(a, b) - if !reflect.DeepEqual(ret.array, test.exp) { - t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array) + if !reflect.DeepEqual(ret.runs, test.exp) { + t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs) } } } +/* + func TestDifferenceRunBitmap(t *testing.T) { a := &container{} b := &container{bitmap: make([]uint64, bitmapN)}