Skip to content

Commit

Permalink
Merge pull request #130 from maciej/rle-fast-and-array
Browse files Browse the repository at this point in the history
Port Java version of array-run container intersection algorithm
  • Loading branch information
lemire authored Jan 9, 2018
2 parents a817a13 + ce9cbe5 commit 0a6691a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 51 deletions.
10 changes: 1 addition & 9 deletions arraycontainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,19 +517,11 @@ func (ac *arrayContainer) iand(a container) container {
if x.isFull() {
return ac.clone()
}
return ac.iandRun16(x)
return x.andArray(ac)
}
panic("unsupported container type")
}

func (ac *arrayContainer) iandRun16(rc *runContainer16) container {
bc1 := ac.toBitmapContainer()
bc2 := newBitmapContainerFromRun(rc)
bc2.iandBitmap(bc1)
*ac = *newArrayContainerFromBitmap(bc2)
return ac
}

func (ac *arrayContainer) iandBitmap(bc *bitmapContainer) container {
pos := 0
c := ac.getCardinality()
Expand Down
60 changes: 25 additions & 35 deletions rlei.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,6 @@ func (rc *runContainer16) andBitmapContainer(bc *bitmapContainer) container {
return bc2.andBitmap(bc)
}

func (rc *runContainer16) andArray(ac *arrayContainer) container {
bc1 := ac.toBitmapContainer()
bc2 := newBitmapContainerFromRun(rc)
return bc2.andBitmap(bc1)
}

func (rc *runContainer16) andArrayCardinality(ac *arrayContainer) int {
pos := 0
answer := 0
Expand Down Expand Up @@ -105,7 +99,7 @@ func (rc *runContainer16) iand(a container) container {
case *runContainer16:
return rc.inplaceIntersect(c)
case *arrayContainer:
return rc.iandArray(c)
return rc.andArray(c)
case *bitmapContainer:
return rc.iandBitmapContainer(c)
}
Expand All @@ -127,38 +121,34 @@ func (rc *runContainer16) iandBitmapContainer(bc *bitmapContainer) container {
return rc
}

func (rc *runContainer16) iandArray(ac *arrayContainer) container {

bc1 := newBitmapContainerFromRun(rc)
bc2 := ac.toBitmapContainer()
and := bc1.andBitmap(bc2)
var rc2 *runContainer16
switch x := and.(type) {
case *bitmapContainer:
rc2 = newRunContainer16FromBitmapContainer(x)
case *arrayContainer:
rc2 = newRunContainer16FromArray(x)
case *runContainer16:
rc2 = x
default:
panic("unknown container type")
func (rc *runContainer16) andArray(ac *arrayContainer) container {
if len(rc.iv) == 0 {
return newArrayContainer()
}
*rc = *rc2
return rc

/*
// TODO: optimize by doing less allocation, possibly?
out := newRunContainer16()
for _, p := range rc.iv {
for i := p.start; i <= p.last; i++ {
if ac.contains(i) {
out.Add(i)
}
acCardinality := ac.getCardinality()
c := newArrayContainerCapacity(acCardinality)

for rlePos, arrayPos := 0, 0; arrayPos < acCardinality; {
iv := rc.iv[rlePos]
arrayVal := ac.content[arrayPos]

for iv.last() < arrayVal {
rlePos++
if rlePos == len(rc.iv) {
return c
}
iv = rc.iv[rlePos]
}
*rc = *out
return rc
*/

if iv.start > arrayVal {
arrayPos = advanceUntil(ac.content, arrayPos, len(ac.content), iv.start)
} else {
c.content = append(c.content, arrayVal)
arrayPos++
}
}
return c
}

func (rc *runContainer16) andNot(a container) container {
Expand Down
21 changes: 14 additions & 7 deletions rlei_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,13 +402,13 @@ func TestRle16RandomInplaceIntersectAgainstOtherContainers014(t *testing.T) {
// vs runContainer
rcb := newRunContainer16FromVals(false, b...)

rcVsBcIsect := rc.Clone()
rcVsAcIsect := rc.Clone()
rcVsRcbIsect := rc.Clone()
var rcVsBcIsect container = rc.Clone()
var rcVsAcIsect container = rc.Clone()
var rcVsRcbIsect container = rc.Clone()

rcVsBcIsect.iand(bc)
rcVsAcIsect.iand(ac)
rcVsRcbIsect.iand(rcb)
rcVsBcIsect = rcVsBcIsect.iand(bc)
rcVsAcIsect = rcVsAcIsect.iand(ac)
rcVsRcbIsect = rcVsRcbIsect.iand(rcb)

p("rcVsBcIsect is %v", rcVsBcIsect)
p("rcVsAcIsect is %v", rcVsAcIsect)
Expand Down Expand Up @@ -1603,7 +1603,6 @@ type twofer struct {
}

func TestAllContainerMethodsAllContainerTypesWithData067(t *testing.T) {

Convey("each of the container methods that takes two containers should handle all 3x3==9 possible ways of being called -- and return results that agree with each other", t, func() {

//rleVerbose = true
Expand Down Expand Up @@ -1688,6 +1687,14 @@ func TestAllContainerMethodsAllContainerTypesWithData067(t *testing.T) {

z := c1.name

// In-place operation are best effort
// User should not assume the receiver is modified, returned container has to be used
if strings.HasPrefix(z, "i") {
c1.cn = res1
c2.cn = res2
c3.cn = res3
}

if strings.HasPrefix(z, "lazy") {
// on purpose, the lazy functions
// do not scan to update their cardinality
Expand Down

0 comments on commit 0a6691a

Please sign in to comment.