more cardinality tracking and tests

This commit is contained in:
Matt Jaffee 2017-05-30 21:57:57 -05:00
parent 88e0e4d5b6
commit 487a369c6d
2 changed files with 36 additions and 4 deletions

View file

@ -1715,7 +1715,7 @@ func intersectRunRun(a, b *container) *container {
i++
}
}
if n < 4096 && len(output.runs) > n/2 {
if output.n < 4096 && len(output.runs) > output.n/2 {
output.runToArray()
} else if len(output.runs) > RunMaxSize {
output.runToBitmap()
@ -1737,6 +1737,7 @@ func intersectBitmapRun(a, b *container) *container {
}
}
}
output.n = len(output.array)
} 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
@ -1752,15 +1753,22 @@ func intersectBitmapRun(a, b *container) *container {
for valast >= vb.start && vastart <= vb.last {
if vastart >= vb.start && valast <= vb.last { // a within b
output.bitmap[i] = a.bitmap[i]
output.n += int(popcnt(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
bits := a.bitmap[i] & mask
output.bitmap[i] |= bits
output.n += int(popcnt(bits))
} else if vastart < vb.start { // a overlaps front of b
offset := 64 - (1 + valast - vb.start)
output.bitmap[i] |= (a.bitmap[i] >> offset) << offset
bits := (a.bitmap[i] >> offset) << offset
output.bitmap[i] |= bits
output.n += int(popcnt(bits))
} else if vb.start < vastart { // b overlaps front of a
offset := 64 - (1 + vb.last - vastart)
output.bitmap[i] |= (a.bitmap[i] << offset) >> offset
bits := (a.bitmap[i] << offset) >> offset
output.bitmap[i] |= bits
output.n += int(popcnt(bits))
}
// update loop vars
i++
@ -1768,6 +1776,9 @@ func intersectBitmapRun(a, b *container) *container {
valast = vastart + 63
}
}
if output.n < 4096 {
output.bitmapToArray()
}
}
return output
}

View file

@ -479,31 +479,37 @@ func TestIntersectBitmapRunBitmap(t *testing.T) {
bitmap []uint64
runs []interval32
exp []uint64
expN int
}{
{
bitmap: []uint64{1},
runs: []interval32{{start: 0, last: 0}, {start: 2, last: 5}, {start: 62, last: 71}, {start: 77, last: 4096}},
exp: []uint64{1},
expN: 1,
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}},
exp: []uint64{2},
expN: 1,
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}, {start: 10, last: 12}, {start: 61, last: 77}},
exp: []uint64{0xe000000000001C02},
expN: 7,
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}, {start: 61, last: 77}},
exp: []uint64{0xE000000000000002, 0x00000000000003FFF},
expN: 18,
},
{
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},
expN: 9,
},
}
for i, test := range tests {
@ -517,9 +523,15 @@ func TestIntersectBitmapRunBitmap(t *testing.T) {
exp[i] = v
}
ret := intersectBitmapRun(a, b)
if ret.isArray() {
ret.arrayToBitmap()
}
if !reflect.DeepEqual(ret.bitmap, exp) {
t.Fatalf("test #%v expected %v, but got %v", i, exp, ret.bitmap)
}
if ret.n != test.expN {
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, ret.n)
}
}
}
@ -531,31 +543,37 @@ func TestIntersectBitmapRunArray(t *testing.T) {
bitmap []uint64
runs []interval32
exp []uint32
expN int
}{
{
bitmap: []uint64{1},
runs: []interval32{{start: 0, last: 0}, {start: 2, last: 5}, {start: 62, last: 71}, {start: 77, last: 4096}},
exp: []uint32{0},
expN: 1,
},
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 1, last: 1}},
exp: []uint32{1},
expN: 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},
expN: 7,
},
{
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},
expN: 9,
},
{
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},
expN: 9,
},
}
for i, test := range tests {
@ -567,6 +585,9 @@ func TestIntersectBitmapRunArray(t *testing.T) {
if !reflect.DeepEqual(ret.array, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
}
if ret.n != test.expN {
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, ret.n)
}
}
}