mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-09 12:27:52 +00:00
Add implementations and minimal tests for bitmap-run conversions
This commit is contained in:
parent
ac5f776db9
commit
bff12f5ce1
2 changed files with 124 additions and 2 deletions
|
|
@ -1363,12 +1363,65 @@ func (c *container) arrayToBitmap() {
|
|||
c.mapped = false
|
||||
}
|
||||
|
||||
// runToBitmap converts from RLE format to bitmap format
|
||||
func (c *container) runToBitmap() {
|
||||
// TODO
|
||||
c.bitmap = make([]uint64, bitmapN)
|
||||
for _, r := range c.runs {
|
||||
// TODO is there a faster way ?!?!!
|
||||
for v := r.start; v <= r.last; v++ {
|
||||
c.bitmap[int(v)/64] |= (uint64(1) << uint(v%64))
|
||||
}
|
||||
}
|
||||
c.runs = nil
|
||||
c.mapped = false
|
||||
}
|
||||
|
||||
// bitmapToRun converts from bitmap format to RLE format
|
||||
func (c *container) bitmapToRun() {
|
||||
// TODO
|
||||
numRuns := c.n // TODO compute properly
|
||||
c.runs = make([]interval32, 0, numRuns)
|
||||
// TODO return early if no runs
|
||||
|
||||
current := c.bitmap[0]
|
||||
var i, start, last uint32
|
||||
for {
|
||||
// skip while empty
|
||||
for current == 0 && i < bitmapN-1 {
|
||||
i++
|
||||
current = c.bitmap[i]
|
||||
}
|
||||
|
||||
if current == 0 {
|
||||
break
|
||||
}
|
||||
currentStart := uint32(trailingZeroN(current))
|
||||
start = 64 * i + currentStart
|
||||
|
||||
// pad LSBs with 1s
|
||||
current = current | (current-1)
|
||||
|
||||
// find next 0
|
||||
for current == 0xFFFFFFFFFFFFFFFF && i < bitmapN-1 {
|
||||
i++
|
||||
current = c.bitmap[i]
|
||||
}
|
||||
|
||||
last = 0
|
||||
if current == 0xFFFFFFFFFFFFFFFF {
|
||||
last = 64*i + 64 // TODO verify
|
||||
c.runs = append(c.runs, interval32{start, last-1})
|
||||
break
|
||||
}
|
||||
currentLast := uint32(trailingZeroN(^current))
|
||||
last = 64 * i + currentLast
|
||||
c.runs = append(c.runs, interval32{start, last-1})
|
||||
|
||||
// pad LSBs with 0s
|
||||
current = current & (current+1)
|
||||
}
|
||||
|
||||
c.bitmap = nil
|
||||
c.mapped = false
|
||||
}
|
||||
|
||||
// arrayToRun converts from array format to RLE format
|
||||
|
|
|
|||
|
|
@ -731,6 +731,75 @@ func TestBitmapSetRange(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRunToBitmap(t *testing.T) {
|
||||
a := &container{}
|
||||
tests := []struct {
|
||||
runs []interval32
|
||||
exp []uint64
|
||||
}{
|
||||
{
|
||||
runs: []interval32{{start: 0, last: 0}},
|
||||
exp: []uint64{1},
|
||||
},
|
||||
{
|
||||
runs: []interval32{{start: 0, last: 4}},
|
||||
exp: []uint64{31},
|
||||
},
|
||||
{
|
||||
runs: []interval32{{start: 2, last: 2}, {start: 5, last: 7}, {start: 13, last: 14}, {start: 17, last: 17}},
|
||||
exp: []uint64{155876},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
exp := make([]uint64, bitmapN)
|
||||
for i, v := range test.exp {
|
||||
exp[i] = v
|
||||
}
|
||||
|
||||
a.runs = test.runs
|
||||
a.runToBitmap()
|
||||
if !reflect.DeepEqual(a.bitmap, exp) {
|
||||
t.Logf("test #%v expected %v, but got (%d) %v", i, exp, a.bitmap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBitmapToRun(t *testing.T) {
|
||||
a := &container{}
|
||||
tests := []struct {
|
||||
bitmap []uint64
|
||||
exp []interval32
|
||||
}{
|
||||
{
|
||||
bitmap: []uint64{1},
|
||||
exp: []interval32{{start: 0, last: 0}},
|
||||
},
|
||||
{
|
||||
bitmap: []uint64{31},
|
||||
exp: []interval32{{start: 0, last: 4}},
|
||||
},
|
||||
{
|
||||
bitmap: []uint64{155876},
|
||||
exp: []interval32{{start: 2, last: 2}, {start: 5, last: 7}, {start: 13, last: 14}, {start: 17, last: 17}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
a.bitmap = make([]uint64, bitmapN)
|
||||
n := 0
|
||||
for i, v := range test.bitmap {
|
||||
a.bitmap[i] = v
|
||||
n += int(popcount(v))
|
||||
}
|
||||
a.n = n
|
||||
a.bitmapToRun()
|
||||
if !reflect.DeepEqual(a.runs, test.exp) {
|
||||
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.runs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestArrayToRun(t *testing.T) {
|
||||
a := &container{}
|
||||
tests := []struct {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue