github.com/coyove/sdss@v0.0.0-20231129015646-c2ec58cca6a2/contrib/roaring/util.go (about) 1 package roaring 2 3 import ( 4 "math" 5 "math/rand" 6 "sort" 7 ) 8 9 const ( 10 arrayDefaultMaxSize = 4096 // containers with 4096 or fewer integers should be array containers. 11 arrayLazyLowerBound = 1024 12 maxCapacity = 1 << 16 13 serialCookieNoRunContainer = 12346 // only arrays and bitmaps 14 invalidCardinality = -1 15 serialCookie = 12347 // runs, arrays, and bitmaps 16 noOffsetThreshold = 4 17 18 // MaxUint32 is the largest uint32 value. 19 MaxUint32 = math.MaxUint32 20 21 // MaxRange is One more than the maximum allowed bitmap bit index. For use as an upper 22 // bound for ranges. 23 MaxRange uint64 = MaxUint32 + 1 24 25 // MaxUint16 is the largest 16 bit unsigned int. 26 // This is the largest value an interval16 can store. 27 MaxUint16 = math.MaxUint16 28 29 // Compute wordSizeInBytes, the size of a word in bytes. 30 _m = ^uint64(0) 31 _logS = _m>>8&1 + _m>>16&1 + _m>>32&1 32 wordSizeInBytes = 1 << _logS 33 34 // other constants used in ctz_generic.go 35 wordSizeInBits = wordSizeInBytes << 3 // word size in bits 36 ) 37 38 const maxWord = 1<<wordSizeInBits - 1 39 40 // doesn't apply to runContainers 41 func getSizeInBytesFromCardinality(card int) int { 42 if card > arrayDefaultMaxSize { 43 // bitmapContainer 44 return maxCapacity / 8 45 } 46 // arrayContainer 47 return 2 * card 48 } 49 50 func fill(arr []uint64, val uint64) { 51 for i := range arr { 52 arr[i] = val 53 } 54 } 55 func fillRange(arr []uint64, start, end int, val uint64) { 56 for i := start; i < end; i++ { 57 arr[i] = val 58 } 59 } 60 61 func fillArrayAND(container []uint16, bitmap1, bitmap2 []uint64) { 62 if len(bitmap1) != len(bitmap2) { 63 panic("array lengths don't match") 64 } 65 // TODO: rewrite in assembly 66 pos := 0 67 for k := range bitmap1 { 68 bitset := bitmap1[k] & bitmap2[k] 69 for bitset != 0 { 70 t := bitset & -bitset 71 container[pos] = uint16((k*64 + int(popcount(t-1)))) 72 pos = pos + 1 73 bitset ^= t 74 } 75 } 76 } 77 78 func fillArrayANDNOT(container []uint16, bitmap1, bitmap2 []uint64) { 79 if len(bitmap1) != len(bitmap2) { 80 panic("array lengths don't match") 81 } 82 // TODO: rewrite in assembly 83 pos := 0 84 for k := range bitmap1 { 85 bitset := bitmap1[k] &^ bitmap2[k] 86 for bitset != 0 { 87 t := bitset & -bitset 88 container[pos] = uint16((k*64 + int(popcount(t-1)))) 89 pos = pos + 1 90 bitset ^= t 91 } 92 } 93 } 94 95 func fillArrayXOR(container []uint16, bitmap1, bitmap2 []uint64) { 96 if len(bitmap1) != len(bitmap2) { 97 panic("array lengths don't match") 98 } 99 // TODO: rewrite in assembly 100 pos := 0 101 for k := 0; k < len(bitmap1); k++ { 102 bitset := bitmap1[k] ^ bitmap2[k] 103 for bitset != 0 { 104 t := bitset & -bitset 105 container[pos] = uint16((k*64 + int(popcount(t-1)))) 106 pos = pos + 1 107 bitset ^= t 108 } 109 } 110 } 111 112 func highbits(x uint32) uint16 { 113 return uint16(x >> 16) 114 } 115 func lowbits(x uint32) uint16 { 116 return uint16(x & maxLowBit) 117 } 118 119 const maxLowBit = 0xFFFF 120 121 func flipBitmapRange(bitmap []uint64, start int, end int) { 122 if start >= end { 123 return 124 } 125 firstword := start / 64 126 endword := (end - 1) / 64 127 bitmap[firstword] ^= ^(^uint64(0) << uint(start%64)) 128 for i := firstword; i < endword; i++ { 129 bitmap[i] = ^bitmap[i] 130 } 131 bitmap[endword] ^= ^uint64(0) >> (uint(-end) % 64) 132 } 133 134 func resetBitmapRange(bitmap []uint64, start int, end int) { 135 if start >= end { 136 return 137 } 138 firstword := start / 64 139 endword := (end - 1) / 64 140 if firstword == endword { 141 bitmap[firstword] &= ^((^uint64(0) << uint(start%64)) & (^uint64(0) >> (uint(-end) % 64))) 142 return 143 } 144 bitmap[firstword] &= ^(^uint64(0) << uint(start%64)) 145 for i := firstword + 1; i < endword; i++ { 146 bitmap[i] = 0 147 } 148 bitmap[endword] &= ^(^uint64(0) >> (uint(-end) % 64)) 149 150 } 151 152 func setBitmapRange(bitmap []uint64, start int, end int) { 153 if start >= end { 154 return 155 } 156 firstword := start / 64 157 endword := (end - 1) / 64 158 if firstword == endword { 159 bitmap[firstword] |= (^uint64(0) << uint(start%64)) & (^uint64(0) >> (uint(-end) % 64)) 160 return 161 } 162 bitmap[firstword] |= ^uint64(0) << uint(start%64) 163 for i := firstword + 1; i < endword; i++ { 164 bitmap[i] = ^uint64(0) 165 } 166 bitmap[endword] |= ^uint64(0) >> (uint(-end) % 64) 167 } 168 169 func flipBitmapRangeAndCardinalityChange(bitmap []uint64, start int, end int) int { 170 before := wordCardinalityForBitmapRange(bitmap, start, end) 171 flipBitmapRange(bitmap, start, end) 172 after := wordCardinalityForBitmapRange(bitmap, start, end) 173 return int(after - before) 174 } 175 176 func resetBitmapRangeAndCardinalityChange(bitmap []uint64, start int, end int) int { 177 before := wordCardinalityForBitmapRange(bitmap, start, end) 178 resetBitmapRange(bitmap, start, end) 179 after := wordCardinalityForBitmapRange(bitmap, start, end) 180 return int(after - before) 181 } 182 183 func setBitmapRangeAndCardinalityChange(bitmap []uint64, start int, end int) int { 184 before := wordCardinalityForBitmapRange(bitmap, start, end) 185 setBitmapRange(bitmap, start, end) 186 after := wordCardinalityForBitmapRange(bitmap, start, end) 187 return int(after - before) 188 } 189 190 func wordCardinalityForBitmapRange(bitmap []uint64, start int, end int) uint64 { 191 answer := uint64(0) 192 if start >= end { 193 return answer 194 } 195 firstword := start / 64 196 endword := (end - 1) / 64 197 for i := firstword; i <= endword; i++ { 198 answer += popcount(bitmap[i]) 199 } 200 return answer 201 } 202 203 func selectBitPosition(w uint64, j int) int { 204 seen := 0 205 206 // Divide 64bit 207 part := w & 0xFFFFFFFF 208 n := popcount(part) 209 if n <= uint64(j) { 210 part = w >> 32 211 seen += 32 212 j -= int(n) 213 } 214 w = part 215 216 // Divide 32bit 217 part = w & 0xFFFF 218 n = popcount(part) 219 if n <= uint64(j) { 220 part = w >> 16 221 seen += 16 222 j -= int(n) 223 } 224 w = part 225 226 // Divide 16bit 227 part = w & 0xFF 228 n = popcount(part) 229 if n <= uint64(j) { 230 part = w >> 8 231 seen += 8 232 j -= int(n) 233 } 234 w = part 235 236 // Lookup in final byte 237 var counter uint 238 for counter = 0; counter < 8; counter++ { 239 j -= int((w >> counter) & 1) 240 if j < 0 { 241 break 242 } 243 } 244 return seen + int(counter) 245 246 } 247 248 func panicOn(err error) { 249 if err != nil { 250 panic(err) 251 } 252 } 253 254 type ph struct { 255 orig int 256 rand int 257 } 258 259 type pha []ph 260 261 func (p pha) Len() int { return len(p) } 262 func (p pha) Less(i, j int) bool { return p[i].rand < p[j].rand } 263 func (p pha) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 264 265 func getRandomPermutation(n int) []int { 266 r := make([]ph, n) 267 for i := 0; i < n; i++ { 268 r[i].orig = i 269 r[i].rand = rand.Intn(1 << 29) 270 } 271 sort.Sort(pha(r)) 272 m := make([]int, n) 273 for i := range m { 274 m[i] = r[i].orig 275 } 276 return m 277 } 278 279 func minOfInt(a, b int) int { 280 if a < b { 281 return a 282 } 283 return b 284 } 285 286 func maxOfInt(a, b int) int { 287 if a > b { 288 return a 289 } 290 return b 291 } 292 293 func maxOfUint16(a, b uint16) uint16 { 294 if a > b { 295 return a 296 } 297 return b 298 } 299 300 func minOfUint16(a, b uint16) uint16 { 301 if a < b { 302 return a 303 } 304 return b 305 }