cleat up flipBitmap and add tests

This commit is contained in:
Travis Turner 2018-04-23 13:23:35 -05:00
parent 3a17b30e7d
commit 23f5c7166b
No known key found for this signature in database
GPG key ID: 7F08008DFD9314C9
3 changed files with 66 additions and 48 deletions

View file

@ -1674,19 +1674,6 @@ 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), containerType: 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() {
@ -1812,6 +1799,43 @@ type ContainerInfo struct {
Pointer unsafe.Pointer // offset within the mmap
}
// flip returns a new container containing the inverse of all
// bits in a.
func flip(a *container) *container {
if a.isArray() {
return flipArray(a)
} else if a.isRun() {
return flipRun(a)
} else {
return flipBitmap(a)
}
}
func flipArray(b *container) *container {
// TODO: actually implement this
x := b.clone()
x.arrayToBitmap()
return flipBitmap(x)
}
func flipBitmap(b *container) *container {
other := &container{bitmap: make([]uint64, bitmapN), containerType: ContainerBitmap}
for i, bitmap := range b.bitmap {
other.bitmap[i] = ^bitmap
}
other.n = other.count()
return other
}
func flipRun(b *container) *container {
// TODO: actually implement this
x := b.clone()
x.runToBitmap()
return flipBitmap(x)
}
func intersectionCount(a, b *container) int {
if a.isArray() {
if b.isArray() {
@ -2571,7 +2595,7 @@ RUNLOOP:
func differenceRunBitmap(a, b *container) *container {
// If a is full, difference is the flip of b.
if len(a.runs) > 0 && a.runs[0].start == 0 && a.runs[0].last == 65535 {
return b.flipBitmap()
return flipBitmap(b)
}
output := &container{containerType: ContainerRun}
output.n = a.n

View file

@ -220,8 +220,11 @@ func runEvenBitsSet() []interval16 {
///////////////////////////////////////////////////////////////////////////
// f is a container function taking either one or two containers as input
// func(a *container) *container
// func(a, b *container) *container
type testOp struct {
f func(a, b *container) *container
f interface{}
x string
y string
exp string

View file

@ -2020,38 +2020,6 @@ func TestXorRunRun(t *testing.T) {
}
}
func TestBitmapFlip(t *testing.T) {
c := &container{bitmap: make([]uint64, bitmapN), containerType: 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), containerType: ContainerBitmap}
tests := []struct {
@ -3185,12 +3153,24 @@ func TestContainerCombinations(t *testing.T) {
//{xor, "evenBitsSet", "outerBitsSet", ""},
{xor, "evenBitsSet", "oddBitsSet", "full"},
{xor, "evenBitsSet", "evenBitsSet", "empty"},
// flip
{flip, "empty", "", "full"},
{flip, "full", "", "empty"},
{flip, "firstBitSet", "", "firstBitUnset"},
{flip, "lastBitSet", "", "lastBitUnset"},
{flip, "firstBitUnset", "", "firstBitSet"},
{flip, "lastBitUnset", "", "lastBitSet"},
{flip, "innerBitsSet", "", "outerBitsSet"},
{flip, "outerBitsSet", "", "innerBitsSet"},
{flip, "oddBitsSet", "", "evenBitsSet"},
{flip, "evenBitsSet", "", "oddBitsSet"},
}
for _, testOp := range testOps {
for _, x := range containerTypes {
for _, y := range containerTypes {
desc := fmt.Sprintf("%s(%s/%s, %s/%s)", getFunctionName(testOp.f), cm[x], testOp.x, cm[y], testOp.y)
ret := testOp.f(cts[x][testOp.x], cts[y][testOp.y])
ret := runContainerFunc(testOp.f, cts[x][testOp.x], cts[y][testOp.y])
exp := testOp.exp
// Convert to all container types and check result.
@ -3240,3 +3220,14 @@ func TestContainerCombinations(t *testing.T) {
}
}
}
//func getFunc(func(a, b *container) *container, m, n *container) *container {
func runContainerFunc(f interface{}, c ...*container) *container {
switch f.(type) {
case func(*container) *container:
return f.(func(*container) *container)(c[0])
case func(*container, *container) *container:
return f.(func(a, b *container) *container)(c[0], c[1])
}
return nil
}