|
|
- 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
-
- // 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 & 0xFFFF)
- }
-
- 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++ {
- //p("flipBitmapRange on i=%v", 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
- }
-
- func maxInt(a, b int) int {
- if a > b {
- return a
- }
- return b
- }
-
- func maxUint16(a, b uint16) uint16 {
- if a > b {
- return a
- }
- return b
- }
-
- func minUint16(a, b uint16) uint16 {
- if a < b {
- return a
- }
- return b
- }
|