updated dependencies

This commit is contained in:
ston1th 2023-01-15 16:24:38 +01:00
commit cff4b58f6d
446 changed files with 57869 additions and 27621 deletions

View file

@ -11,7 +11,8 @@ import (
"fmt"
"io"
"strconv"
"sync"
"github.com/RoaringBitmap/roaring/internal"
)
// Bitmap represents a compressed bitmap where you can add integers.
@ -52,27 +53,72 @@ func (rb *Bitmap) ToBytes() ([]byte, error) {
return rb.highlowcontainer.toBytes()
}
// Deprecated: WriteToMsgpack writes a msgpack2/snappy-streaming compressed serialized
// version of this bitmap to stream. The format is not
// compatible with the WriteTo() format, and is
// experimental: it may produce smaller on disk
// footprint and/or be faster to read, depending
// on your content. Currently only the Go roaring
// implementation supports this format.
func (rb *Bitmap) WriteToMsgpack(stream io.Writer) (int64, error) {
return 0, rb.highlowcontainer.writeToMsgpack(stream)
// Checksum computes a hash (currently FNV-1a) for a bitmap that is suitable for
// using bitmaps as elements in hash sets or as keys in hash maps, as well as
// generally quicker comparisons.
// The implementation is biased towards efficiency in little endian machines, so
// expect some extra CPU cycles and memory to be used if your machine is big endian.
// Likewise, don't use this to verify integrity unless you're certain you'll load
// the bitmap on a machine with the same endianess used to create it.
func (rb *Bitmap) Checksum() uint64 {
const (
offset = 14695981039346656037
prime = 1099511628211
)
var bytes []byte
hash := uint64(offset)
bytes = uint16SliceAsByteSlice(rb.highlowcontainer.keys)
for _, b := range bytes {
hash ^= uint64(b)
hash *= prime
}
for _, c := range rb.highlowcontainer.containers {
// 0 separator
hash ^= 0
hash *= prime
switch c := c.(type) {
case *bitmapContainer:
bytes = uint64SliceAsByteSlice(c.bitmap)
case *arrayContainer:
bytes = uint16SliceAsByteSlice(c.content)
case *runContainer16:
bytes = interval16SliceAsByteSlice(c.iv)
default:
panic("invalid container type")
}
if len(bytes) == 0 {
panic("empty containers are not supported")
}
for _, b := range bytes {
hash ^= uint64(b)
hash *= prime
}
}
return hash
}
// ReadFrom reads a serialized version of this bitmap from stream.
// The format is compatible with other RoaringBitmap
// implementations (Java, C) and is documented here:
// https://github.com/RoaringBitmap/RoaringFormatSpec
func (rb *Bitmap) ReadFrom(reader io.Reader) (p int64, err error) {
stream := byteInputAdapterPool.Get().(*byteInputAdapter)
stream.reset(reader)
// Since io.Reader is regarded as a stream and cannot be read twice.
// So add cookieHeader to accept the 4-byte data that has been read in roaring64.ReadFrom.
// It is not necessary to pass cookieHeader when call roaring.ReadFrom to read the roaring32 data directly.
func (rb *Bitmap) ReadFrom(reader io.Reader, cookieHeader ...byte) (p int64, err error) {
stream := internal.ByteInputAdapterPool.Get().(*internal.ByteInputAdapter)
stream.Reset(reader)
p, err = rb.highlowcontainer.readFrom(stream)
byteInputAdapterPool.Put(stream)
p, err = rb.highlowcontainer.readFrom(stream, cookieHeader...)
internal.ByteInputAdapterPool.Put(stream)
return
}
@ -100,29 +146,15 @@ func (rb *Bitmap) ReadFrom(reader io.Reader) (p int64, err error) {
// call CloneCopyOnWriteContainers on all such bitmaps.
//
func (rb *Bitmap) FromBuffer(buf []byte) (p int64, err error) {
stream := byteBufferPool.Get().(*byteBuffer)
stream.reset(buf)
stream := internal.ByteBufferPool.Get().(*internal.ByteBuffer)
stream.Reset(buf)
p, err = rb.highlowcontainer.readFrom(stream)
byteBufferPool.Put(stream)
internal.ByteBufferPool.Put(stream)
return
}
var (
byteBufferPool = sync.Pool{
New: func() interface{} {
return &byteBuffer{}
},
}
byteInputAdapterPool = sync.Pool{
New: func() interface{} {
return &byteInputAdapter{}
},
}
)
// RunOptimize attempts to further compress the runs of consecutive values found in the bitmap
func (rb *Bitmap) RunOptimize() {
rb.highlowcontainer.runOptimize()
@ -133,14 +165,6 @@ func (rb *Bitmap) HasRunCompression() bool {
return rb.highlowcontainer.hasRunCompression()
}
// Deprecated: ReadFromMsgpack reads a msgpack2/snappy-streaming serialized
// version of this bitmap from stream. The format is
// expected is that written by the WriteToMsgpack()
// call; see additional notes there.
func (rb *Bitmap) ReadFromMsgpack(stream io.Reader) (int64, error) {
return 0, rb.highlowcontainer.readFromMsgpack(stream)
}
// MarshalBinary implements the encoding.BinaryMarshaler interface for the bitmap
// (same as ToBytes)
func (rb *Bitmap) MarshalBinary() ([]byte, error) {
@ -180,8 +204,7 @@ func (rb *Bitmap) ToArray() []uint32 {
hs := uint32(rb.highlowcontainer.getKeyAtIndex(pos)) << 16
c := rb.highlowcontainer.getContainerAtIndex(pos)
pos++
c.fillLeastSignificant16bits(array, pos2, hs)
pos2 += c.getCardinality()
pos2 = c.fillLeastSignificant16bits(array, pos2, hs)
}
return array
}
@ -248,6 +271,14 @@ type intIterator struct {
hs uint32
iter shortPeekable
highlowcontainer *roaringArray
// These embedded iterators per container type help reduce load in the GC.
// This way, instead of making up-to 64k allocations per full iteration
// we get a single allocation and simply reinitialize the appropriate
// iterator and point to it in the generic `iter` member on each key bound.
shortIter shortIterator
runIter runIterator16
bitmapIter bitmapContainerShortIterator
}
// HasNext returns true if there are more integers to iterate over
@ -257,8 +288,19 @@ func (ii *intIterator) HasNext() bool {
func (ii *intIterator) init() {
if ii.highlowcontainer.size() > ii.pos {
ii.iter = ii.highlowcontainer.getContainerAtIndex(ii.pos).getShortIterator()
ii.hs = uint32(ii.highlowcontainer.getKeyAtIndex(ii.pos)) << 16
c := ii.highlowcontainer.getContainerAtIndex(ii.pos)
switch t := c.(type) {
case *arrayContainer:
ii.shortIter = shortIterator{t.content, 0}
ii.iter = &ii.shortIter
case *runContainer16:
ii.runIter = runIterator16{rc: t, curIndex: 0, curPosInIndex: 0}
ii.iter = &ii.runIter
case *bitmapContainer:
ii.bitmapIter = bitmapContainerShortIterator{t, t.NextSetBit(0)}
ii.iter = &ii.bitmapIter
}
}
}
@ -279,14 +321,14 @@ func (ii *intIterator) PeekNext() uint32 {
// AdvanceIfNeeded advances as long as the next value is smaller than minval
func (ii *intIterator) AdvanceIfNeeded(minval uint32) {
to := minval >> 16
to := minval & 0xffff0000
for ii.HasNext() && (ii.hs>>16) < to {
for ii.HasNext() && ii.hs < to {
ii.pos++
ii.init()
}
if ii.HasNext() && (ii.hs>>16) == to {
if ii.HasNext() && ii.hs == to {
ii.iter.advanceIfNeeded(lowbits(minval))
if !ii.iter.hasNext() {
@ -296,12 +338,17 @@ func (ii *intIterator) AdvanceIfNeeded(minval uint32) {
}
}
func newIntIterator(a *Bitmap) *intIterator {
p := new(intIterator)
// IntIterator is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
type IntIterator = intIterator
// Initialize configures the existing iterator so that it can iterate through the values of
// the provided bitmap.
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
func (p *intIterator) Initialize(a *Bitmap) {
p.pos = 0
p.highlowcontainer = &a.highlowcontainer
p.init()
return p
}
type intReverseIterator struct {
@ -309,6 +356,10 @@ type intReverseIterator struct {
hs uint32
iter shortIterable
highlowcontainer *roaringArray
shortIter reverseIterator
runIter runReverseIterator16
bitmapIter reverseBitmapContainerShortIterator
}
// HasNext returns true if there are more integers to iterate over
@ -318,8 +369,30 @@ func (ii *intReverseIterator) HasNext() bool {
func (ii *intReverseIterator) init() {
if ii.pos >= 0 {
ii.iter = ii.highlowcontainer.getContainerAtIndex(ii.pos).getReverseIterator()
ii.hs = uint32(ii.highlowcontainer.getKeyAtIndex(ii.pos)) << 16
c := ii.highlowcontainer.getContainerAtIndex(ii.pos)
switch t := c.(type) {
case *arrayContainer:
ii.shortIter = reverseIterator{t.content, len(t.content) - 1}
ii.iter = &ii.shortIter
case *runContainer16:
index := int(len(t.iv)) - 1
pos := uint16(0)
if index >= 0 {
pos = t.iv[index].length
}
ii.runIter = runReverseIterator16{rc: t, curIndex: index, curPosInIndex: pos}
ii.iter = &ii.runIter
case *bitmapContainer:
pos := -1
if t.cardinality > 0 {
pos = int(t.maximum())
}
ii.bitmapIter = reverseBitmapContainerShortIterator{t, pos}
ii.iter = &ii.bitmapIter
}
} else {
ii.iter = nil
}
@ -335,12 +408,16 @@ func (ii *intReverseIterator) Next() uint32 {
return x
}
func newIntReverseIterator(a *Bitmap) *intReverseIterator {
p := new(intReverseIterator)
// IntReverseIterator is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
type IntReverseIterator = intReverseIterator
// Initialize configures the existing iterator so that it can iterate through the values of
// the provided bitmap.
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
func (p *intReverseIterator) Initialize(a *Bitmap) {
p.highlowcontainer = &a.highlowcontainer
p.pos = a.highlowcontainer.size() - 1
p.init()
return p
}
// ManyIntIterable allows you to iterate over the values in a Bitmap
@ -356,12 +433,27 @@ type manyIntIterator struct {
hs uint32
iter manyIterable
highlowcontainer *roaringArray
shortIter shortIterator
runIter runIterator16
bitmapIter bitmapContainerManyIterator
}
func (ii *manyIntIterator) init() {
if ii.highlowcontainer.size() > ii.pos {
ii.iter = ii.highlowcontainer.getContainerAtIndex(ii.pos).getManyIterator()
ii.hs = uint32(ii.highlowcontainer.getKeyAtIndex(ii.pos)) << 16
c := ii.highlowcontainer.getContainerAtIndex(ii.pos)
switch t := c.(type) {
case *arrayContainer:
ii.shortIter = shortIterator{t.content, 0}
ii.iter = &ii.shortIter
case *runContainer16:
ii.runIter = runIterator16{rc: t, curIndex: 0, curPosInIndex: 0}
ii.iter = &ii.runIter
case *bitmapContainer:
ii.bitmapIter = bitmapContainerManyIterator{t, -1, 0}
ii.iter = &ii.bitmapIter
}
} else {
ii.iter = nil
}
@ -403,12 +495,17 @@ func (ii *manyIntIterator) NextMany64(hs64 uint64, buf []uint64) int {
return n
}
func newManyIntIterator(a *Bitmap) *manyIntIterator {
p := new(manyIntIterator)
// ManyIntIterator is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
type ManyIntIterator = manyIntIterator
// Initialize configures the existing iterator so that it can iterate through the values of
// the provided bitmap.
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
func (p *manyIntIterator) Initialize(a *Bitmap) {
p.pos = 0
p.highlowcontainer = &a.highlowcontainer
p.init()
return p
}
// String creates a string representation of the Bitmap
@ -440,7 +537,7 @@ func (rb *Bitmap) String() string {
// Iterate iterates over the bitmap, calling the given callback with each value in the bitmap. If the callback returns
// false, the iteration is halted.
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
// There is no guarantee as to what order the values will be iterated
// There is no guarantee as to what order the values will be iterated.
func (rb *Bitmap) Iterate(cb func(x uint32) bool) {
for i := 0; i < rb.highlowcontainer.size(); i++ {
hs := uint32(rb.highlowcontainer.getKeyAtIndex(i)) << 16
@ -472,19 +569,25 @@ func (rb *Bitmap) Iterate(cb func(x uint32) bool) {
// Iterator creates a new IntPeekable to iterate over the integers contained in the bitmap, in sorted order;
// the iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
func (rb *Bitmap) Iterator() IntPeekable {
return newIntIterator(rb)
p := new(intIterator)
p.Initialize(rb)
return p
}
// ReverseIterator creates a new IntIterable to iterate over the integers contained in the bitmap, in sorted order;
// the iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
func (rb *Bitmap) ReverseIterator() IntIterable {
return newIntReverseIterator(rb)
p := new(intReverseIterator)
p.Initialize(rb)
return p
}
// ManyIterator creates a new ManyIntIterable to iterate over the integers contained in the bitmap, in sorted order;
// the iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
func (rb *Bitmap) ManyIterator() ManyIntIterable {
return newManyIntIterator(rb)
p := new(manyIntIterator)
p.Initialize(rb)
return p
}
// Clone creates a copy of the Bitmap
@ -496,11 +599,17 @@ func (rb *Bitmap) Clone() *Bitmap {
// Minimum get the smallest value stored in this roaring bitmap, assumes that it is not empty
func (rb *Bitmap) Minimum() uint32 {
if len(rb.highlowcontainer.containers) == 0 {
panic("Empty bitmap")
}
return uint32(rb.highlowcontainer.containers[0].minimum()) | (uint32(rb.highlowcontainer.keys[0]) << 16)
}
// Maximum get the largest value stored in this roaring bitmap, assumes that it is not empty
func (rb *Bitmap) Maximum() uint32 {
if len(rb.highlowcontainer.containers) == 0 {
panic("Empty bitmap")
}
lastindex := len(rb.highlowcontainer.containers) - 1
return uint32(rb.highlowcontainer.containers[lastindex].maximum()) | (uint32(rb.highlowcontainer.keys[lastindex]) << 16)
}
@ -544,34 +653,38 @@ func AddOffset64(x *Bitmap, offset int64) (answer *Bitmap) {
containerOffset64 = offset >> 16
}
if containerOffset64 >= (1<<16) || containerOffset64 <= -(1<<16) {
return New()
answer = New()
if containerOffset64 >= (1<<16) || containerOffset64 < -(1<<16) {
return answer
}
containerOffset := int32(containerOffset64)
inOffset := (uint16)(offset - containerOffset64*(1<<16))
if inOffset == 0 {
answer = x.Clone()
for pos := 0; pos < answer.highlowcontainer.size(); pos++ {
key := int32(answer.highlowcontainer.getKeyAtIndex(pos))
key += containerOffset
if key >= 0 && key <= MaxUint16 {
answer.highlowcontainer.keys[pos] = uint16(key)
}
}
} else {
answer = New()
for pos := 0; pos < x.highlowcontainer.size(); pos++ {
key := int32(x.highlowcontainer.getKeyAtIndex(pos))
key += containerOffset
c := x.highlowcontainer.getContainerAtIndex(pos)
offsetted := c.addOffset(inOffset)
if key >= 0 && key <= MaxUint16 {
c := x.highlowcontainer.getContainerAtIndex(pos).clone()
answer.highlowcontainer.appendContainer(uint16(key), c, false)
}
}
} else {
for pos := 0; pos < x.highlowcontainer.size(); pos++ {
key := int32(x.highlowcontainer.getKeyAtIndex(pos))
key += containerOffset
if offsetted[0].getCardinality() > 0 && (key >= 0 && key <= MaxUint16) {
if key+1 < 0 || key > MaxUint16 {
continue
}
c := x.highlowcontainer.getContainerAtIndex(pos)
lo, hi := c.addOffset(inOffset)
if lo != nil && key >= 0 {
curSize := answer.highlowcontainer.size()
lastkey := int32(0)
@ -581,15 +694,15 @@ func AddOffset64(x *Bitmap, offset int64) (answer *Bitmap) {
if curSize > 0 && lastkey == key {
prev := answer.highlowcontainer.getContainerAtIndex(curSize - 1)
orrseult := prev.ior(offsetted[0])
answer.highlowcontainer.setContainerAtIndex(curSize-1, orrseult)
orresult := prev.ior(lo)
answer.highlowcontainer.setContainerAtIndex(curSize-1, orresult)
} else {
answer.highlowcontainer.appendContainer(uint16(key), offsetted[0], false)
answer.highlowcontainer.appendContainer(uint16(key), lo, false)
}
}
if offsetted[1].getCardinality() > 0 && ((key+1) >= 0 && (key+1) <= MaxUint16) {
answer.highlowcontainer.appendContainer(uint16(key+1), offsetted[1], false)
if hi != nil && key+1 <= MaxUint16 {
answer.highlowcontainer.appendContainer(uint16(key+1), hi, false)
}
}
}
@ -659,13 +772,13 @@ func (rb *Bitmap) Remove(x uint32) {
if i >= 0 {
c := rb.highlowcontainer.getWritableContainerAtIndex(i).iremoveReturnMinimized(lowbits(x))
rb.highlowcontainer.setContainerAtIndex(i, c)
if rb.highlowcontainer.getContainerAtIndex(i).getCardinality() == 0 {
if rb.highlowcontainer.getContainerAtIndex(i).isEmpty() {
rb.highlowcontainer.removeAtIndex(i)
}
}
}
// CheckedRemove removes the integer x from the bitmap and return true if the integer was effectively remove (and false if the integer was not present)
// CheckedRemove removes the integer x from the bitmap and return true if the integer was effectively removed (and false if the integer was not present)
func (rb *Bitmap) CheckedRemove(x uint32) bool {
// TODO: add unit tests for this method
hb := highbits(x)
@ -675,7 +788,7 @@ func (rb *Bitmap) CheckedRemove(x uint32) bool {
oldcard := C.getCardinality()
C = C.iremoveReturnMinimized(lowbits(x))
rb.highlowcontainer.setContainerAtIndex(i, C)
if rb.highlowcontainer.getContainerAtIndex(i).getCardinality() == 0 {
if rb.highlowcontainer.getContainerAtIndex(i).isEmpty() {
rb.highlowcontainer.removeAtIndex(i)
return true
}
@ -723,15 +836,12 @@ func (rb *Bitmap) Rank(x uint32) uint64 {
// the smallest element. Note that this function differs in convention from
// the Rank function which returns 1 on the smallest value.
func (rb *Bitmap) Select(x uint32) (uint32, error) {
if rb.GetCardinality() <= uint64(x) {
return 0, fmt.Errorf("can't find %dth integer in a bitmap with only %d items", x, rb.GetCardinality())
}
remaining := x
for i := 0; i < rb.highlowcontainer.size(); i++ {
c := rb.highlowcontainer.getContainerAtIndex(i)
if remaining >= uint32(c.getCardinality()) {
remaining -= uint32(c.getCardinality())
card := uint32(c.getCardinality())
if remaining >= card {
remaining -= card
} else {
key := rb.highlowcontainer.getKeyAtIndex(i)
return uint32(key)<<16 + uint32(c.selectInt(uint16(remaining))), nil
@ -758,7 +868,7 @@ main:
c1 := rb.highlowcontainer.getWritableContainerAtIndex(pos1)
c2 := x2.highlowcontainer.getContainerAtIndex(pos2)
diff := c1.iand(c2)
if diff.getCardinality() > 0 {
if !diff.isEmpty() {
rb.highlowcontainer.replaceKeyAndContainerAtIndex(intersectionsize, s1, diff, false)
intersectionsize++
}
@ -889,6 +999,28 @@ main:
return answer
}
// IntersectsWithInterval checks whether a bitmap 'rb' and an open interval '[x,y)' intersect.
func (rb *Bitmap) IntersectsWithInterval(x, y uint64) bool {
if x >= y {
return false
}
if x > MaxUint32 {
return false
}
it := intIterator{}
it.Initialize(rb)
it.AdvanceIfNeeded(uint32(x))
if !it.HasNext() {
return false
}
if uint64(it.Next()) >= y {
return false
}
return true
}
// Intersects checks whether two bitmap intersects, bitmaps are not modified
func (rb *Bitmap) Intersects(x2 *Bitmap) bool {
pos1 := 0
@ -960,7 +1092,7 @@ func (rb *Bitmap) Xor(x2 *Bitmap) {
} else {
// TODO: couple be computed in-place for reduced memory usage
c := rb.highlowcontainer.getContainerAtIndex(pos1).xor(x2.highlowcontainer.getContainerAtIndex(pos2))
if c.getCardinality() > 0 {
if !c.isEmpty() {
rb.highlowcontainer.setContainerAtIndex(pos1, c)
pos1++
} else {
@ -1040,7 +1172,7 @@ main:
c1 := rb.highlowcontainer.getWritableContainerAtIndex(pos1)
c2 := x2.highlowcontainer.getContainerAtIndex(pos2)
diff := c1.iandNot(c2)
if diff.getCardinality() > 0 {
if !diff.isEmpty() {
rb.highlowcontainer.replaceKeyAndContainerAtIndex(intersectionsize, s1, diff, false)
intersectionsize++
}
@ -1149,7 +1281,7 @@ main:
C := x1.highlowcontainer.getContainerAtIndex(pos1)
C = C.and(x2.highlowcontainer.getContainerAtIndex(pos2))
if C.getCardinality() > 0 {
if !C.isEmpty() {
answer.highlowcontainer.appendContainer(s1, C, false)
}
pos1++
@ -1196,7 +1328,7 @@ func Xor(x1, x2 *Bitmap) *Bitmap {
pos2++
} else {
c := x1.highlowcontainer.getContainerAtIndex(pos1).xor(x2.highlowcontainer.getContainerAtIndex(pos2))
if c.getCardinality() > 0 {
if !c.isEmpty() {
answer.highlowcontainer.appendContainer(s1, c, false)
}
pos1++
@ -1239,7 +1371,7 @@ main:
c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
c2 := x2.highlowcontainer.getContainerAtIndex(pos2)
diff := c1.andNot(c2)
if diff.getCardinality() > 0 {
if !diff.isEmpty() {
answer.highlowcontainer.appendContainer(s1, diff, false)
}
pos1++
@ -1329,7 +1461,7 @@ func (rb *Bitmap) Flip(rangeStart, rangeEnd uint64) {
if i >= 0 {
c := rb.highlowcontainer.getWritableContainerAtIndex(i).inot(int(containerStart), int(containerLast)+1)
if c.getCardinality() > 0 {
if !c.isEmpty() {
rb.highlowcontainer.setContainerAtIndex(i, c)
} else {
rb.highlowcontainer.removeAtIndex(i)
@ -1410,7 +1542,7 @@ func (rb *Bitmap) RemoveRange(rangeStart, rangeEnd uint64) {
return
}
c := rb.highlowcontainer.getWritableContainerAtIndex(i).iremoveRange(int(lbStart), int(lbLast+1))
if c.getCardinality() > 0 {
if !c.isEmpty() {
rb.highlowcontainer.setContainerAtIndex(i, c)
} else {
rb.highlowcontainer.removeAtIndex(i)
@ -1423,7 +1555,7 @@ func (rb *Bitmap) RemoveRange(rangeStart, rangeEnd uint64) {
if ifirst >= 0 {
if lbStart != 0 {
c := rb.highlowcontainer.getWritableContainerAtIndex(ifirst).iremoveRange(int(lbStart), int(max+1))
if c.getCardinality() > 0 {
if !c.isEmpty() {
rb.highlowcontainer.setContainerAtIndex(ifirst, c)
ifirst++
}
@ -1434,7 +1566,7 @@ func (rb *Bitmap) RemoveRange(rangeStart, rangeEnd uint64) {
if ilast >= 0 {
if lbLast != max {
c := rb.highlowcontainer.getWritableContainerAtIndex(ilast).iremoveRange(int(0), int(lbLast+1))
if c.getCardinality() > 0 {
if !c.isEmpty() {
rb.highlowcontainer.setContainerAtIndex(ilast, c)
} else {
ilast++
@ -1490,7 +1622,7 @@ func Flip(bm *Bitmap, rangeStart, rangeEnd uint64) *Bitmap {
if i >= 0 {
c := bm.highlowcontainer.getContainerAtIndex(i).not(int(containerStart), int(containerLast)+1)
if c.getCardinality() > 0 {
if !c.isEmpty() {
answer.highlowcontainer.insertNewKeyValueAt(-j-1, uint16(hb), c)
}