clean up some leftover bits from previous implementation

It used to be useful/desireable to set the other slices to nil when
setting a new slice type, it's no longer useful, take some of those
out.

Also reuse the already-computed run count when converting arrays
and bitmaps to runs.
This commit is contained in:
Seebs 2019-03-19 22:23:19 -05:00
parent 2af5d64e2c
commit 8041785ea4
2 changed files with 31 additions and 25 deletions

View file

@ -1683,7 +1683,7 @@ func (c *Container) optimize() {
c.arrayToBitmap()
} else if newType == containerRun {
statsHit("optimize/arrayToRun")
c.arrayToRun()
c.arrayToRun(runs)
} else {
statsHit("optimize/arrayUnchanged")
}
@ -1693,7 +1693,7 @@ func (c *Container) optimize() {
c.bitmapToArray()
} else if newType == containerRun {
statsHit("optimize/bitmapToRun")
c.bitmapToRun()
c.bitmapToRun(runs)
} else {
statsHit("optimize/bitmapUnchanged")
}
@ -1899,17 +1899,16 @@ func (c *Container) bitmapToArray() {
bitmap := c.bitmap()
c.setBitmap(nil)
c.typ = containerArray
array := make([]uint16, c.n)
c.setArray(array)
array = c.array()
c.mapped = false
// return early if empty
if c.n == 0 {
c.setArray(nil)
return
}
n := int32(0)
array := make([]uint16, c.n)
for i, word := range bitmap {
for word != 0 {
t := word & -word
@ -1928,13 +1927,13 @@ func (c *Container) bitmapToArray() {
panic("bitmap has fewer bits set than container.n")
}
}
c.setArray(array)
}
// arrayToBitmap converts from array format to bitmap format.
func (c *Container) arrayToBitmap() {
statsHit("arrayToBitmap")
array := c.array()
c.setArray(nil)
c.typ = containerBitmap
bitmap := make([]uint64, bitmapN)
c.setBitmap(bitmap)
@ -1954,7 +1953,6 @@ func (c *Container) arrayToBitmap() {
func (c *Container) runToBitmap() {
statsHit("runToBitmap")
runs := c.runs()
c.setRuns(nil)
bitmap := make([]uint64, bitmapN)
c.typ = containerBitmap
c.setBitmap(bitmap)
@ -1976,19 +1974,20 @@ func (c *Container) runToBitmap() {
}
// bitmapToRun converts from bitmap format to RLE format.
func (c *Container) bitmapToRun() {
func (c *Container) bitmapToRun(numRuns int32) {
statsHit("bitmapToRun")
bitmap := c.bitmap()
c.setBitmap(nil)
c.mapped = false
c.typ = containerRun
// return early if empty
if c.n == 0 {
c.setRuns(make([]interval16, 0))
c.setRuns(nil)
return
}
if numRuns == 0 {
numRuns = bitmapCountRuns(bitmap)
}
numRuns := bitmapCountRuns(bitmap)
runs := make([]interval16, 0, numRuns)
current := bitmap[0]
@ -2032,19 +2031,20 @@ func (c *Container) bitmapToRun() {
}
// arrayToRun converts from array format to RLE format.
func (c *Container) arrayToRun() {
func (c *Container) arrayToRun(numRuns int32) {
statsHit("arrayToRun")
array := c.array()
c.setArray(nil)
c.typ = containerRun
c.mapped = false
// return early if empty
if c.n == 0 {
c.setRuns(make([]interval16, 0))
c.setRuns(nil)
return
}
if numRuns == 0 {
numRuns = arrayCountRuns(array)
}
numRuns := arrayCountRuns(array)
runs := make([]interval16, 0, numRuns)
start := array[0]
for i, v := range array[1:] {
@ -2062,21 +2062,27 @@ func (c *Container) arrayToRun() {
// runToArray converts from RLE format to array format.
func (c *Container) runToArray() {
statsHit("runToArray")
array := make([]uint16, 0, c.n)
runs := c.runs()
c.setRuns(nil)
c.typ = containerArray
c.mapped = false
// return early if empty
if c.n == 0 {
c.setArray(array)
c.setArray(nil)
return
}
array := make([]uint16, c.n)
n := int32(0)
for _, r := range runs {
for v := int(r.start); v <= int(r.last); v++ {
array = append(array, uint16(v))
array[n] = uint16(v)
n++
}
}
if roaringParanoia {
if n != c.n {
panic("run has fewer bits set than container.n")
}
}
c.setArray(array)

View file

@ -244,12 +244,12 @@ func TestIntersectionCountArrayBitmap3(t *testing.T) {
t.Fatalf("test #1 intersectCountBitmapBitmap fail orig: %v new: %v exp: %v", res.n, res.count(), maxContainerVal+1)
}
a.bitmapToRun()
a.bitmapToRun(0)
res = intersectBitmapRun(b, a)
if res.n != res.count() || res.n != maxContainerVal+1 {
t.Fatalf("test #2 intersectCountBitmapRun fail orig: %v new: %v exp: %v", res.n, res.count(), maxContainerVal+1)
}
b.bitmapToRun()
b.bitmapToRun(0)
res = intersectRunRun(a, b)
n := intersectionCountRunRun(a, b)
if res.n != res.count() || res.n != maxContainerVal+1 || res.n != int32(n) {
@ -1125,7 +1125,7 @@ func TestBitmapToRun(t *testing.T) {
}
a.n = int32(n)
x := bitmap
a.bitmapToRun()
a.bitmapToRun(0)
if !reflect.DeepEqual(a.runs(), test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.runs())
}
@ -1164,7 +1164,7 @@ func TestArrayToRun(t *testing.T) {
a.typ = containerArray
a.setArray(test.array)
a.n = int32(len(test.array))
a.arrayToRun()
a.arrayToRun(0)
if !reflect.DeepEqual(a.runs(), test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.runs())
}
@ -3289,9 +3289,9 @@ func TestContainerCombinations(t *testing.T) {
}
} else if ct == containerRun {
if clone.isArray() {
clone.arrayToRun()
clone.arrayToRun(0)
} else if clone.isBitmap() {
clone.bitmapToRun()
clone.bitmapToRun(0)
}
if clone.n != cts[ct][exp].n {
t.Fatalf("test %s expected runs n=%d, but got n=%d", desc, cts[ct][exp].n, clone.n)