mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-09 22:51:02 +00:00
bitmap/run support for rle
This commit is contained in:
parent
bf7a1bc08a
commit
93a7320cd9
2 changed files with 134 additions and 0 deletions
|
|
@ -2252,6 +2252,32 @@ func (c *container) bitmapSetRange(i, j uint64) {
|
|||
}
|
||||
}
|
||||
|
||||
// xor's all bits in [i, j] with all true (inclusive) (c must be a bitmap container).
|
||||
func (c *container) bitmapXorRange(i, j uint64) {
|
||||
j += 1
|
||||
x := i / 64
|
||||
y := (j - 1) / 64
|
||||
var X uint64 = maxBitmap << (i % 64)
|
||||
var Y uint64 = maxBitmap >> (64 - (j % 64))
|
||||
if x == y {
|
||||
cnt := popcnt(c.bitmap[x])
|
||||
c.bitmap[x] ^= (X & Y) //// flip
|
||||
c.n += int(popcnt(c.bitmap[x]) - cnt)
|
||||
} else {
|
||||
cnt := popcnt(c.bitmap[x])
|
||||
c.bitmap[x] ^= X
|
||||
c.n += int(popcnt(c.bitmap[x]) - cnt)
|
||||
for i := x + 1; i < y; i++ {
|
||||
cnt = popcnt(c.bitmap[i])
|
||||
c.bitmap[i] ^= maxBitmap
|
||||
c.n += int(popcnt(c.bitmap[i]) - cnt)
|
||||
}
|
||||
cnt = popcnt(c.bitmap[y])
|
||||
c.bitmap[y] ^= Y
|
||||
c.n += int(popcnt(c.bitmap[y]) - cnt)
|
||||
}
|
||||
}
|
||||
|
||||
// zeroes all bits in [i, j] (inclusive) (c must be a bitmap container)
|
||||
func (c *container) bitmapZeroRange(i, j uint64) {
|
||||
j += 1
|
||||
|
|
@ -3152,3 +3178,18 @@ func xorRunRun(a, b *container) *container {
|
|||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// xorRunRun computes the exclusive or of a bitmap and a run container.
|
||||
func xorBitmapRun(a, b *container) *container {
|
||||
output := a.clone()
|
||||
for j := 0; j < len(b.runs); j++ {
|
||||
output.bitmapXorRange(uint64(b.runs[j].start), uint64(b.runs[j].last))
|
||||
}
|
||||
|
||||
if output.n < ArrayMaxSize && len(output.runs) > output.n/2 {
|
||||
output.runToArray()
|
||||
} else if len(output.runs) > RunMaxSize {
|
||||
output.runToBitmap()
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1363,3 +1363,96 @@ func TestXorRunRun(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBitmapFlipRange(t *testing.T) {
|
||||
c := &container{bitmap: make([]uint64, bitmapN)}
|
||||
tests := []struct {
|
||||
bitmap []uint64
|
||||
start uint64
|
||||
last uint64
|
||||
exp []uint64
|
||||
expN int
|
||||
}{
|
||||
{
|
||||
bitmap: []uint64{0x0000000000000000},
|
||||
start: 0,
|
||||
last: 2,
|
||||
exp: []uint64{0x0000000000000007},
|
||||
expN: 3,
|
||||
},
|
||||
{
|
||||
bitmap: []uint64{0xF1},
|
||||
start: 4,
|
||||
last: 8,
|
||||
exp: []uint64{0x101},
|
||||
expN: 2,
|
||||
},
|
||||
{
|
||||
bitmap: []uint64{0xAA},
|
||||
start: 0,
|
||||
last: 7,
|
||||
exp: []uint64{0x55},
|
||||
expN: 4,
|
||||
},
|
||||
{
|
||||
bitmap: []uint64{0x0, 0x0000000000000000, 0x0000000000000000},
|
||||
start: 63,
|
||||
last: 128,
|
||||
exp: []uint64{0x8000000000000000, 0xFFFFFFFFFFFFFFFF, 0x000000000000001},
|
||||
expN: 66,
|
||||
},
|
||||
{
|
||||
bitmap: []uint64{0x0, 0x00000000000000FF, 0x0000000000000000},
|
||||
start: 63,
|
||||
last: 128,
|
||||
exp: []uint64{0x8000000000000000, 0xFFFFFFFFFFFFFF00, 0x000000000000001},
|
||||
expN: 58,
|
||||
},
|
||||
{
|
||||
bitmap: []uint64{0x0, 0x0, 0x0},
|
||||
start: 129,
|
||||
last: 131,
|
||||
exp: []uint64{0x0000000000000000, 0x0000000000000000, 0x00000000000000E},
|
||||
expN: 3,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
for i, v := range test.bitmap {
|
||||
c.bitmap[i] = v
|
||||
}
|
||||
c.n = c.countRange(0, 65535)
|
||||
c.bitmapXorRange(test.start, test.last)
|
||||
if !reflect.DeepEqual(c.bitmap[:len(test.exp)], test.exp) {
|
||||
t.Fatalf("test %#v expected %x, got %x", i, test.exp, c.bitmap[:len(test.bitmap)])
|
||||
}
|
||||
if test.expN != c.n {
|
||||
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, c.n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestXorBitmapRun(t *testing.T) {
|
||||
a := &container{}
|
||||
b := &container{}
|
||||
tests := []struct {
|
||||
bitmap []uint64
|
||||
runs []interval32
|
||||
exp []uint64
|
||||
}{
|
||||
{bitmap: []uint64{0x0, 0x0, 0x0},
|
||||
runs: []interval32{{start: 129, last: 131}},
|
||||
exp: []uint64{0x0, 0x0, 0x00000000000000E},
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
a.bitmap = test.bitmap
|
||||
b.runs = test.runs
|
||||
ret := xorBitmapRun(a, b)
|
||||
|
||||
if !reflect.DeepEqual(ret.bitmap, test.exp) {
|
||||
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue