mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-09 04:17:51 +00:00
implement intersectionCounts for run containers
This commit is contained in:
parent
014005b5d5
commit
20cec1363b
2 changed files with 146 additions and 2 deletions
|
|
@ -1446,12 +1446,24 @@ func intersectionCount(a, b *container) uint64 {
|
|||
if a.isArray() {
|
||||
if b.isArray() {
|
||||
return intersectionCountArrayArray(a, b)
|
||||
} else if b.isRun() {
|
||||
return intersectionCountArrayRun(a, b)
|
||||
} else {
|
||||
return intersectionCountArrayBitmap(a, b)
|
||||
}
|
||||
} else if a.isRun() {
|
||||
if b.isArray() {
|
||||
return intersectionCountArrayRun(b, a)
|
||||
} else if b.isRun() {
|
||||
return intersectionCountRunRun(a, b)
|
||||
} else {
|
||||
return intersectionCountBitmapRun(b, a)
|
||||
}
|
||||
} else {
|
||||
if b.isArray() {
|
||||
return intersectionCountArrayBitmap(b, a)
|
||||
} else if b.isRun() {
|
||||
return intersectionCountBitmapRun(a, b)
|
||||
} else {
|
||||
return intersectionCountBitmapBitmap(a, b)
|
||||
}
|
||||
|
|
@ -1474,6 +1486,61 @@ func intersectionCountArrayArray(a, b *container) (n uint64) {
|
|||
return n
|
||||
}
|
||||
|
||||
func intersectionCountArrayRun(a, b *container) (n uint64) {
|
||||
na, nb := len(a.array), len(b.runs)
|
||||
for i, j := 0, 0; i < na && j < nb; {
|
||||
va, vb := a.array[i], b.runs[j]
|
||||
if va < vb.start {
|
||||
i++
|
||||
} else if va >= vb.start && va <= vb.last {
|
||||
i++
|
||||
n++
|
||||
} else if va > vb.last {
|
||||
j++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func intersectionCountRunRun(a, b *container) uint64 {
|
||||
var n uint32
|
||||
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 va.start > vb.last {
|
||||
// |--vb--| |--va--|
|
||||
j++
|
||||
} else if va.last > vb.last && va.start >= vb.start {
|
||||
// |--vb-|-|-va--|
|
||||
n += 1 + vb.last - va.start
|
||||
j++
|
||||
} else if va.last > vb.last && va.start < vb.start {
|
||||
// |--va|--vb--|--|
|
||||
n += 1 + vb.last - vb.start
|
||||
j++
|
||||
} else if va.last <= vb.last && va.start >= vb.start {
|
||||
// |--vb|--va--|--|
|
||||
n += 1 + va.last - va.start
|
||||
i++
|
||||
} else if va.last <= vb.last && va.start < vb.start {
|
||||
// |--va-|-|-vb--|
|
||||
n += 1 + va.last - vb.start
|
||||
i++
|
||||
}
|
||||
}
|
||||
return uint64(n)
|
||||
}
|
||||
|
||||
func intersectionCountBitmapRun(a, b *container) (n uint64) {
|
||||
for _, iv := range b.runs {
|
||||
n += uint64(a.bitmapCountRange(iv.start, iv.last+1))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func intersectionCountArrayBitmapOld(a, b *container) (n uint64) {
|
||||
// Copy array header so we can shrink it.
|
||||
array := a.array
|
||||
|
|
@ -1878,7 +1945,7 @@ func xorArrayBitmap(a, b *container) *container {
|
|||
}
|
||||
|
||||
if output.count() < ArrayMaxSize {
|
||||
output.convertToArray()
|
||||
output.bitmapToArray()
|
||||
}
|
||||
|
||||
return output
|
||||
|
|
@ -1896,7 +1963,7 @@ func xorBitmapBitmap(a, b *container) *container {
|
|||
}
|
||||
|
||||
if output.count() < ArrayMaxSize {
|
||||
output.convertToArray()
|
||||
output.bitmapToArray()
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,3 +273,80 @@ func TestRunMax(t *testing.T) {
|
|||
t.Fatalf("max for %v should be 0", c.runs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersectionCountArrayRun(t *testing.T) {
|
||||
a := &container{array: []uint32{1, 5, 10, 11, 12}}
|
||||
b := &container{runs: []interval32{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}}
|
||||
|
||||
ret := intersectionCountArrayRun(a, b)
|
||||
if ret != 3 {
|
||||
t.Fatalf("count of %v with %v should be 3, but got %v", a.array, b.runs, ret)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersectionCountBitmapRun(t *testing.T) {
|
||||
a := &container{bitmap: []uint64{1}}
|
||||
b := &container{runs: []interval32{{start: 63, last: 64}}}
|
||||
|
||||
ret := intersectionCountBitmapRun(a, b)
|
||||
if ret != 1 {
|
||||
t.Fatalf("count of %v with %v should be 1, but got %v", a.bitmap, b.runs, ret)
|
||||
}
|
||||
|
||||
a = &container{bitmap: []uint64{0xF0000001, 0xFF00000000000000, 0xFF000000000000F0, 0x0F0000}}
|
||||
b = &container{runs: []interval32{{start: 33, last: 35}, {start: 62, last: 69}, {start: 130, last: 150}, {start: 186, last: 300}}}
|
||||
|
||||
ret = intersectionCountBitmapRun(a, b)
|
||||
if ret != 22 {
|
||||
t.Fatalf("count of %v with %v should be 22, but got %v", a.bitmap, b.runs, ret)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersectionCountRunRun(t *testing.T) {
|
||||
a := &container{}
|
||||
b := &container{}
|
||||
tests := []struct {
|
||||
aruns []interval32
|
||||
bruns []interval32
|
||||
exp uint64
|
||||
}{
|
||||
{
|
||||
aruns: []interval32{},
|
||||
bruns: []interval32{{start: 3, last: 8}}, exp: 0},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}},
|
||||
bruns: []interval32{{start: 3, last: 8}}, exp: 6},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}},
|
||||
bruns: []interval32{{start: 1, last: 11}}, exp: 9},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}},
|
||||
bruns: []interval32{{start: 0, last: 2}}, exp: 1},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}},
|
||||
bruns: []interval32{{start: 1, last: 10}}, exp: 9},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}},
|
||||
bruns: []interval32{{start: 5, last: 12}}, exp: 6},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}},
|
||||
bruns: []interval32{{start: 10, last: 99}}, exp: 1},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}, {start: 44, last: 99}},
|
||||
bruns: []interval32{{start: 12, last: 14}}, exp: 0},
|
||||
{
|
||||
aruns: []interval32{{start: 2, last: 10}, {start: 12, last: 13}},
|
||||
bruns: []interval32{{start: 2, last: 10}, {start: 12, last: 13}}, exp: 11},
|
||||
{
|
||||
aruns: []interval32{{start: 8, last: 12}, {start: 15, last: 19}},
|
||||
bruns: []interval32{{start: 9, last: 9}, {start: 11, last: 17}}, exp: 6},
|
||||
}
|
||||
for i, test := range tests {
|
||||
a.runs = test.aruns
|
||||
b.runs = test.bruns
|
||||
ret := intersectionCountRunRun(a, b)
|
||||
if ret != test.exp {
|
||||
t.Fatalf("test #%v failed intersecting %v with %v should be %v, but got %v", i, test.aruns, test.bruns, test.exp, ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue