Skip to content

Commit

Permalink
added copy optimization ; type check; and code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
tgruben committed May 30, 2017
1 parent 2182534 commit 498045f
Showing 1 changed file with 48 additions and 54 deletions.
102 changes: 48 additions & 54 deletions roaring/roaring.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,39 @@ func (b *Bitmap) Difference(other *Bitmap) *Bitmap {
return output
}

// Xor returns the bitwise exclusive or of b and other.
func (b *Bitmap) Xor(other *Bitmap) *Bitmap {
output := &Bitmap{}

ki, ci := b.keys, b.containers
kj, cj := other.keys, other.containers

for {
var key uint64
var container *container

ni, nj := len(ki), len(kj)
if ni == 0 && nj == 0 { // eof(i,j)
break
} else if ni == 0 || (nj != 0 && ki[0] > kj[0]) { // eof(i) or i > j
key, container = kj[0], cj[0].clone()
kj, cj = kj[1:], cj[1:]
} else if nj == 0 || (ki[0] < kj[0]) { // eof(j) or i < j
key, container = ki[0], ci[0].clone()
ki, ci = ki[1:], ci[1:]
} else { // i == j
key, container = ki[0], xor(ci[0], cj[0])
ki, ci = ki[1:], ci[1:]
kj, cj = kj[1:], cj[1:]
}

output.keys = append(output.keys, key)
output.containers = append(output.containers, container)
}

return output
}

// removeEmptyContainers deletes all containers that have a count of zero.
func (b *Bitmap) removeEmptyContainers() {
for i := 0; i < len(b.containers); {
Expand Down Expand Up @@ -1563,37 +1596,6 @@ func differenceBitmapBitmap(a, b *container) *container {
}
return output
}
func (b *Bitmap) Xor(other *Bitmap) *Bitmap {
output := &Bitmap{}

ki, ci := b.keys, b.containers
kj, cj := other.keys, other.containers

for {
var key uint64
var container *container

ni, nj := len(ki), len(kj)
if ni == 0 && nj == 0 { // eof(i,j)
break
} else if ni == 0 || (nj != 0 && ki[0] > kj[0]) { // eof(i) or i > j
key, container = kj[0], cj[0].clone()
kj, cj = kj[1:], cj[1:]
} else if nj == 0 || (ki[0] < kj[0]) { // eof(j) or i < j
key, container = ki[0], ci[0].clone()
ki, ci = ki[1:], ci[1:]
} else { // i == j
key, container = ki[0], xor(ci[0], cj[0])
ki, ci = ki[1:], ci[1:]
kj, cj = kj[1:], cj[1:]
}

output.keys = append(output.keys, key)
output.containers = append(output.containers, container)
}

return output
}

func xor(a, b *container) *container {
if a.isArray() {
Expand Down Expand Up @@ -1643,32 +1645,20 @@ func xorArrayArray(a, b *container) *container {
}

func xorArrayBitmap(a, b *container) *container {
output := &container{}
itr := newBufIterator(newBitmapIterator(b.bitmap))
for i := 0; ; {
vb, eof := itr.next()
if i >= len(a.array) && eof {
break
} else if i >= len(a.array) {
output.add(vb)
continue
} else if eof {
output.add(a.array[i])
i++
continue
}

va := a.array[i]
if va < vb {
output.add(va)
i++
itr.unread()
} else if va > vb {
output.add(vb)
output := b.clone()
for _, v := range a.array {
if b.bitmapContains(v) {
output.remove(v)
} else {
i++

output.add(v)
}
}

if output.count() < ArrayMaxSize {
output.convertToArray()
}

return output
}

Expand All @@ -1682,6 +1672,10 @@ func xorBitmapBitmap(a, b *container) *container {
output.bitmap[i] = v
output.n += int(popcnt(v))
}

if output.count() < ArrayMaxSize {
output.convertToArray()
}
return output
}

Expand Down

0 comments on commit 498045f

Please sign in to comment.