Skip to content

Commit ce9cbe5

Browse files
committed
Port Java version of array-run container intersection algorithm
This commit ports the Java version of the array-run intersection algorithm. In a private benchmark the performance improves significantly.
1 parent ceab3d4 commit ce9cbe5

File tree

2 files changed

+26
-44
lines changed

2 files changed

+26
-44
lines changed

arraycontainer.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -517,19 +517,11 @@ func (ac *arrayContainer) iand(a container) container {
517517
if x.isFull() {
518518
return ac.clone()
519519
}
520-
return ac.iandRun16(x)
520+
return x.andArray(ac)
521521
}
522522
panic("unsupported container type")
523523
}
524524

525-
func (ac *arrayContainer) iandRun16(rc *runContainer16) container {
526-
bc1 := ac.toBitmapContainer()
527-
bc2 := newBitmapContainerFromRun(rc)
528-
bc2.iandBitmap(bc1)
529-
*ac = *newArrayContainerFromBitmap(bc2)
530-
return ac
531-
}
532-
533525
func (ac *arrayContainer) iandBitmap(bc *bitmapContainer) container {
534526
pos := 0
535527
c := ac.getCardinality()

rlei.go

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,6 @@ func (rc *runContainer16) andBitmapContainer(bc *bitmapContainer) container {
6262
return bc2.andBitmap(bc)
6363
}
6464

65-
func (rc *runContainer16) andArray(ac *arrayContainer) container {
66-
bc1 := ac.toBitmapContainer()
67-
bc2 := newBitmapContainerFromRun(rc)
68-
return bc2.andBitmap(bc1)
69-
}
70-
7165
func (rc *runContainer16) andArrayCardinality(ac *arrayContainer) int {
7266
pos := 0
7367
answer := 0
@@ -105,7 +99,7 @@ func (rc *runContainer16) iand(a container) container {
10599
case *runContainer16:
106100
return rc.inplaceIntersect(c)
107101
case *arrayContainer:
108-
return rc.iandArray(c)
102+
return rc.andArray(c)
109103
case *bitmapContainer:
110104
return rc.iandBitmapContainer(c)
111105
}
@@ -127,38 +121,34 @@ func (rc *runContainer16) iandBitmapContainer(bc *bitmapContainer) container {
127121
return rc
128122
}
129123

130-
func (rc *runContainer16) iandArray(ac *arrayContainer) container {
131-
132-
bc1 := newBitmapContainerFromRun(rc)
133-
bc2 := ac.toBitmapContainer()
134-
and := bc1.andBitmap(bc2)
135-
var rc2 *runContainer16
136-
switch x := and.(type) {
137-
case *bitmapContainer:
138-
rc2 = newRunContainer16FromBitmapContainer(x)
139-
case *arrayContainer:
140-
rc2 = newRunContainer16FromArray(x)
141-
case *runContainer16:
142-
rc2 = x
143-
default:
144-
panic("unknown container type")
124+
func (rc *runContainer16) andArray(ac *arrayContainer) container {
125+
if len(rc.iv) == 0 {
126+
return newArrayContainer()
145127
}
146-
*rc = *rc2
147-
return rc
148128

149-
/*
150-
// TODO: optimize by doing less allocation, possibly?
151-
out := newRunContainer16()
152-
for _, p := range rc.iv {
153-
for i := p.start; i <= p.last; i++ {
154-
if ac.contains(i) {
155-
out.Add(i)
156-
}
129+
acCardinality := ac.getCardinality()
130+
c := newArrayContainerCapacity(acCardinality)
131+
132+
for rlePos, arrayPos := 0, 0; arrayPos < acCardinality; {
133+
iv := rc.iv[rlePos]
134+
arrayVal := ac.content[arrayPos]
135+
136+
for iv.last() < arrayVal {
137+
rlePos++
138+
if rlePos == len(rc.iv) {
139+
return c
157140
}
141+
iv = rc.iv[rlePos]
158142
}
159-
*rc = *out
160-
return rc
161-
*/
143+
144+
if iv.start > arrayVal {
145+
arrayPos = advanceUntil(ac.content, arrayPos, len(ac.content), iv.start)
146+
} else {
147+
c.content = append(c.content, arrayVal)
148+
arrayPos++
149+
}
150+
}
151+
return c
162152
}
163153

164154
func (rc *runContainer16) andNot(a container) container {

0 commit comments

Comments
 (0)