From 498045f25acfcf09a599d2e33eadda0ebbafd0d8 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Tue, 30 May 2017 11:18:05 -0500 Subject: [PATCH] added copy optimization ; type check; and code cleanup --- roaring/roaring.go | 102 +++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/roaring/roaring.go b/roaring/roaring.go index bb27a4143..79d19337c 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -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); { @@ -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() { @@ -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 } @@ -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 }