| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048 |
- package roaring
- import (
- "fmt"
- )
- 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) int {
- for k := 0; k < len(ac.content); k++ {
- x[k+i] = uint32(ac.content[k]) | mask
- }
- return i + len(ac.content)
- }
- func (ac *arrayContainer) iterate(cb func(x uint16) bool) bool {
- iterator := shortIterator{ac.content, 0}
- for iterator.hasNext() {
- if !cb(iterator.next()) {
- return false
- }
- }
- return true
- }
- func (ac *arrayContainer) getShortIterator() shortPeekable {
- return &shortIterator{ac.content, 0}
- }
- func (ac *arrayContainer) getReverseIterator() shortIterable {
- return &reverseIterator{ac.content, len(ac.content) - 1}
- }
- func (ac *arrayContainer) getManyIterator() manyIterable {
- return &shortIterator{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 {
- 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]
- return ac.clone()
- }
- // determine the span of array indices to be affected^M
- startIndex := binarySearch(ac.content, uint16(firstOfRange))
- if startIndex < 0 {
- startIndex = -startIndex - 1
- }
- lastIndex := binarySearch(ac.content, uint16(lastOfRange))
- 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
- if newCardinality > arrayDefaultMaxSize {
- 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 > cap(value1.content) {
- // doubling the capacity reduces new slice allocations in the case of
- // repeated calls to iorArray().
- newSize := 2 * maxPossibleCardinality
- // the second check is to handle overly large array containers
- // and should not occur in normal usage,
- // as all array containers should be at most arrayDefaultMaxSize
- if newSize > 2*arrayDefaultMaxSize && maxPossibleCardinality <= 2*arrayDefaultMaxSize {
- newSize = 2 * arrayDefaultMaxSize
- }
- newcontent := make([]uint16, 0, newSize)
- 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
- if nl > arrayDefaultMaxSize {
- // Only converting to a bitmap when arrayDefaultMaxSize
- // is actually exceeded minimizes conversions in the case of repeated
- // calls to iorArray().
- return ac.toBitmapContainer()
- }
- 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 {
- runCardinality := rc.getCardinality()
- // heuristic for if the container should maybe be an
- // array container.
- if runCardinality < ac.getCardinality() &&
- runCardinality+ac.getCardinality() < arrayDefaultMaxSize {
- var result container
- result = ac
- for _, run := range rc.iv {
- result = result.iaddRange(int(run.start), int(run.start)+int(run.length)+1)
- }
- return result
- }
- return rc.orArray(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!
- 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 {
- 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
- }
- 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 {
- 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 {
- 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]
- 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) isEmpty() bool {
- return len(ac.content) == 0
- }
- 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 (ac *arrayContainer) resetTo(a container) {
- switch x := a.(type) {
- case *arrayContainer:
- ac.realloc(len(x.content))
- copy(ac.content, x.content)
- case *bitmapContainer:
- ac.realloc(x.cardinality)
- x.fillArray(ac.content)
- case *runContainer16:
- card := int(x.getCardinality())
- ac.realloc(card)
- cur := 0
- for _, r := range x.iv {
- for val := r.start; val <= r.last(); val++ {
- ac.content[cur] = val
- cur++
- }
- }
- default:
- panic("unsupported container type")
- }
- }
- func (ac *arrayContainer) realloc(size int) {
- if cap(ac.content) < size {
- ac.content = make([]uint16, size)
- } else {
- ac.content = ac.content[:size]
- }
- }
- 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("the fundamental arrayContainer assumption of sorted ac.content was broken")
- }
- if cur == prev {
- panic("the 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
- }
- func (ac *arrayContainer) addOffset(x uint16) (container, container) {
- var low, high *arrayContainer
- if len(ac.content) == 0 {
- return nil, nil
- }
- if y := uint32(ac.content[0]) + uint32(x); highbits(y) == 0 {
- // Some elements will fall into low part, allocate a container.
- // Checking the first one is enough because they are ordered.
- low = &arrayContainer{}
- }
- if y := uint32(ac.content[len(ac.content)-1]) + uint32(x); highbits(y) > 0 {
- // Some elements will fall into high part, allocate a container.
- // Checking the last one is enough because they are ordered.
- high = &arrayContainer{}
- }
- for _, val := range ac.content {
- y := uint32(val) + uint32(x)
- if highbits(y) > 0 {
- // OK, if high == nil then highbits(y) == 0 for all y.
- high.content = append(high.content, lowbits(y))
- } else {
- // OK, if low == nil then highbits(y) > 0 for all y.
- low.content = append(low.content, lowbits(y))
- }
- }
- // Ensure proper nil interface.
- if low == nil {
- return nil, high
- }
- if high == nil {
- return low, nil
- }
- return low, high
- }
|