Skip to content
This repository has been archived by the owner on Jul 18, 2024. It is now read-only.

fix(andNot): Fix andNot for bitmap-array container #29

Merged
merged 1 commit into from
Oct 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 33 additions & 16 deletions bitmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,22 @@ func TestAnd(t *testing.T) {
require.Equal(t, 0, a.GetCardinality())
}

func TestAnd2(t *testing.T) {
a := NewBitmap()
n := int(1e7)

for i := 0; i < n; i++ {
a.Set(uint64(i))
}
require.Equal(t, n, a.GetCardinality())
a.RemoveRange(0, uint64(n/2))

for i := 0; i < n; i++ {
a.Set(uint64(i))
}
require.Equal(t, n, a.GetCardinality())
}

func TestAndNot(t *testing.T) {
a := NewBitmap()
b := NewBitmap()
Expand Down Expand Up @@ -451,6 +467,23 @@ func TestAndNot(t *testing.T) {
}
}

func TestAndNot2(t *testing.T) {
a := NewBitmap()
b := NewBitmap()
n := int(1e6)

for i := 0; i < n/2; i++ {
a.Set(uint64(i))
}
for i := n / 2; i < n; i++ {
b.Set(uint64(i))
}
require.Equal(t, n/2, a.GetCardinality())
a.AndNot(b)
require.Equal(t, n/2, a.GetCardinality())

}

func TestOr(t *testing.T) {
a := NewBitmap()
b := NewBitmap()
Expand Down Expand Up @@ -806,19 +839,3 @@ func TestRank(t *testing.T) {
}
}
}

func TestAnd2(t *testing.T) {
a := NewBitmap()
n := int(1e7)

for i := 0; i < n; i++ {
a.Set(uint64(i))
}
require.Equal(t, n, a.GetCardinality())
a.RemoveRange(0, uint64(n/2))

for i := 0; i < n; i++ {
a.Set(uint64(i))
}
require.Equal(t, n, a.GetCardinality())
}
37 changes: 23 additions & 14 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,16 @@ func (c array) andBitmap(other bitmap) []uint16 {

// TODO: Write an optmized version of this function.
func (c array) andNotBitmap(other bitmap, buf []uint16) []uint16 {
// TODO: Iterate over the array and just check if the element is present in the bitmap.
// TODO: This won't work, because we're using buf wrong here.
bm := c.toBitmapContainer(nil)
return bitmap(bm).andNotBitmap(other, buf)
assert(len(buf) == maxContainerSize)
res := array(buf)
Memclr(res)
res[indexSize] = 4
for _, e := range c.all() {
if !other.has(e) {
res.add(e)
}
}
return res
}

func (c array) isFull() bool {
Expand Down Expand Up @@ -505,19 +511,22 @@ func (b bitmap) orBitmap(other bitmap, buf []uint16, runMode int) []uint16 {
return buf
}

func (b bitmap) andNotBitmap(other bitmap, buf []uint16) []uint16 {
copy(buf, b) // Copy over first.
buf[indexSize] = maxContainerSize
buf[indexType] = typeBitmap

func (b bitmap) andNotBitmap(other bitmap) []uint16 {
var num int
data := buf[startIdx:]
data := b[startIdx:]
for i, v := range other[startIdx:] {
data[i] = data[i] ^ (data[i] & v)
num += bits.OnesCount16(data[i])
}
setCardinality(buf, num)
return buf
setCardinality(b, num)
return b
}

func (b bitmap) andNotArray(other array) []uint16 {
for _, e := range other.all() {
b.remove(e)
}
return b
}

func (b bitmap) orArray(other array, buf []uint16, runMode int) []uint16 {
Expand Down Expand Up @@ -745,13 +754,13 @@ func containerAndNot(ac, bc, buf []uint16) []uint16 {
if at == typeBitmap && bt == typeArray {
left := bitmap(ac)
right := array(bc)
out := right.andNotBitmap(left, buf)
out := left.andNotArray(right)
return out
}
if at == typeBitmap && bt == typeBitmap {
left := bitmap(ac)
right := bitmap(bc)
return left.andNotBitmap(right, buf)
return left.andNotBitmap(right)
}
panic("containerAndNot: We should not reach here")
}