implement intersectRunRun

This commit is contained in:
Matt Jaffee 2017-05-19 08:22:56 -05:00
parent 0c3f61a426
commit 3e8030aee4
2 changed files with 69 additions and 1 deletions

View file

@ -1645,6 +1645,9 @@ func intersectArrayArray(a, b *container) *container {
return output
}
// intersectArrayRun computes the intersect of an array container and a run
// container. The return is always an array container (since it's guaranteed to
// be low-cardinality)
func intersectArrayRun(a, b *container) *container {
output := &container{}
na, nb := len(a.array), len(b.runs)
@ -1663,9 +1666,39 @@ func intersectArrayRun(a, b *container) *container {
return output
}
// intersectRunRun computes the intersect of two run containers. The output is
// always a run container, since it can't possible have more runs than either of
// the inputs. (note: it is possible that an array container would be better in
// some cases, but probably not worth complicating the implementation)
func intersectRunRun(a, b *container) *container {
output := &container{}
// TODO
na, nb := len(a.runs), len(b.runs)
for i, j := 0, 0; i < na && j < nb; {
va, vb := a.runs[i], b.runs[j]
if va.last < vb.start {
// |--va--| |--vb--|
i++
} else if vb.last < va.start {
// |--vb--| |--va--|
j++
} else if va.last > vb.last && va.start >= vb.start {
// |--vb-|-|-va--|
output.runs = append(output.runs, interval32{start: va.start, last: vb.last})
j++
} else if va.last > vb.last && va.start < vb.start {
// |--va|--vb--|--|
output.runs = append(output.runs, vb)
j++
} else if va.last <= vb.last && va.start >= vb.start {
// |--vb|--va--|--|
output.runs = append(output.runs, va)
i++
} else if va.last <= vb.last && va.start < vb.start {
// |--va-|-|-vb--|
output.runs = append(output.runs, interval32{start: vb.start, last: va.last})
i++
}
}
return output
}

View file

@ -390,3 +390,38 @@ func TestIntersectArrayRun(t *testing.T) {
}
}
}
func TestIntersectRunRun(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(nil),
},
{
aruns: []interval32{{start: 5, last: 12}},
bruns: []interval32{{start: 5, last: 10}},
exp: []interval32{{start: 5, last: 10}},
},
{
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: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 10}},
},
}
for i, test := range tests {
a.runs = test.aruns
b.runs = test.bruns
ret := intersectRunRun(a, b)
if !reflect.DeepEqual(ret.runs, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
}
}
}