From 4848a99acaf1e7cd5db2c7c9f6cddda01deac4c1 Mon Sep 17 00:00:00 2001 From: Matt Jaffee Date: Tue, 30 May 2017 13:19:02 -0500 Subject: [PATCH] unionRunRun working - messy --- roaring/roaring.go | 66 +++++++++++++++++++++++++++++++- roaring/roaring_internal_test.go | 35 +++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/roaring/roaring.go b/roaring/roaring.go index 729cf3ec4..201e2be21 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -1865,7 +1865,71 @@ func unionArrayRun(a, b *container) *container { } func unionRunRun(a, b *container) *container { - return nil + na, nb := len(a.runs), len(b.runs) + if na == 0 { + return b.clone() + } else if nb == 0 { + return a.clone() + } + output := &container{ + runs: make([]interval32, 0, na+nb), + } + i, j := 0, 0 + if a.runs[0].start < b.runs[0].start { + output.runs = append(output.runs, a.runs[0]) + i = 1 + } else { + output.runs = append(output.runs, b.runs[0]) + j = 1 + } + for i < na && j < nb { + va, vb := a.runs[i], b.runs[j] + lastrun := output.runs[len(output.runs)-1] + if va.start < vb.start { + if va.start <= lastrun.last+1 { + if lastrun.last < va.last { + lastrun.last = va.last + output.runs[len(output.runs)-1] = lastrun + } + } else { + output.runs = append(output.runs, va) + } + i++ + } else { + if vb.start <= lastrun.last+1 { + if lastrun.last < vb.last { + lastrun.last = vb.last + output.runs[len(output.runs)-1] = lastrun + } + } else { + output.runs = append(output.runs, vb) + } + j++ + } + } + var k int + var rest []interval32 + if i < na { + k = i + rest = a.runs + } else { + k = j + rest = b.runs + } + for k < len(rest) { + vk := rest[k] + lastrun := output.runs[len(output.runs)-1] + if vk.start <= lastrun.last+1 { + if lastrun.last < vk.last { + lastrun.last = vk.last + output.runs[len(output.runs)-1] = lastrun + } + } else { + output.runs = append(output.runs, vk) + } + k++ + } + return output } func unionBitmapRun(a, b *container) *container { diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index 91e256e05..0231bf93f 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -525,3 +525,38 @@ func TestIntersectBitmapRunArray(t *testing.T) { } } + +func TestUnionRunRun(t *testing.T) { + a := &container{} + b := &container{} + tests := []struct { + aruns []interval32 + bruns []interval32 + exp []interval32 + }{ + { + aruns: []interval32{}, + bruns: []interval32{{start: 5, last: 10}}, + exp: []interval32{{start: 5, last: 10}}, + }, + { + aruns: []interval32{{start: 5, last: 12}}, + bruns: []interval32{{start: 5, last: 10}}, + exp: []interval32{{start: 5, last: 12}}, + }, + { + aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 12}}, + bruns: []interval32{{start: 5, last: 10}}, + exp: []interval32{{start: 1, last: 3}, {start: 5, last: 12}}, + }, + } + for i, test := range tests { + a.runs = test.aruns + b.runs = test.bruns + ret := unionRunRun(a, b) + if !reflect.DeepEqual(ret.runs, test.exp) { + t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs) + } + } + +}