Add fast check for empty conversions

This commit is contained in:
Alan Bernstein 2017-06-15 11:43:28 -05:00 committed by Matt Jaffee
parent 971d60617b
commit 371f36fb76
2 changed files with 106 additions and 3 deletions

View file

@ -1469,6 +1469,14 @@ func (c *container) runMax() uint32 {
// bitmapToArray converts from bitmap format to array format.
func (c *container) bitmapToArray() {
c.array = make([]uint32, 0, c.n)
// return early if empty
if c.n == 0 {
c.bitmap = nil
c.mapped = false
return
}
for i, bitmap := range c.bitmap {
for bitmap != 0 {
t := bitmap & -bitmap
@ -1483,6 +1491,14 @@ func (c *container) bitmapToArray() {
// arrayToBitmap converts from array format to bitmap format.
func (c *container) arrayToBitmap() {
c.bitmap = make([]uint64, bitmapN)
// return early if empty
if c.n == 0 {
c.array = nil
c.mapped = false
return
}
for _, v := range c.array {
c.bitmap[int(v)/64] |= (uint64(1) << uint(v%64))
}
@ -1493,6 +1509,14 @@ func (c *container) arrayToBitmap() {
// runToBitmap converts from RLE format to bitmap format.
func (c *container) runToBitmap() {
c.bitmap = make([]uint64, bitmapN)
// return early if empty
if c.n == 0 {
c.runs = nil
c.mapped = false
return
}
for _, r := range c.runs {
// TODO is there a faster way ?!?!!
for v := r.start; v <= r.last; v++ {
@ -1505,9 +1529,16 @@ func (c *container) runToBitmap() {
// bitmapToRun converts from bitmap format to RLE format.
func (c *container) bitmapToRun() {
numRuns := c.bitmapCountRuns() // TODO test
// return early if empty
if c.n == 0 {
c.runs = make([]interval32, 0)
c.bitmap = nil
c.mapped = false
return
}
numRuns := c.bitmapCountRuns()
c.runs = make([]interval32, 0, numRuns)
// TODO return early if no runs
current := c.bitmap[0]
var i, start, last uint32
@ -1553,7 +1584,15 @@ func (c *container) bitmapToRun() {
// arrayToRun converts from array format to RLE format.
func (c *container) arrayToRun() {
numRuns := c.arrayCountRuns() // TODO test
// return early if empty
if c.n == 0 {
c.runs = make([]interval32, 0)
c.array = nil
c.mapped = false
return
}
numRuns := c.arrayCountRuns()
c.runs = make([]interval32, 0, numRuns)
start := c.array[0]
for i, v := range c.array[1:] {
@ -1572,6 +1611,14 @@ func (c *container) arrayToRun() {
// runToArray converts from RLE format to array format.
func (c *container) runToArray() {
c.array = make([]uint32, 0, c.n)
// return early if empty
if c.n == 0 {
c.runs = nil
c.mapped = false
return
}
for _, r := range c.runs {
for v := r.start; v <= r.last; v++ {
c.array = append(c.array, v)

View file

@ -748,6 +748,10 @@ func TestArrayToBitmap(t *testing.T) {
array []uint32
exp []uint64
}{
{
array: []uint32{},
exp: []uint64{},
},
{
array: []uint32{0, 1, 2, 3},
exp: []uint64{0xF},
@ -761,6 +765,7 @@ func TestArrayToBitmap(t *testing.T) {
}
a.array = test.array
a.n = len(test.array)
a.arrayToBitmap()
if !reflect.DeepEqual(a.bitmap, exp) {
t.Fatalf("test #%v expected %v, but got %v", i, exp, a.bitmap)
@ -768,12 +773,47 @@ func TestArrayToBitmap(t *testing.T) {
}
}
func TestBitmapToArray(t *testing.T) {
a := &container{}
tests := []struct {
bitmap []uint64
exp []uint32
}{
{
bitmap: []uint64{},
exp: []uint32{},
},
{
bitmap: []uint64{0xF},
exp: []uint32{0, 1, 2, 3},
},
}
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.bitmapToArray()
if !reflect.DeepEqual(a.array, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.array)
}
}
}
func TestRunToBitmap(t *testing.T) {
a := &container{}
tests := []struct {
runs []interval32
exp []uint64
}{
{
runs: []interval32{},
exp: []uint64{},
},
{
runs: []interval32{{start: 0, last: 0}},
exp: []uint64{1},
@ -794,11 +834,14 @@ func TestRunToBitmap(t *testing.T) {
for i, test := range tests {
exp := make([]uint64, bitmapN)
n := 0
for i, v := range test.exp {
exp[i] = v
n += int(popcount(v))
}
a.runs = test.runs
a.n = n
a.runToBitmap()
if !reflect.DeepEqual(a.bitmap, exp) {
t.Fatalf("test #%v expected %v, but got %v", i, exp, a.bitmap)
@ -812,6 +855,11 @@ func TestBitmapToRun(t *testing.T) {
bitmap []uint64
exp []interval32
}{
{
// empty run
bitmap: []uint64{},
exp: []interval32{},
},
{
// single-bit run
bitmap: []uint64{1},
@ -870,6 +918,10 @@ func TestArrayToRun(t *testing.T) {
array []uint32
exp []interval32
}{
{
array: []uint32{},
exp: []interval32{},
},
{
array: []uint32{0},
exp: []interval32{{start: 0, last: 0}},
@ -900,6 +952,10 @@ func TestRunToArray(t *testing.T) {
runs []interval32
exp []uint32
}{
{
runs: []interval32{},
exp: []uint32{},
},
{
runs: []interval32{{start: 0, last: 0}},
exp: []uint32{0},