Skip to content

Commit b80a6f4

Browse files
committed
introduces ContainsMany
1 parent 08464f0 commit b80a6f4

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

bitmap_opt.go

+44
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,50 @@ func orContainersInRange(a, b *Bitmap, bi, bn int, buf []uint16) {
458458
}
459459
}
460460

461+
func (ra *Bitmap) ContainsMany(xs []uint64) []uint64 {
462+
if xs == nil {
463+
xs = []uint64{}
464+
}
465+
466+
if len(xs) == 0 || ra.IsEmpty() {
467+
return xs[:0]
468+
}
469+
if len(xs) == 1 {
470+
if ra.Contains(xs[0]) {
471+
return xs
472+
}
473+
return xs[:0]
474+
}
475+
476+
keyToContainer := map[uint64][]uint16{}
477+
j := 0
478+
for i, x := range xs {
479+
key := x & mask
480+
container, ok := keyToContainer[key]
481+
if !ok {
482+
if offset, has := ra.keys.getValue(key); has {
483+
container = ra.getContainer(offset)
484+
}
485+
keyToContainer[key] = container
486+
}
487+
if container != nil {
488+
y := uint16(x)
489+
contains := false
490+
switch container[indexType] {
491+
case typeArray:
492+
contains = array(container).has(y)
493+
case typeBitmap:
494+
contains = bitmap(container).has(y)
495+
}
496+
if contains {
497+
xs[j] = xs[i]
498+
j++
499+
}
500+
}
501+
}
502+
return xs[:j]
503+
}
504+
461505
const minContainersForConcurrency = 16
462506

463507
// AndToSuperset calculates intersection of current and incoming bitmap

bitmap_opt_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,32 @@ func TestIssue_Or_NotMergeContainers(t *testing.T) {
871871
})
872872
}
873873

874+
func TestContainsMany(t *testing.T) {
875+
t.Run("contains even", func(t *testing.T) {
876+
maxI := 10
877+
maxJ := 100
878+
879+
set := make([]uint64, 0, maxI*maxJ)
880+
control := make([]uint64, 0, maxI*maxJ)
881+
bm := NewBitmap()
882+
883+
for i := 0; i < maxI; i++ {
884+
for j := 0; j < maxJ; j++ {
885+
x := uint64(maxCardinality*i + j)
886+
set = append(set, x)
887+
if j%2 == 0 {
888+
control = append(control, x)
889+
bm.Set(x)
890+
}
891+
}
892+
}
893+
894+
contained := bm.ContainsMany(set)
895+
require.Len(t, contained, len(control))
896+
require.ElementsMatch(t, contained, control)
897+
})
898+
}
899+
874900
func TestMergeToSuperset(t *testing.T) {
875901
run := func(t *testing.T, bufs [][]uint16) {
876902
containerThreshold := uint64(math.MaxUint16 + 1)

0 commit comments

Comments
 (0)