Merge pull request #849 from travisturner/flip-bitmap

implement container.flipBitmap() to improve differenceRunBitmap()
This commit is contained in:
Travis Turner 2017-09-25 17:10:37 -05:00 committed by GitHub
commit 6066c29ea7
2 changed files with 50 additions and 1 deletions

View file

@ -965,7 +965,7 @@ const RunMaxSize = 2048
// an array or RLE container is used, depending on the contents. For containers
// with more than 4,096 values, the values are encoded into bitmaps.
type container struct {
container_type byte // number of integers in container
container_type byte // array, bitmap, or run
n int // number of integers in container
array []uint16 // used for array containers
bitmap []uint64 // used for bitmap containers
@ -1625,6 +1625,19 @@ func (c *container) clone() *container {
return other
}
// flipBitmap returns a new bitmap containter containing the inverse of all
// bits in c.
func (c *container) flipBitmap() *container {
other := &container{bitmap: make([]uint64, bitmapN), container_type: ContainerBitmap}
for i, bitmap := range c.bitmap {
other.bitmap[i] = ^bitmap
}
other.n = other.count()
return other
}
// WriteTo writes c to w.
func (c *container) WriteTo(w io.Writer) (n int64, err error) {
if c.isArray() {
@ -2533,6 +2546,10 @@ func differenceRunBitmap(a, b *container) *container {
if a.n == 0 || b.n == 0 {
return a.clone()
}
// If a is full, difference is the flip of b.
if a.runs[0].start == 0 && a.runs[0].last == 65535 {
return b.flipBitmap()
}
itr := newBufBitmapIterator(newBitmapIterator(b.bitmap))
return differenceRunIterator(a, itr)
}

View file

@ -1869,6 +1869,38 @@ func TestXorRunRun(t *testing.T) {
}
}
func TestBitmapFlip(t *testing.T) {
c := &container{bitmap: make([]uint64, bitmapN), container_type: ContainerBitmap}
ttable := []struct {
original uint64
flipped uint64
}{
{0x0000000000000000, 0xFFFFFFFFFFFFFFFF},
{0xFFFFFFFFFFFFFFFF, 0x0000000000000000},
{0xFFFFFFFFFFFFFFF0, 0x000000000000000F},
{0xFFFFFFEFFFFFFFFF, 0x0000001000000000},
{0x0000001000000000, 0xFFFFFFEFFFFFFFFF},
}
expectedN := int(65536)
for i, tt := range ttable {
c.bitmap[i] = tt.original
expectedN -= int(popcount(tt.original))
}
o := c.flipBitmap()
for i, tt := range ttable {
if o.bitmap[i] != tt.flipped {
t.Fatalf("bitmapFlip calculation. expected %v, got %v", tt.flipped, o.bitmap[i])
}
}
if o.n != expectedN {
t.Fatalf("bitmapFlip calculation. expected count %v, got %v", expectedN, o.n)
}
}
func TestBitmapXorRange(t *testing.T) {
c := &container{bitmap: make([]uint64, bitmapN), container_type: ContainerBitmap}
tests := []struct {