implement intersectBitmapRun

wowza
This commit is contained in:
Matt Jaffee 2017-05-25 16:53:26 -05:00
parent 8954a6ae8c
commit 250e8f6f5b
2 changed files with 144 additions and 2 deletions

View file

@ -1702,9 +1702,52 @@ func intersectRunRun(a, b *container) *container {
return output
}
// intersectBitmapRun returns an array container of the run container's
// cardinality is < 4096. Otherwise it returns a bitmap container.
func intersectBitmapRun(a, b *container) *container {
output := &container{}
// TODO
var output *container
if b.n < 4096 {
// output is array container
output = &container{}
for _, iv := range b.runs {
for i := iv.start; i <= iv.last; i++ {
if a.bitmapContains(i) {
output.array = append(output.array, i)
}
}
}
} else {
// right now this iterates through the runs and sets integers in the
// bitmap that are in the runs. alternately, we could zero out ranges in
// the bitmap which are between runs.
output = &container{
bitmap: make([]uint64, bitmapN),
}
for j := 0; j < len(b.runs); j++ {
vb := b.runs[j]
i := vb.start / 64 // index into a
vastart := 64 * i
valast := vastart + 63
for valast >= vb.start && vastart <= vb.last {
if vastart >= vb.start && valast <= vb.last { // a within b
output.bitmap[i] = a.bitmap[i]
} else if vb.start >= vastart && vb.last <= valast { // b within a
var mask uint64 = ((1 << (vb.last - vb.start + 1)) - 1) << (vb.start - vastart)
output.bitmap[i] |= a.bitmap[i] & mask
} else if vastart < vb.start { // a overlaps front of b
offset := 64 - (1 + valast - vb.start)
output.bitmap[i] |= (a.bitmap[i] >> offset) << offset
} else if vb.start < vastart { // b overlaps front of a
offset := 64 - (1 + vb.last - vastart)
output.bitmap[i] |= (a.bitmap[i] << offset) >> offset
}
// update loop vars
i++
vastart = 64 * i
valast = vastart + 63
}
}
}
return output
}

View file

@ -426,3 +426,102 @@ func TestIntersectRunRun(t *testing.T) {
}
}
func TestIntersectBitmapRunBitmap(t *testing.T) {
a := &container{bitmap: make([]uint64, bitmapN)}
b := &container{}
tests := []struct {
bitmap []uint64
runs []interval32
exp []uint64
}{
{
bitmap: []uint64{1},
runs: []interval32{{start: 0, last: 0}, {start: 2, last: 5}, {start: 62, last: 71}, {start: 77, last: 4096}},
exp: []uint64{1},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}},
exp: []uint64{2},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}, {start: 10, last: 12}, {start: 61, last: 77}},
exp: []uint64{0xe000000000001C02},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}, {start: 61, last: 77}},
exp: []uint64{0xE000000000000002, 0x00000000000003FFF},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 1, 1, 1, 0xA, 1, 1, 0, 1},
runs: []interval32{{start: 63, last: 10000}},
exp: []uint64{0x8000000000000000, 1, 1, 1, 0xA, 1, 1, 0, 1},
},
}
for i, test := range tests {
for i, v := range test.bitmap {
a.bitmap[i] = v
}
b.runs = test.runs
b.n = 4097 // ;)
exp := make([]uint64, bitmapN)
for i, v := range test.exp {
exp[i] = v
}
ret := intersectBitmapRun(a, b)
if !reflect.DeepEqual(ret.bitmap, exp) {
t.Fatalf("test #%v expected %v, but got %v", i, exp, ret.bitmap)
}
}
}
func TestIntersectBitmapRunArray(t *testing.T) {
a := &container{bitmap: make([]uint64, bitmapN)}
b := &container{}
tests := []struct {
bitmap []uint64
runs []interval32
exp []uint32
}{
{
bitmap: []uint64{1},
runs: []interval32{{start: 0, last: 0}, {start: 2, last: 5}, {start: 62, last: 71}, {start: 77, last: 4096}},
exp: []uint32{0},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}},
exp: []uint32{1},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}, {start: 10, last: 12}, {start: 61, last: 77}},
exp: []uint32{1, 10, 11, 12, 61, 62, 63},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}, {start: 61, last: 68}},
exp: []uint32{1, 61, 62, 63, 64, 65, 66, 67, 68},
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 1, 1, 1, 0xA, 1, 1, 0, 1},
runs: []interval32{{start: 63, last: 10000}},
exp: []uint32{63, 64, 128, 192, 257, 259, 320, 384, 512},
},
}
for i, test := range tests {
for i, v := range test.bitmap {
a.bitmap[i] = v
}
b.runs = test.runs
ret := intersectBitmapRun(a, b)
if !reflect.DeepEqual(ret.array, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
}
}
}