mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
cleat up flipBitmap and add tests
This commit is contained in:
parent
3a17b30e7d
commit
23f5c7166b
3 changed files with 66 additions and 48 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue