mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 00:55:55 +00:00
implement intersectBitmapRun
wowza
This commit is contained in:
parent
8954a6ae8c
commit
250e8f6f5b
2 changed files with 144 additions and 2 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue