special case individual union

This commit is contained in:
Richard Artoul 2018-11-29 16:34:17 -05:00
parent 56b3d7d5db
commit f97ff4b5a0

View file

@ -399,9 +399,14 @@ func (b *Bitmap) Intersect(other *Bitmap) *Bitmap {
return output
}
// Union returns the bitwise union of b and other.
// Union returns the bitwise union of b and other as a new bitmap.
func (b *Bitmap) Union(others ...*Bitmap) *Bitmap {
output := NewBitmap()
if len(others) == 1 {
b.unionIntoTargetSingle(output, others[0])
return output
}
output.UnionInPlace(b)
output.UnionInPlace(others...)
return output
@ -413,6 +418,30 @@ func (b *Bitmap) UnionInPlace(others ...*Bitmap) {
b.unionIntoTarget(b, others...)
}
func (b *Bitmap) unionIntoTargetSingle(target *Bitmap, other *Bitmap) {
iiter, _ := b.Containers.Iterator(0)
jiter, _ := other.Containers.Iterator(0)
i, j := iiter.Next(), jiter.Next()
ki, ci := iiter.Value()
kj, cj := jiter.Value()
for i || j {
if i && (!j || ki < kj) {
target.Containers.Put(ki, ci.Clone())
i = iiter.Next()
ki, ci = iiter.Value()
} else if j && (!i || ki > kj) {
target.Containers.Put(kj, cj.Clone())
j = jiter.Next()
kj, cj = jiter.Value()
} else { // ki == kj
target.Containers.Put(ki, union(ci, cj))
i, j = iiter.Next(), jiter.Next()
ki, ci = iiter.Value()
kj, cj = jiter.Value()
}
}
}
// unionIntoTarget stores the union of b and others into target. b and others will
// be left unchanged (unless one of them is also target), but target will be modified
// in place.