forked from forgejo/forgejo
Update to last common bleve (#3986)
This commit is contained in:
parent
1b7cd3d0b0
commit
917b9641ec
184 changed files with 39576 additions and 121 deletions
960
vendor/github.com/RoaringBitmap/roaring/arraycontainer.go
generated
vendored
Normal file
960
vendor/github.com/RoaringBitmap/roaring/arraycontainer.go
generated
vendored
Normal file
|
@ -0,0 +1,960 @@
|
|||
package roaring
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//go:generate msgp -unexported
|
||||
|
||||
type arrayContainer struct {
|
||||
content []uint16
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) String() string {
|
||||
s := "{"
|
||||
for it := ac.getShortIterator(); it.hasNext(); {
|
||||
s += fmt.Sprintf("%v, ", it.next())
|
||||
}
|
||||
return s + "}"
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) fillLeastSignificant16bits(x []uint32, i int, mask uint32) {
|
||||
for k := 0; k < len(ac.content); k++ {
|
||||
x[k+i] = uint32(ac.content[k]) | mask
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) getShortIterator() shortIterable {
|
||||
return &shortIterator{ac.content, 0}
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) getManyIterator() manyIterable {
|
||||
return &manyIterator{ac.content, 0}
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) minimum() uint16 {
|
||||
return ac.content[0] // assume not empty
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) maximum() uint16 {
|
||||
return ac.content[len(ac.content)-1] // assume not empty
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) getSizeInBytes() int {
|
||||
return ac.getCardinality() * 2
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) serializedSizeInBytes() int {
|
||||
return ac.getCardinality() * 2
|
||||
}
|
||||
|
||||
func arrayContainerSizeInBytes(card int) int {
|
||||
return card * 2
|
||||
}
|
||||
|
||||
// add the values in the range [firstOfRange,endx)
|
||||
func (ac *arrayContainer) iaddRange(firstOfRange, endx int) container {
|
||||
if firstOfRange >= endx {
|
||||
return ac
|
||||
}
|
||||
indexstart := binarySearch(ac.content, uint16(firstOfRange))
|
||||
if indexstart < 0 {
|
||||
indexstart = -indexstart - 1
|
||||
}
|
||||
indexend := binarySearch(ac.content, uint16(endx-1))
|
||||
if indexend < 0 {
|
||||
indexend = -indexend - 1
|
||||
} else {
|
||||
indexend++
|
||||
}
|
||||
rangelength := endx - firstOfRange
|
||||
newcardinality := indexstart + (ac.getCardinality() - indexend) + rangelength
|
||||
if newcardinality > arrayDefaultMaxSize {
|
||||
a := ac.toBitmapContainer()
|
||||
return a.iaddRange(firstOfRange, endx)
|
||||
}
|
||||
if cap(ac.content) < newcardinality {
|
||||
tmp := make([]uint16, newcardinality, newcardinality)
|
||||
copy(tmp[:indexstart], ac.content[:indexstart])
|
||||
copy(tmp[indexstart+rangelength:], ac.content[indexend:])
|
||||
|
||||
ac.content = tmp
|
||||
} else {
|
||||
ac.content = ac.content[:newcardinality]
|
||||
copy(ac.content[indexstart+rangelength:], ac.content[indexend:])
|
||||
|
||||
}
|
||||
for k := 0; k < rangelength; k++ {
|
||||
ac.content[k+indexstart] = uint16(firstOfRange + k)
|
||||
}
|
||||
return ac
|
||||
}
|
||||
|
||||
// remove the values in the range [firstOfRange,endx)
|
||||
func (ac *arrayContainer) iremoveRange(firstOfRange, endx int) container {
|
||||
if firstOfRange >= endx {
|
||||
return ac
|
||||
}
|
||||
indexstart := binarySearch(ac.content, uint16(firstOfRange))
|
||||
if indexstart < 0 {
|
||||
indexstart = -indexstart - 1
|
||||
}
|
||||
indexend := binarySearch(ac.content, uint16(endx-1))
|
||||
if indexend < 0 {
|
||||
indexend = -indexend - 1
|
||||
} else {
|
||||
indexend++
|
||||
}
|
||||
rangelength := indexend - indexstart
|
||||
answer := ac
|
||||
copy(answer.content[indexstart:], ac.content[indexstart+rangelength:])
|
||||
answer.content = answer.content[:ac.getCardinality()-rangelength]
|
||||
return answer
|
||||
}
|
||||
|
||||
// flip the values in the range [firstOfRange,endx)
|
||||
func (ac *arrayContainer) not(firstOfRange, endx int) container {
|
||||
if firstOfRange >= endx {
|
||||
//p("arrayContainer.not(): exiting early with ac.clone()")
|
||||
return ac.clone()
|
||||
}
|
||||
return ac.notClose(firstOfRange, endx-1) // remove everything in [firstOfRange,endx-1]
|
||||
}
|
||||
|
||||
// flip the values in the range [firstOfRange,lastOfRange]
|
||||
func (ac *arrayContainer) notClose(firstOfRange, lastOfRange int) container {
|
||||
if firstOfRange > lastOfRange { // unlike add and remove, not uses an inclusive range [firstOfRange,lastOfRange]
|
||||
//p("arrayContainer.notClose(): exiting early with ac.clone()")
|
||||
return ac.clone()
|
||||
}
|
||||
|
||||
// determine the span of array indices to be affected^M
|
||||
startIndex := binarySearch(ac.content, uint16(firstOfRange))
|
||||
//p("startIndex=%v", startIndex)
|
||||
if startIndex < 0 {
|
||||
startIndex = -startIndex - 1
|
||||
}
|
||||
lastIndex := binarySearch(ac.content, uint16(lastOfRange))
|
||||
//p("lastIndex=%v", lastIndex)
|
||||
if lastIndex < 0 {
|
||||
lastIndex = -lastIndex - 2
|
||||
}
|
||||
currentValuesInRange := lastIndex - startIndex + 1
|
||||
spanToBeFlipped := lastOfRange - firstOfRange + 1
|
||||
newValuesInRange := spanToBeFlipped - currentValuesInRange
|
||||
cardinalityChange := newValuesInRange - currentValuesInRange
|
||||
newCardinality := len(ac.content) + cardinalityChange
|
||||
//p("new card is %v", newCardinality)
|
||||
if newCardinality > arrayDefaultMaxSize {
|
||||
//p("new card over arrayDefaultMaxSize, so returning bitmap")
|
||||
return ac.toBitmapContainer().not(firstOfRange, lastOfRange+1)
|
||||
}
|
||||
answer := newArrayContainer()
|
||||
answer.content = make([]uint16, newCardinality, newCardinality) //a hack for sure
|
||||
|
||||
copy(answer.content, ac.content[:startIndex])
|
||||
outPos := startIndex
|
||||
inPos := startIndex
|
||||
valInRange := firstOfRange
|
||||
for ; valInRange <= lastOfRange && inPos <= lastIndex; valInRange++ {
|
||||
if uint16(valInRange) != ac.content[inPos] {
|
||||
answer.content[outPos] = uint16(valInRange)
|
||||
outPos++
|
||||
} else {
|
||||
inPos++
|
||||
}
|
||||
}
|
||||
|
||||
for ; valInRange <= lastOfRange; valInRange++ {
|
||||
answer.content[outPos] = uint16(valInRange)
|
||||
outPos++
|
||||
}
|
||||
|
||||
for i := lastIndex + 1; i < len(ac.content); i++ {
|
||||
answer.content[outPos] = ac.content[i]
|
||||
outPos++
|
||||
}
|
||||
answer.content = answer.content[:newCardinality]
|
||||
return answer
|
||||
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) equals(o container) bool {
|
||||
|
||||
srb, ok := o.(*arrayContainer)
|
||||
if ok {
|
||||
// Check if the containers are the same object.
|
||||
if ac == srb {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(srb.content) != len(ac.content) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, v := range ac.content {
|
||||
if v != srb.content[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// use generic comparison
|
||||
bCard := o.getCardinality()
|
||||
aCard := ac.getCardinality()
|
||||
if bCard != aCard {
|
||||
return false
|
||||
}
|
||||
|
||||
ait := ac.getShortIterator()
|
||||
bit := o.getShortIterator()
|
||||
for ait.hasNext() {
|
||||
if bit.next() != ait.next() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) toBitmapContainer() *bitmapContainer {
|
||||
bc := newBitmapContainer()
|
||||
bc.loadData(ac)
|
||||
return bc
|
||||
|
||||
}
|
||||
func (ac *arrayContainer) iadd(x uint16) (wasNew bool) {
|
||||
// Special case adding to the end of the container.
|
||||
l := len(ac.content)
|
||||
if l > 0 && l < arrayDefaultMaxSize && ac.content[l-1] < x {
|
||||
ac.content = append(ac.content, x)
|
||||
return true
|
||||
}
|
||||
|
||||
loc := binarySearch(ac.content, x)
|
||||
|
||||
if loc < 0 {
|
||||
s := ac.content
|
||||
i := -loc - 1
|
||||
s = append(s, 0)
|
||||
copy(s[i+1:], s[i:])
|
||||
s[i] = x
|
||||
ac.content = s
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iaddReturnMinimized(x uint16) container {
|
||||
// Special case adding to the end of the container.
|
||||
l := len(ac.content)
|
||||
if l > 0 && l < arrayDefaultMaxSize && ac.content[l-1] < x {
|
||||
ac.content = append(ac.content, x)
|
||||
return ac
|
||||
}
|
||||
|
||||
loc := binarySearch(ac.content, x)
|
||||
|
||||
if loc < 0 {
|
||||
if len(ac.content) >= arrayDefaultMaxSize {
|
||||
a := ac.toBitmapContainer()
|
||||
a.iadd(x)
|
||||
return a
|
||||
}
|
||||
s := ac.content
|
||||
i := -loc - 1
|
||||
s = append(s, 0)
|
||||
copy(s[i+1:], s[i:])
|
||||
s[i] = x
|
||||
ac.content = s
|
||||
}
|
||||
return ac
|
||||
}
|
||||
|
||||
// iremoveReturnMinimized is allowed to change the return type to minimize storage.
|
||||
func (ac *arrayContainer) iremoveReturnMinimized(x uint16) container {
|
||||
ac.iremove(x)
|
||||
return ac
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iremove(x uint16) bool {
|
||||
loc := binarySearch(ac.content, x)
|
||||
if loc >= 0 {
|
||||
s := ac.content
|
||||
s = append(s[:loc], s[loc+1:]...)
|
||||
ac.content = s
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) remove(x uint16) container {
|
||||
out := &arrayContainer{make([]uint16, len(ac.content))}
|
||||
copy(out.content, ac.content[:])
|
||||
|
||||
loc := binarySearch(out.content, x)
|
||||
if loc >= 0 {
|
||||
s := out.content
|
||||
s = append(s[:loc], s[loc+1:]...)
|
||||
out.content = s
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) or(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.orArray(x)
|
||||
case *bitmapContainer:
|
||||
return x.orArray(ac)
|
||||
case *runContainer16:
|
||||
if x.isFull() {
|
||||
return x.clone()
|
||||
}
|
||||
return x.orArray(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) orCardinality(a container) int {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.orArrayCardinality(x)
|
||||
case *bitmapContainer:
|
||||
return x.orArrayCardinality(ac)
|
||||
case *runContainer16:
|
||||
return x.orArrayCardinality(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) ior(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.iorArray(x)
|
||||
case *bitmapContainer:
|
||||
return a.(*bitmapContainer).orArray(ac)
|
||||
//return ac.iorBitmap(x) // note: this does not make sense
|
||||
case *runContainer16:
|
||||
if x.isFull() {
|
||||
return x.clone()
|
||||
}
|
||||
return ac.iorRun16(x)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iorArray(value2 *arrayContainer) container {
|
||||
value1 := ac
|
||||
len1 := value1.getCardinality()
|
||||
len2 := value2.getCardinality()
|
||||
maxPossibleCardinality := len1 + len2
|
||||
if maxPossibleCardinality > arrayDefaultMaxSize { // it could be a bitmap!
|
||||
bc := newBitmapContainer()
|
||||
for k := 0; k < len(value2.content); k++ {
|
||||
v := value2.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
for k := 0; k < len(ac.content); k++ {
|
||||
v := ac.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
bc.cardinality = int(popcntSlice(bc.bitmap))
|
||||
if bc.cardinality <= arrayDefaultMaxSize {
|
||||
return bc.toArrayContainer()
|
||||
}
|
||||
return bc
|
||||
}
|
||||
if maxPossibleCardinality > cap(value1.content) {
|
||||
newcontent := make([]uint16, 0, maxPossibleCardinality)
|
||||
copy(newcontent[len2:maxPossibleCardinality], ac.content[0:len1])
|
||||
ac.content = newcontent
|
||||
} else {
|
||||
copy(ac.content[len2:maxPossibleCardinality], ac.content[0:len1])
|
||||
}
|
||||
nl := union2by2(value1.content[len2:maxPossibleCardinality], value2.content, ac.content)
|
||||
ac.content = ac.content[:nl] // reslice to match actual used capacity
|
||||
return ac
|
||||
}
|
||||
|
||||
// Note: such code does not make practical sense, except for lazy evaluations
|
||||
func (ac *arrayContainer) iorBitmap(bc2 *bitmapContainer) container {
|
||||
bc1 := ac.toBitmapContainer()
|
||||
bc1.iorBitmap(bc2)
|
||||
*ac = *newArrayContainerFromBitmap(bc1)
|
||||
return ac
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iorRun16(rc *runContainer16) container {
|
||||
bc1 := ac.toBitmapContainer()
|
||||
bc2 := rc.toBitmapContainer()
|
||||
bc1.iorBitmap(bc2)
|
||||
*ac = *newArrayContainerFromBitmap(bc1)
|
||||
return ac
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) lazyIOR(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.lazyIorArray(x)
|
||||
case *bitmapContainer:
|
||||
return ac.lazyIorBitmap(x)
|
||||
case *runContainer16:
|
||||
if x.isFull() {
|
||||
return x.clone()
|
||||
}
|
||||
return ac.lazyIorRun16(x)
|
||||
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) lazyIorArray(ac2 *arrayContainer) container {
|
||||
// TODO actually make this lazy
|
||||
return ac.iorArray(ac2)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) lazyIorBitmap(bc *bitmapContainer) container {
|
||||
// TODO actually make this lazy
|
||||
return ac.iorBitmap(bc)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) lazyIorRun16(rc *runContainer16) container {
|
||||
// TODO actually make this lazy
|
||||
return ac.iorRun16(rc)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) lazyOR(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.lazyorArray(x)
|
||||
case *bitmapContainer:
|
||||
return a.lazyOR(ac)
|
||||
case *runContainer16:
|
||||
if x.isFull() {
|
||||
return x.clone()
|
||||
}
|
||||
return x.orArray(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) orArray(value2 *arrayContainer) container {
|
||||
value1 := ac
|
||||
maxPossibleCardinality := value1.getCardinality() + value2.getCardinality()
|
||||
if maxPossibleCardinality > arrayDefaultMaxSize { // it could be a bitmap!
|
||||
bc := newBitmapContainer()
|
||||
for k := 0; k < len(value2.content); k++ {
|
||||
v := value2.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
for k := 0; k < len(ac.content); k++ {
|
||||
v := ac.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
bc.cardinality = int(popcntSlice(bc.bitmap))
|
||||
if bc.cardinality <= arrayDefaultMaxSize {
|
||||
return bc.toArrayContainer()
|
||||
}
|
||||
return bc
|
||||
}
|
||||
answer := newArrayContainerCapacity(maxPossibleCardinality)
|
||||
nl := union2by2(value1.content, value2.content, answer.content)
|
||||
answer.content = answer.content[:nl] // reslice to match actual used capacity
|
||||
return answer
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) orArrayCardinality(value2 *arrayContainer) int {
|
||||
return union2by2Cardinality(ac.content, value2.content)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) lazyorArray(value2 *arrayContainer) container {
|
||||
value1 := ac
|
||||
maxPossibleCardinality := value1.getCardinality() + value2.getCardinality()
|
||||
if maxPossibleCardinality > arrayLazyLowerBound { // it could be a bitmap!^M
|
||||
bc := newBitmapContainer()
|
||||
for k := 0; k < len(value2.content); k++ {
|
||||
v := value2.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
for k := 0; k < len(ac.content); k++ {
|
||||
v := ac.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
bc.cardinality = invalidCardinality
|
||||
return bc
|
||||
}
|
||||
answer := newArrayContainerCapacity(maxPossibleCardinality)
|
||||
nl := union2by2(value1.content, value2.content, answer.content)
|
||||
answer.content = answer.content[:nl] // reslice to match actual used capacity
|
||||
return answer
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) and(a container) container {
|
||||
//p("ac.and() called")
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.andArray(x)
|
||||
case *bitmapContainer:
|
||||
return x.and(ac)
|
||||
case *runContainer16:
|
||||
if x.isFull() {
|
||||
return ac.clone()
|
||||
}
|
||||
return x.andArray(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andCardinality(a container) int {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.andArrayCardinality(x)
|
||||
case *bitmapContainer:
|
||||
return x.andCardinality(ac)
|
||||
case *runContainer16:
|
||||
return x.andArrayCardinality(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) intersects(a container) bool {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.intersectsArray(x)
|
||||
case *bitmapContainer:
|
||||
return x.intersects(ac)
|
||||
case *runContainer16:
|
||||
return x.intersects(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iand(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.iandArray(x)
|
||||
case *bitmapContainer:
|
||||
return ac.iandBitmap(x)
|
||||
case *runContainer16:
|
||||
if x.isFull() {
|
||||
return ac.clone()
|
||||
}
|
||||
return x.andArray(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iandBitmap(bc *bitmapContainer) container {
|
||||
pos := 0
|
||||
c := ac.getCardinality()
|
||||
for k := 0; k < c; k++ {
|
||||
// branchless
|
||||
v := ac.content[k]
|
||||
ac.content[pos] = v
|
||||
pos += int(bc.bitValue(v))
|
||||
}
|
||||
ac.content = ac.content[:pos]
|
||||
return ac
|
||||
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) xor(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.xorArray(x)
|
||||
case *bitmapContainer:
|
||||
return a.xor(ac)
|
||||
case *runContainer16:
|
||||
return x.xorArray(ac)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) xorArray(value2 *arrayContainer) container {
|
||||
value1 := ac
|
||||
totalCardinality := value1.getCardinality() + value2.getCardinality()
|
||||
if totalCardinality > arrayDefaultMaxSize { // it could be a bitmap!
|
||||
bc := newBitmapContainer()
|
||||
for k := 0; k < len(value2.content); k++ {
|
||||
v := value2.content[k]
|
||||
i := uint(v) >> 6
|
||||
bc.bitmap[i] ^= (uint64(1) << (v % 64))
|
||||
}
|
||||
for k := 0; k < len(ac.content); k++ {
|
||||
v := ac.content[k]
|
||||
i := uint(v) >> 6
|
||||
bc.bitmap[i] ^= (uint64(1) << (v % 64))
|
||||
}
|
||||
bc.computeCardinality()
|
||||
if bc.cardinality <= arrayDefaultMaxSize {
|
||||
return bc.toArrayContainer()
|
||||
}
|
||||
return bc
|
||||
}
|
||||
desiredCapacity := totalCardinality
|
||||
answer := newArrayContainerCapacity(desiredCapacity)
|
||||
length := exclusiveUnion2by2(value1.content, value2.content, answer.content)
|
||||
answer.content = answer.content[:length]
|
||||
return answer
|
||||
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andNot(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.andNotArray(x)
|
||||
case *bitmapContainer:
|
||||
return ac.andNotBitmap(x)
|
||||
case *runContainer16:
|
||||
return ac.andNotRun16(x)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andNotRun16(rc *runContainer16) container {
|
||||
acb := ac.toBitmapContainer()
|
||||
rcb := rc.toBitmapContainer()
|
||||
return acb.andNotBitmap(rcb)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iandNot(a container) container {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
return ac.iandNotArray(x)
|
||||
case *bitmapContainer:
|
||||
return ac.iandNotBitmap(x)
|
||||
case *runContainer16:
|
||||
return ac.iandNotRun16(x)
|
||||
}
|
||||
panic("unsupported container type")
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iandNotRun16(rc *runContainer16) container {
|
||||
rcb := rc.toBitmapContainer()
|
||||
acb := ac.toBitmapContainer()
|
||||
acb.iandNotBitmapSurely(rcb)
|
||||
*ac = *(acb.toArrayContainer())
|
||||
return ac
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andNotArray(value2 *arrayContainer) container {
|
||||
value1 := ac
|
||||
desiredcapacity := value1.getCardinality()
|
||||
answer := newArrayContainerCapacity(desiredcapacity)
|
||||
length := difference(value1.content, value2.content, answer.content)
|
||||
answer.content = answer.content[:length]
|
||||
return answer
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iandNotArray(value2 *arrayContainer) container {
|
||||
length := difference(ac.content, value2.content, ac.content)
|
||||
ac.content = ac.content[:length]
|
||||
return ac
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andNotBitmap(value2 *bitmapContainer) container {
|
||||
desiredcapacity := ac.getCardinality()
|
||||
answer := newArrayContainerCapacity(desiredcapacity)
|
||||
answer.content = answer.content[:desiredcapacity]
|
||||
pos := 0
|
||||
for _, v := range ac.content {
|
||||
answer.content[pos] = v
|
||||
pos += 1 - int(value2.bitValue(v))
|
||||
}
|
||||
answer.content = answer.content[:pos]
|
||||
return answer
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andBitmap(value2 *bitmapContainer) container {
|
||||
desiredcapacity := ac.getCardinality()
|
||||
answer := newArrayContainerCapacity(desiredcapacity)
|
||||
answer.content = answer.content[:desiredcapacity]
|
||||
pos := 0
|
||||
for _, v := range ac.content {
|
||||
answer.content[pos] = v
|
||||
pos += int(value2.bitValue(v))
|
||||
}
|
||||
answer.content = answer.content[:pos]
|
||||
return answer
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iandNotBitmap(value2 *bitmapContainer) container {
|
||||
pos := 0
|
||||
for _, v := range ac.content {
|
||||
ac.content[pos] = v
|
||||
pos += 1 - int(value2.bitValue(v))
|
||||
}
|
||||
ac.content = ac.content[:pos]
|
||||
return ac
|
||||
}
|
||||
|
||||
func copyOf(array []uint16, size int) []uint16 {
|
||||
result := make([]uint16, size)
|
||||
for i, x := range array {
|
||||
if i == size {
|
||||
break
|
||||
}
|
||||
result[i] = x
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// flip the values in the range [firstOfRange,endx)
|
||||
func (ac *arrayContainer) inot(firstOfRange, endx int) container {
|
||||
if firstOfRange >= endx {
|
||||
return ac
|
||||
}
|
||||
return ac.inotClose(firstOfRange, endx-1) // remove everything in [firstOfRange,endx-1]
|
||||
}
|
||||
|
||||
// flip the values in the range [firstOfRange,lastOfRange]
|
||||
func (ac *arrayContainer) inotClose(firstOfRange, lastOfRange int) container {
|
||||
//p("ac.inotClose() starting")
|
||||
if firstOfRange > lastOfRange { // unlike add and remove, not uses an inclusive range [firstOfRange,lastOfRange]
|
||||
return ac
|
||||
}
|
||||
// determine the span of array indices to be affected
|
||||
startIndex := binarySearch(ac.content, uint16(firstOfRange))
|
||||
if startIndex < 0 {
|
||||
startIndex = -startIndex - 1
|
||||
}
|
||||
lastIndex := binarySearch(ac.content, uint16(lastOfRange))
|
||||
if lastIndex < 0 {
|
||||
lastIndex = -lastIndex - 1 - 1
|
||||
}
|
||||
currentValuesInRange := lastIndex - startIndex + 1
|
||||
spanToBeFlipped := lastOfRange - firstOfRange + 1
|
||||
|
||||
newValuesInRange := spanToBeFlipped - currentValuesInRange
|
||||
buffer := make([]uint16, newValuesInRange)
|
||||
cardinalityChange := newValuesInRange - currentValuesInRange
|
||||
newCardinality := len(ac.content) + cardinalityChange
|
||||
if cardinalityChange > 0 {
|
||||
if newCardinality > len(ac.content) {
|
||||
if newCardinality > arrayDefaultMaxSize {
|
||||
//p("ac.inotClose() converting to bitmap and doing inot there")
|
||||
bcRet := ac.toBitmapContainer()
|
||||
bcRet.inot(firstOfRange, lastOfRange+1)
|
||||
*ac = *bcRet.toArrayContainer()
|
||||
return bcRet
|
||||
}
|
||||
ac.content = copyOf(ac.content, newCardinality)
|
||||
}
|
||||
base := lastIndex + 1
|
||||
copy(ac.content[lastIndex+1+cardinalityChange:], ac.content[base:base+len(ac.content)-1-lastIndex])
|
||||
ac.negateRange(buffer, startIndex, lastIndex, firstOfRange, lastOfRange+1)
|
||||
} else { // no expansion needed
|
||||
ac.negateRange(buffer, startIndex, lastIndex, firstOfRange, lastOfRange+1)
|
||||
if cardinalityChange < 0 {
|
||||
|
||||
for i := startIndex + newValuesInRange; i < newCardinality; i++ {
|
||||
ac.content[i] = ac.content[i-cardinalityChange]
|
||||
}
|
||||
}
|
||||
}
|
||||
ac.content = ac.content[:newCardinality]
|
||||
//p("bottom of ac.inotClose(): returning ac")
|
||||
return ac
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) negateRange(buffer []uint16, startIndex, lastIndex, startRange, lastRange int) {
|
||||
// compute the negation into buffer
|
||||
outPos := 0
|
||||
inPos := startIndex // value here always >= valInRange,
|
||||
// until it is exhausted
|
||||
// n.b., we can start initially exhausted.
|
||||
|
||||
valInRange := startRange
|
||||
for ; valInRange < lastRange && inPos <= lastIndex; valInRange++ {
|
||||
if uint16(valInRange) != ac.content[inPos] {
|
||||
buffer[outPos] = uint16(valInRange)
|
||||
outPos++
|
||||
} else {
|
||||
inPos++
|
||||
}
|
||||
}
|
||||
|
||||
// if there are extra items (greater than the biggest
|
||||
// pre-existing one in range), buffer them
|
||||
for ; valInRange < lastRange; valInRange++ {
|
||||
buffer[outPos] = uint16(valInRange)
|
||||
outPos++
|
||||
}
|
||||
|
||||
if outPos != len(buffer) {
|
||||
panic("negateRange: internal bug")
|
||||
}
|
||||
|
||||
for i, item := range buffer {
|
||||
ac.content[i+startIndex] = item
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) isFull() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andArray(value2 *arrayContainer) container {
|
||||
desiredcapacity := minOfInt(ac.getCardinality(), value2.getCardinality())
|
||||
answer := newArrayContainerCapacity(desiredcapacity)
|
||||
length := intersection2by2(
|
||||
ac.content,
|
||||
value2.content,
|
||||
answer.content)
|
||||
answer.content = answer.content[:length]
|
||||
return answer
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) andArrayCardinality(value2 *arrayContainer) int {
|
||||
return intersection2by2Cardinality(
|
||||
ac.content,
|
||||
value2.content)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) intersectsArray(value2 *arrayContainer) bool {
|
||||
return intersects2by2(
|
||||
ac.content,
|
||||
value2.content)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iandArray(value2 *arrayContainer) container {
|
||||
length := intersection2by2(
|
||||
ac.content,
|
||||
value2.content,
|
||||
ac.content)
|
||||
ac.content = ac.content[:length]
|
||||
return ac
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) getCardinality() int {
|
||||
return len(ac.content)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) rank(x uint16) int {
|
||||
answer := binarySearch(ac.content, x)
|
||||
if answer >= 0 {
|
||||
return answer + 1
|
||||
}
|
||||
return -answer - 1
|
||||
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) selectInt(x uint16) int {
|
||||
return int(ac.content[x])
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) clone() container {
|
||||
ptr := arrayContainer{make([]uint16, len(ac.content))}
|
||||
copy(ptr.content, ac.content[:])
|
||||
return &ptr
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) contains(x uint16) bool {
|
||||
return binarySearch(ac.content, x) >= 0
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) loadData(bitmapContainer *bitmapContainer) {
|
||||
ac.content = make([]uint16, bitmapContainer.cardinality, bitmapContainer.cardinality)
|
||||
bitmapContainer.fillArray(ac.content)
|
||||
}
|
||||
func newArrayContainer() *arrayContainer {
|
||||
p := new(arrayContainer)
|
||||
return p
|
||||
}
|
||||
|
||||
func newArrayContainerFromBitmap(bc *bitmapContainer) *arrayContainer {
|
||||
ac := &arrayContainer{}
|
||||
ac.loadData(bc)
|
||||
return ac
|
||||
}
|
||||
|
||||
func newArrayContainerCapacity(size int) *arrayContainer {
|
||||
p := new(arrayContainer)
|
||||
p.content = make([]uint16, 0, size)
|
||||
return p
|
||||
}
|
||||
|
||||
func newArrayContainerSize(size int) *arrayContainer {
|
||||
p := new(arrayContainer)
|
||||
p.content = make([]uint16, size, size)
|
||||
return p
|
||||
}
|
||||
|
||||
func newArrayContainerRange(firstOfRun, lastOfRun int) *arrayContainer {
|
||||
valuesInRange := lastOfRun - firstOfRun + 1
|
||||
this := newArrayContainerCapacity(valuesInRange)
|
||||
for i := 0; i < valuesInRange; i++ {
|
||||
this.content = append(this.content, uint16(firstOfRun+i))
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) numberOfRuns() (nr int) {
|
||||
n := len(ac.content)
|
||||
var runlen uint16
|
||||
var cur, prev uint16
|
||||
|
||||
switch n {
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
default:
|
||||
for i := 1; i < n; i++ {
|
||||
prev = ac.content[i-1]
|
||||
cur = ac.content[i]
|
||||
|
||||
if cur == prev+1 {
|
||||
runlen++
|
||||
} else {
|
||||
if cur < prev {
|
||||
panic("then fundamental arrayContainer assumption of sorted ac.content was broken")
|
||||
}
|
||||
if cur == prev {
|
||||
panic("then fundamental arrayContainer assumption of deduplicated content was broken")
|
||||
} else {
|
||||
nr++
|
||||
runlen = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
nr++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// convert to run or array *if needed*
|
||||
func (ac *arrayContainer) toEfficientContainer() container {
|
||||
|
||||
numRuns := ac.numberOfRuns()
|
||||
|
||||
sizeAsRunContainer := runContainer16SerializedSizeInBytes(numRuns)
|
||||
sizeAsBitmapContainer := bitmapContainerSizeInBytes()
|
||||
card := ac.getCardinality()
|
||||
sizeAsArrayContainer := arrayContainerSizeInBytes(card)
|
||||
|
||||
if sizeAsRunContainer <= minOfInt(sizeAsBitmapContainer, sizeAsArrayContainer) {
|
||||
return newRunContainer16FromArray(ac)
|
||||
}
|
||||
if card <= arrayDefaultMaxSize {
|
||||
return ac
|
||||
}
|
||||
return ac.toBitmapContainer()
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) containerType() contype {
|
||||
return arrayContype
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue