123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- package roaring
-
- import (
- "math/rand"
- "sort"
- )
-
- const (
- arrayDefaultMaxSize = 4096 // containers with 4096 or fewer integers should be array containers.
- arrayLazyLowerBound = 1024
- maxCapacity = 1 << 16
- serialCookieNoRunContainer = 12346 // only arrays and bitmaps
- invalidCardinality = -1
- serialCookie = 12347 // runs, arrays, and bitmaps
- noOffsetThreshold = 4
-
- // MaxUint32 is the largest uint32 value.
- MaxUint32 = 4294967295
-
- // MaxRange is One more than the maximum allowed bitmap bit index. For use as an upper
- // bound for ranges.
- MaxRange uint64 = MaxUint32 + 1
-
- // MaxUint16 is the largest 16 bit unsigned int.
- // This is the largest value an interval16 can store.
- MaxUint16 = 65535
-
- // Compute wordSizeInBytes, the size of a word in bytes.
- _m = ^uint64(0)
- _logS = _m>>8&1 + _m>>16&1 + _m>>32&1
- wordSizeInBytes = 1 << _logS
-
- // other constants used in ctz_generic.go
- wordSizeInBits = wordSizeInBytes << 3 // word size in bits
- )
-
- const maxWord = 1<<wordSizeInBits - 1
-
- // doesn't apply to runContainers
- func getSizeInBytesFromCardinality(card int) int {
- if card > arrayDefaultMaxSize {
- // bitmapContainer
- return maxCapacity / 8
- }
- // arrayContainer
- return 2 * card
- }
-
- func fill(arr []uint64, val uint64) {
- for i := range arr {
- arr[i] = val
- }
- }
- func fillRange(arr []uint64, start, end int, val uint64) {
- for i := start; i < end; i++ {
- arr[i] = val
- }
- }
-
- func fillArrayAND(container []uint16, bitmap1, bitmap2 []uint64) {
- if len(bitmap1) != len(bitmap2) {
- panic("array lengths don't match")
- }
- // TODO: rewrite in assembly
- pos := 0
- for k := range bitmap1 {
- bitset := bitmap1[k] & bitmap2[k]
- for bitset != 0 {
- t := bitset & -bitset
- container[pos] = uint16((k*64 + int(popcount(t-1))))
- pos = pos + 1
- bitset ^= t
- }
- }
- }
-
- func fillArrayANDNOT(container []uint16, bitmap1, bitmap2 []uint64) {
- if len(bitmap1) != len(bitmap2) {
- panic("array lengths don't match")
- }
- // TODO: rewrite in assembly
- pos := 0
- for k := range bitmap1 {
- bitset := bitmap1[k] &^ bitmap2[k]
- for bitset != 0 {
- t := bitset & -bitset
- container[pos] = uint16((k*64 + int(popcount(t-1))))
- pos = pos + 1
- bitset ^= t
- }
- }
- }
-
- func fillArrayXOR(container []uint16, bitmap1, bitmap2 []uint64) {
- if len(bitmap1) != len(bitmap2) {
- panic("array lengths don't match")
- }
- // TODO: rewrite in assembly
- pos := 0
- for k := 0; k < len(bitmap1); k++ {
- bitset := bitmap1[k] ^ bitmap2[k]
- for bitset != 0 {
- t := bitset & -bitset
- container[pos] = uint16((k*64 + int(popcount(t-1))))
- pos = pos + 1
- bitset ^= t
- }
- }
- }
-
- func highbits(x uint32) uint16 {
- return uint16(x >> 16)
- }
- func lowbits(x uint32) uint16 {
- return uint16(x & maxLowBit)
- }
-
- const maxLowBit = 0xFFFF
-
- func flipBitmapRange(bitmap []uint64, start int, end int) {
- if start >= end {
- return
- }
- firstword := start / 64
- endword := (end - 1) / 64
- bitmap[firstword] ^= ^(^uint64(0) << uint(start%64))
- for i := firstword; i < endword; i++ {
- bitmap[i] = ^bitmap[i]
- }
- bitmap[endword] ^= ^uint64(0) >> (uint(-end) % 64)
- }
-
- func resetBitmapRange(bitmap []uint64, start int, end int) {
- if start >= end {
- return
- }
- firstword := start / 64
- endword := (end - 1) / 64
- if firstword == endword {
- bitmap[firstword] &= ^((^uint64(0) << uint(start%64)) & (^uint64(0) >> (uint(-end) % 64)))
- return
- }
- bitmap[firstword] &= ^(^uint64(0) << uint(start%64))
- for i := firstword + 1; i < endword; i++ {
- bitmap[i] = 0
- }
- bitmap[endword] &= ^(^uint64(0) >> (uint(-end) % 64))
-
- }
-
- func setBitmapRange(bitmap []uint64, start int, end int) {
- if start >= end {
- return
- }
- firstword := start / 64
- endword := (end - 1) / 64
- if firstword == endword {
- bitmap[firstword] |= (^uint64(0) << uint(start%64)) & (^uint64(0) >> (uint(-end) % 64))
- return
- }
- bitmap[firstword] |= ^uint64(0) << uint(start%64)
- for i := firstword + 1; i < endword; i++ {
- bitmap[i] = ^uint64(0)
- }
- bitmap[endword] |= ^uint64(0) >> (uint(-end) % 64)
- }
-
- func flipBitmapRangeAndCardinalityChange(bitmap []uint64, start int, end int) int {
- before := wordCardinalityForBitmapRange(bitmap, start, end)
- flipBitmapRange(bitmap, start, end)
- after := wordCardinalityForBitmapRange(bitmap, start, end)
- return int(after - before)
- }
-
- func resetBitmapRangeAndCardinalityChange(bitmap []uint64, start int, end int) int {
- before := wordCardinalityForBitmapRange(bitmap, start, end)
- resetBitmapRange(bitmap, start, end)
- after := wordCardinalityForBitmapRange(bitmap, start, end)
- return int(after - before)
- }
-
- func setBitmapRangeAndCardinalityChange(bitmap []uint64, start int, end int) int {
- before := wordCardinalityForBitmapRange(bitmap, start, end)
- setBitmapRange(bitmap, start, end)
- after := wordCardinalityForBitmapRange(bitmap, start, end)
- return int(after - before)
- }
-
- func wordCardinalityForBitmapRange(bitmap []uint64, start int, end int) uint64 {
- answer := uint64(0)
- if start >= end {
- return answer
- }
- firstword := start / 64
- endword := (end - 1) / 64
- for i := firstword; i <= endword; i++ {
- answer += popcount(bitmap[i])
- }
- return answer
- }
-
- func selectBitPosition(w uint64, j int) int {
- seen := 0
-
- // Divide 64bit
- part := w & 0xFFFFFFFF
- n := popcount(part)
- if n <= uint64(j) {
- part = w >> 32
- seen += 32
- j -= int(n)
- }
- w = part
-
- // Divide 32bit
- part = w & 0xFFFF
- n = popcount(part)
- if n <= uint64(j) {
- part = w >> 16
- seen += 16
- j -= int(n)
- }
- w = part
-
- // Divide 16bit
- part = w & 0xFF
- n = popcount(part)
- if n <= uint64(j) {
- part = w >> 8
- seen += 8
- j -= int(n)
- }
- w = part
-
- // Lookup in final byte
- var counter uint
- for counter = 0; counter < 8; counter++ {
- j -= int((w >> counter) & 1)
- if j < 0 {
- break
- }
- }
- return seen + int(counter)
-
- }
-
- func panicOn(err error) {
- if err != nil {
- panic(err)
- }
- }
-
- type ph struct {
- orig int
- rand int
- }
-
- type pha []ph
-
- func (p pha) Len() int { return len(p) }
- func (p pha) Less(i, j int) bool { return p[i].rand < p[j].rand }
- func (p pha) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-
- func getRandomPermutation(n int) []int {
- r := make([]ph, n)
- for i := 0; i < n; i++ {
- r[i].orig = i
- r[i].rand = rand.Intn(1 << 29)
- }
- sort.Sort(pha(r))
- m := make([]int, n)
- for i := range m {
- m[i] = r[i].orig
- }
- return m
- }
-
- func minOfInt(a, b int) int {
- if a < b {
- return a
- }
- return b
- }
-
- func maxOfInt(a, b int) int {
- if a > b {
- return a
- }
- return b
- }
-
- func maxOfUint16(a, b uint16) uint16 {
- if a > b {
- return a
- }
- return b
- }
-
- func minOfUint16(a, b uint16) uint16 {
- if a < b {
- return a
- }
- return b
- }
|