github.com/outcaste-io/sroar@v0.0.0-20221229172112-1fb64f14314c/bitmap_test.go (about) 1 package sroar 2 3 import ( 4 "math" 5 "math/rand" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 func fill(c []uint16, b uint16) { 13 for i := range c[startIdx:] { 14 c[i+int(startIdx)] = b 15 } 16 } 17 18 func TestModify(t *testing.T) { 19 data := make([]uint16, 16) 20 s := toUint64Slice(data) 21 for i := 0; i < len(s); i++ { 22 s[i] = uint64(i) 23 } 24 25 o := toUint64Slice(data) 26 for i := 0; i < len(o); i++ { 27 require.Equal(t, uint64(i), o[i]) 28 } 29 } 30 31 func TestContainer(t *testing.T) { 32 ra := NewBitmap() 33 34 // We're creating a container of size 64 words. 4 of these would be used for 35 // the header. So, the data can only live in 60 words. 36 offset := ra.newContainer(64) 37 c := ra.getContainer(offset) 38 require.Equal(t, uint16(64), ra.data[offset]) 39 require.Equal(t, uint16(0), c[indexCardinality]) 40 41 fill(c, 0xFF) 42 for i, u := range c[startIdx:] { 43 if i < 60 { 44 require.Equalf(t, uint16(0xFF), u, "at index: %d", i) 45 } else { 46 require.Equalf(t, uint16(0x00), u, "at index: %d", i) 47 } 48 } 49 50 offset2 := ra.newContainer(32) // Add a second container. 51 c2 := ra.getContainer(offset2) 52 require.Equal(t, uint16(32), ra.data[offset2]) 53 fill(c2, 0xEE) 54 55 // Expand the first container. This would push out the second container, so update its offset. 56 ra.expandContainer(offset) 57 offset2 += 64 58 59 // Check if the second container is correct. 60 c2 = ra.getContainer(offset2) 61 require.Equal(t, uint16(32), ra.data[offset2]) 62 require.Equal(t, 32, len(c2)) 63 for _, val := range c2[startIdx:] { 64 require.Equal(t, uint16(0xEE), val) 65 } 66 67 // Check if the first container is correct. 68 c = ra.getContainer(offset) 69 require.Equal(t, uint16(128), ra.data[offset]) 70 require.Equal(t, 128, len(c)) 71 for i, u := range c[startIdx:] { 72 if i < 60 { 73 require.Equalf(t, uint16(0xFF), u, "at index: %d", i) 74 } else { 75 require.Equalf(t, uint16(0x00), u, "at index: %d", i) 76 } 77 } 78 } 79 80 func TestKey(t *testing.T) { 81 ra := NewBitmap() 82 for i := 1; i <= 10; i++ { 83 ra.Set(uint64(i)) 84 } 85 86 off, has := ra.keys.getValue(0) 87 require.True(t, has) 88 c := ra.getContainer(off) 89 require.Equal(t, uint16(10), c[indexCardinality]) 90 91 // Create 10 containers 92 for i := 0; i < 10; i++ { 93 t.Logf("Creating a new container: %d\n", i) 94 ra.Set(uint64(i)<<16 + 1) 95 } 96 97 for i := 0; i < 10; i++ { 98 ra.Set(uint64(i)<<16 + 2) 99 } 100 101 for i := 1; i < 10; i++ { 102 offset, has := ra.keys.getValue(uint64(i) << 16) 103 require.True(t, has) 104 c = ra.getContainer(offset) 105 require.Equal(t, uint16(2), c[indexCardinality]) 106 } 107 108 // Do add in the reverse order. 109 for i := 19; i >= 10; i-- { 110 ra.Set(uint64(i)<<16 + 2) 111 } 112 113 for i := 10; i < 20; i++ { 114 offset, has := ra.keys.getValue(uint64(i) << 16) 115 require.True(t, has) 116 c = ra.getContainer(offset) 117 require.Equal(t, uint16(1), c[indexCardinality]) 118 } 119 } 120 121 func TestEdgeCase(t *testing.T) { 122 ra := NewBitmap() 123 124 require.True(t, ra.Set(65536)) 125 require.True(t, ra.Contains(65536)) 126 } 127 128 func TestBulkAdd(t *testing.T) { 129 ra := NewBitmap() 130 m := make(map[uint64]struct{}) 131 max := int64(64 << 16) 132 start := time.Now() 133 134 var cnt int 135 for i := 0; ; i++ { 136 if i%100 == 0 && time.Since(start) > time.Second { 137 cnt++ 138 start = time.Now() 139 // t.Logf("Bitmap:\n%s\n", ra) 140 if cnt == 3 { 141 t.Logf("Breaking out of the loop\n") 142 break 143 } 144 } 145 x := uint64(rand.Int63n(max)) 146 147 if _, has := m[x]; has { 148 if !ra.Contains(x) { 149 t.Logf("x should be present: %d %#x. Bitmap: %s\n", x, x, ra) 150 off, found := ra.keys.getValue(x & mask) 151 assert(found) 152 c := ra.getContainer(off) 153 lo := uint16(x) 154 t.Logf("x: %#x lo: %#x. offset: %d\n", x, lo, off) 155 switch c[indexType] { 156 case typeArray: 157 case typeBitmap: 158 idx := lo / 16 159 pos := lo % 16 160 t.Logf("At idx: %d. Pos: %d val: %#b\n", idx, pos, c[startIdx+idx]) 161 } 162 163 t.Logf("Added: %d %#x. Added: %v\n", x, x, ra.Set(x)) 164 t.Logf("After add. has: %v\n", ra.Contains(x)) 165 166 // t.Logf("Hex dump of container at offset: %d\n%s\n", off, hex.Dump(toByteSlice(c))) 167 t.FailNow() 168 } 169 continue 170 } 171 m[x] = struct{}{} 172 // fmt.Printf("Setting x: %#x\n", x) 173 if added := ra.Set(x); !added { 174 t.Logf("Unable to set: %d %#x\n", x, x) 175 t.Logf("ra.Has(x): %v\n", ra.Contains(x)) 176 t.FailNow() 177 } 178 // for x := range m { 179 // if !ra.Has(x) { 180 // t.Logf("has(x) failed: %#x\n", x) 181 // t.Logf("Debug: %s\n", ra.Debug(x)) 182 // t.FailNow() 183 // } 184 // } 185 // require.Truef(t, ra.Set(x), "Unable to set x: %d %#x\n", x, x) 186 } 187 t.Logf("Card: %d\n", len(m)) 188 require.Equalf(t, len(m), ra.GetCardinality(), "Bitmap:\n%s\n", ra) 189 for x := range m { 190 require.True(t, ra.Contains(x)) 191 } 192 193 // _, has := ra.keys.getValue(0) 194 // require.True(t, has) 195 // for i := uint64(1); i <= max; i++ { 196 // require.Truef(t, ra.Has(i), "i=%d", i) 197 // } 198 // t.Logf("Data size: %d\n", len(ra.data)) 199 200 t.Logf("Copying data. Size: %d\n", len(ra.data)) 201 dup := make([]uint16, len(ra.data)) 202 copy(dup, ra.data) 203 204 ra2 := FromBuffer(toByteSlice(dup)) 205 require.Equal(t, len(m), ra2.GetCardinality()) 206 for x := range m { 207 require.True(t, ra2.Contains(x)) 208 } 209 } 210 211 func TestBitmapUint64Max(t *testing.T) { 212 bm := NewBitmap() 213 214 edges := []uint64{0, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64} 215 for _, e := range edges { 216 bm.Set(e) 217 } 218 for _, e := range edges { 219 require.True(t, bm.Contains(e)) 220 } 221 } 222 223 func TestBitmapZero(t *testing.T) { 224 bm1 := NewBitmap() 225 bm1.Set(1) 226 uids := bm1.ToArray() 227 require.Equal(t, 1, len(uids)) 228 for _, u := range uids { 229 require.Equal(t, uint64(1), u) 230 } 231 232 bm2 := NewBitmap() 233 bm2.Set(2) 234 235 bm3 := Or(bm1, bm2) 236 require.False(t, bm3.Contains(0)) 237 require.True(t, bm3.Contains(1)) 238 require.True(t, bm3.Contains(2)) 239 require.Equal(t, 2, bm3.GetCardinality()) 240 } 241 242 func TestBitmapOps(t *testing.T) { 243 M := int64(10000) 244 // smaller bitmap would always operate with [0, M) range. 245 // max for each bitmap = M * F 246 F := []int64{1, 10, 100, 1000} 247 N := 10000 248 249 for _, f := range F { 250 t.Logf("Using N: %d M: %d F: %d\n", N, M, f) 251 small, big := NewBitmap(), NewBitmap() 252 occ := make(map[uint64]int) 253 smallMap := make(map[uint64]struct{}) 254 bigMap := make(map[uint64]struct{}) 255 256 for i := 0; i < N; i++ { 257 smallx := uint64(rand.Int63n(M)) 258 259 _, has := smallMap[smallx] 260 added := small.Set(smallx) 261 if has { 262 require.False(t, added, "Can't readd already present x: %d", smallx) 263 } 264 smallMap[smallx] = struct{}{} 265 266 bigx := uint64(rand.Int63n(M * f)) 267 _, has = bigMap[bigx] 268 added = big.Set(bigx) 269 if has { 270 require.False(t, added, "Can't readd already present x: %d", bigx) 271 } 272 bigMap[bigx] = struct{}{} 273 274 occ[smallx] |= 0x01 // binary 0001 275 occ[bigx] |= 0x02 // binary 0010 276 } 277 require.Equal(t, len(smallMap), small.GetCardinality()) 278 require.Equal(t, len(bigMap), big.GetCardinality()) 279 280 bitOr := Or(small, big) 281 bitAnd := And(small, big) 282 283 t.Logf("Sizes. small: %d big: %d, bitOr: %d bitAnd: %d\n", 284 small.GetCardinality(), big.GetCardinality(), 285 bitOr.GetCardinality(), bitAnd.GetCardinality()) 286 287 cntOr, cntAnd := 0, 0 288 for x, freq := range occ { 289 if freq == 0x00 { 290 require.Failf(t, "Failed", "Value of freq can't be zero. Found: %#x\n", freq) 291 } else if freq == 0x01 { 292 _, has := smallMap[x] 293 require.True(t, has) 294 require.True(t, small.Contains(x)) 295 require.Truef(t, bitOr.Contains(x), "Expected %d %#x. But, not found. freq: %#x\n", 296 x, x, freq) 297 cntOr++ 298 299 } else if freq == 0x02 { 300 // one of them has it. 301 _, has := bigMap[x] 302 require.True(t, has) 303 require.True(t, big.Contains(x)) 304 require.Truef(t, bitOr.Contains(x), "Expected %d %#x. But, not found. freq: %#x\n", 305 x, x, freq) 306 cntOr++ 307 308 } else if freq == 0x03 { 309 require.True(t, small.Contains(x)) 310 require.True(t, big.Contains(x)) 311 require.Truef(t, bitAnd.Contains(x), "x: %#x\n", x) 312 cntOr++ 313 cntAnd++ 314 } else { 315 require.Failf(t, "Failed", "Value of freq can't exceed 0x03. Found: %#x\n", freq) 316 } 317 } 318 if cntAnd != bitAnd.GetCardinality() { 319 uids := bitAnd.ToArray() 320 t.Logf("Len Uids: %d Card: %d cntAnd: %d. Occ: %d\n", len(uids), bitAnd.GetCardinality(), cntAnd, len(occ)) 321 322 uidMap := make(map[uint64]struct{}) 323 for _, u := range uids { 324 uidMap[u] = struct{}{} 325 } 326 for u := range occ { 327 delete(uidMap, u) 328 } 329 for x := range uidMap { 330 t.Logf("Remaining uids in UidMap: %d %#b\n", x, x) 331 } 332 require.FailNow(t, "Cardinality isn't matching") 333 } 334 require.Equal(t, cntOr, bitOr.GetCardinality()) 335 require.Equal(t, cntAnd, bitAnd.GetCardinality()) 336 } 337 } 338 339 func TestUint16(t *testing.T) { 340 a := uint16(0xfeff) 341 b := uint16(0x100) 342 t.Logf("a & b: %#x", a&b) 343 var x uint16 344 for i := 0; i < 100000; i++ { 345 prev := x 346 x++ 347 if x <= prev { 348 // This triggers when prev = 0xFFFF. 349 // require.Failf(t, "x<=prev", "x %d <= prev %d", x, prev) 350 } 351 } 352 } 353 354 func TestSetGet(t *testing.T) { 355 bm := NewBitmap() 356 N := int(1e6) 357 for i := 0; i < N; i++ { 358 bm.Set(uint64(i)) 359 } 360 for i := 0; i < N; i++ { 361 has := bm.Contains(uint64(i)) 362 require.True(t, has) 363 } 364 } 365 366 func TestSetSorted(t *testing.T) { 367 check := func(n int) { 368 var arr []uint64 369 for i := 0; i < n; i++ { 370 arr = append(arr, uint64(i)) 371 } 372 r := FromSortedList(arr) 373 require.Equal(t, len(arr), r.GetCardinality()) 374 375 rarr := r.ToArray() 376 for i := 0; i < n; i++ { 377 require.Equal(t, uint64(i), rarr[i]) 378 } 379 380 r.Set(uint64(n)) 381 require.True(t, r.Contains(uint64(n))) 382 } 383 check(10) 384 check(1e6) 385 } 386 387 func TestAnd(t *testing.T) { 388 a := NewBitmap() 389 b := NewBitmap() 390 391 N := int(1e7) 392 for i := 0; i < N; i++ { 393 if i%2 == 0 { 394 a.Set(uint64(i)) 395 } else { 396 b.Set(uint64(i)) 397 } 398 } 399 require.Equal(t, N/2, a.GetCardinality()) 400 require.Equal(t, N/2, b.GetCardinality()) 401 res := And(a, b) 402 require.Equal(t, 0, res.GetCardinality()) 403 a.And(b) 404 require.Equal(t, 0, a.GetCardinality()) 405 } 406 407 func TestAnd2(t *testing.T) { 408 a := NewBitmap() 409 n := int(1e7) 410 411 for i := 0; i < n; i++ { 412 a.Set(uint64(i)) 413 } 414 require.Equal(t, n, a.GetCardinality()) 415 a.RemoveRange(0, uint64(n/2)) 416 417 for i := 0; i < n; i++ { 418 a.Set(uint64(i)) 419 } 420 require.Equal(t, n, a.GetCardinality()) 421 } 422 423 func TestAndNot(t *testing.T) { 424 a := NewBitmap() 425 b := NewBitmap() 426 427 N := int(1e7) 428 for i := 0; i < N; i++ { 429 a.Set(uint64(i)) 430 if i < N/2 { 431 b.Set(uint64(i)) 432 } 433 } 434 require.Equal(t, N, a.GetCardinality()) 435 require.Equal(t, N/2, b.GetCardinality()) 436 437 a.AndNot(b) 438 require.Equal(t, N/2, a.GetCardinality()) 439 440 // Test for case when array container will be generated. 441 a = NewBitmap() 442 b = NewBitmap() 443 444 a.SetMany([]uint64{1, 2, 3, 4}) 445 b.SetMany([]uint64{3, 4, 5, 6}) 446 447 a.AndNot(b) 448 require.Equal(t, []uint64{1, 2}, a.ToArray()) 449 450 // Test for case when bitmap container will be generated. 451 a = NewBitmap() 452 b = NewBitmap() 453 for i := 0; i < 10000; i++ { 454 a.Set(uint64(i)) 455 if i < 7000 { 456 b.Set(uint64(i)) 457 } 458 } 459 a.AndNot(b) 460 require.Equal(t, 3000, a.GetCardinality()) 461 for i := 0; i < 10000; i++ { 462 if i < 7000 { 463 require.False(t, a.Contains(uint64(i))) 464 } else { 465 require.True(t, a.Contains(uint64(i))) 466 } 467 } 468 } 469 470 func TestAndNot2(t *testing.T) { 471 a := NewBitmap() 472 b := NewBitmap() 473 n := int(1e6) 474 475 for i := 0; i < n/2; i++ { 476 a.Set(uint64(i)) 477 } 478 for i := n / 2; i < n; i++ { 479 b.Set(uint64(i)) 480 } 481 require.Equal(t, n/2, a.GetCardinality()) 482 a.AndNot(b) 483 require.Equal(t, n/2, a.GetCardinality()) 484 485 } 486 487 func TestOr(t *testing.T) { 488 a := NewBitmap() 489 b := NewBitmap() 490 491 N := int(1e7) 492 for i := 0; i < N; i++ { 493 if i%2 == 0 { 494 a.Set(uint64(i)) 495 } else { 496 b.Set(uint64(i)) 497 } 498 } 499 require.Equal(t, N/2, a.GetCardinality()) 500 require.Equal(t, N/2, b.GetCardinality()) 501 res := Or(a, b) 502 require.Equal(t, N, res.GetCardinality()) 503 a.or(b, 0) 504 require.Equal(t, N, a.GetCardinality()) 505 } 506 507 func TestCardinality(t *testing.T) { 508 a := NewBitmap() 509 n := 1 << 20 510 for i := 0; i < n; i++ { 511 a.Set(uint64(i)) 512 } 513 require.Equal(t, n, a.GetCardinality()) 514 } 515 516 func TestRemove(t *testing.T) { 517 a := NewBitmap() 518 N := int(1e7) 519 for i := 0; i < N; i++ { 520 a.Set(uint64(i)) 521 } 522 require.Equal(t, N, a.GetCardinality()) 523 for i := 0; i < N/2; i++ { 524 require.True(t, a.Remove(uint64(i))) 525 } 526 require.Equal(t, N/2, a.GetCardinality()) 527 528 // Remove elelemts which doesn't exist should be no-op 529 for i := 0; i < N/2; i++ { 530 require.False(t, a.Remove(uint64(i))) 531 } 532 require.Equal(t, N/2, a.GetCardinality()) 533 534 for i := 0; i < N/2; i++ { 535 require.True(t, a.Remove(uint64(i+N/2))) 536 } 537 require.Equal(t, 0, a.GetCardinality()) 538 } 539 540 func TestContainerRemoveRange(t *testing.T) { 541 ra := NewBitmap() 542 543 type cases struct { 544 lo uint16 545 hi uint16 546 expected []uint16 547 } 548 549 testBitmap := func(tc cases) { 550 offset := ra.newContainer(maxContainerSize) 551 c := ra.getContainer(offset) 552 c[indexType] = typeBitmap 553 a := bitmap(c) 554 555 for i := 1; i <= 5; i++ { 556 a.add(uint16(5 * i)) 557 } 558 a.removeRange(tc.lo, tc.hi) 559 result := a.all() 560 require.Equalf(t, len(tc.expected), getCardinality(a), "case: %+v, actual:%v\n", tc, result) 561 require.Equalf(t, tc.expected, result, "case: %+v actual: %v\n", tc, result) 562 } 563 564 testArray := func(tc cases) { 565 offset := ra.newContainer(maxContainerSize) 566 c := ra.getContainer(offset) 567 c[indexType] = typeArray 568 a := array(c) 569 570 for i := 1; i <= 5; i++ { 571 a.add(uint16(5 * i)) 572 } 573 a.removeRange(tc.lo, tc.hi) 574 result := a.all() 575 require.Equalf(t, len(tc.expected), getCardinality(a), "case: %+v, actual:%v\n", tc, result) 576 require.Equalf(t, tc.expected, result, "case: %+v actual: %v\n", tc, result) 577 } 578 579 tests := []cases{ 580 {8, 22, []uint16{5, 25}}, 581 {8, 20, []uint16{5, 25}}, 582 {10, 22, []uint16{5, 25}}, 583 {10, 20, []uint16{5, 25}}, 584 {7, 11, []uint16{5, 15, 20, 25}}, 585 {7, 10, []uint16{5, 15, 20, 25}}, 586 {10, 11, []uint16{5, 15, 20, 25}}, 587 {0, 0, []uint16{5, 10, 15, 20, 25}}, 588 {30, 30, []uint16{5, 10, 15, 20, 25}}, 589 } 590 591 for _, tc := range tests { 592 testBitmap(tc) 593 testArray(tc) 594 } 595 } 596 597 func TestRemoveRange(t *testing.T) { 598 a := NewBitmap() 599 N := int(1e7) 600 for i := 0; i < N; i++ { 601 a.Set(uint64(i)) 602 } 603 a.RemoveRange(0, 0) 604 require.Equal(t, N, a.GetCardinality()) 605 606 require.Equal(t, N, a.GetCardinality()) 607 a.RemoveRange(uint64(N/4), uint64(N/2)) 608 require.Equal(t, 3*N/4, a.GetCardinality()) 609 610 a.RemoveRange(0, uint64(N/2)) 611 require.Equal(t, N/2, a.GetCardinality()) 612 613 a.RemoveRange(uint64(N/2), uint64(N)) 614 require.Equal(t, 0, a.GetCardinality()) 615 a.Set(uint64(N / 4)) 616 a.Set(uint64(N / 2)) 617 a.Set(uint64(3 * N / 4)) 618 require.Equal(t, 3, a.GetCardinality()) 619 620 var arr []uint64 621 for i := 0; i < 123; i++ { 622 arr = append(arr, uint64(i)) 623 } 624 b := FromSortedList(arr) 625 b.RemoveRange(50, math.MaxUint64) 626 require.Equal(t, 50, b.GetCardinality()) 627 } 628 629 func TestRemoveRange2(t *testing.T) { 630 // High from the last container should not be removed. 631 a := NewBitmap() 632 for i := 1; i < 10; i++ { 633 a.Set(uint64(i * (1 << 16))) 634 a.Set(uint64(i*(1<<16)) - 1) 635 } 636 a.RemoveRange(1<<16, (4<<16)-1) 637 require.True(t, a.Contains((4<<16)-1)) 638 } 639 640 func TestSelect(t *testing.T) { 641 a := NewBitmap() 642 N := int(1e4) 643 for i := 0; i < N; i++ { 644 a.Set(uint64(i)) 645 } 646 for i := 0; i < N; i++ { 647 val, err := a.Select(uint64(i)) 648 require.NoError(t, err) 649 require.Equal(t, uint64(i), val) 650 } 651 } 652 653 func TestClone(t *testing.T) { 654 a := NewBitmap() 655 N := int(1e5) 656 657 for i := 0; i < N; i++ { 658 a.Set(uint64(rand.Int63n(math.MaxInt64))) 659 } 660 b := a.Clone() 661 require.Equal(t, a.GetCardinality(), b.GetCardinality()) 662 require.Equal(t, a.ToArray(), b.ToArray()) 663 } 664 665 func TestContainerFull(t *testing.T) { 666 c := make([]uint16, maxContainerSize) 667 b := bitmap(c) 668 b[indexType] = typeBitmap 669 b[indexSize] = maxContainerSize 670 for i := 0; i < 1<<16; i++ { 671 b.add(uint16(i)) 672 } 673 require.Equal(t, math.MaxUint16+1, getCardinality(b)) 674 675 c2 := make([]uint16, maxContainerSize) 676 copy(c2, c) 677 b2 := bitmap(c2) 678 679 b.orBitmap(b2, nil, runInline) 680 require.Equal(t, math.MaxUint16+1, getCardinality(b)) 681 682 setCardinality(b, invalidCardinality) 683 b.orBitmap(b2, nil, runInline) 684 require.Equal(t, invalidCardinality, getCardinality(b)) 685 686 setCardinality(b, b.cardinality()) 687 require.Equal(t, maxCardinality, getCardinality(b)) 688 } 689 690 func TestExtremes(t *testing.T) { 691 a := NewBitmap() 692 require.Equal(t, uint64(0), a.Minimum()) 693 require.Equal(t, uint64(0), a.Maximum()) 694 695 a.Set(1) 696 require.Equal(t, uint64(1), a.Minimum()) 697 require.Equal(t, uint64(1), a.Maximum()) 698 699 a.Set(100000) 700 require.Equal(t, uint64(1), a.Minimum()) 701 require.Equal(t, uint64(100000), a.Maximum()) 702 703 a.Remove(100000) 704 require.Equal(t, uint64(1), a.Minimum()) 705 require.Equal(t, uint64(1), a.Maximum()) 706 707 a.Remove(1) 708 require.Equal(t, uint64(0), a.Minimum()) 709 require.Equal(t, uint64(0), a.Maximum()) 710 711 a.Set(100000) 712 require.Equal(t, uint64(100000), a.Minimum()) 713 require.Equal(t, uint64(100000), a.Maximum()) 714 } 715 716 func TestCleanup(t *testing.T) { 717 a := NewBitmap() 718 n := 10 719 720 for i := 0; i < n; i++ { 721 a.Set(uint64((i * (1 << 16)))) 722 } 723 abuf := a.ToBufferWithCopy() 724 725 require.Equal(t, 10, a.keys.numKeys()) 726 a.RemoveRange(1<<16, 2*(1<<16)) 727 require.Equal(t, 9, a.keys.numKeys()) 728 729 a.RemoveRange(6*(1<<16), 8*(1<<16)) 730 require.Equal(t, 7, a.keys.numKeys()) 731 732 a = FromBufferWithCopy(abuf) 733 require.Equal(t, 10, a.keys.numKeys()) 734 a.Remove(6 * (1 << 16)) 735 a.RemoveRange(7*(1<<16), 9*(1<<16)) 736 require.Equal(t, 7, a.keys.numKeys()) 737 738 n = int(1e6) 739 b := NewBitmap() 740 for i := 0; i < n; i++ { 741 b.Set(uint64(i)) 742 } 743 b.RemoveRange(0, uint64(n/2)) 744 require.Equal(t, n/2, b.GetCardinality()) 745 buf := b.ToBuffer() 746 b = FromBuffer(buf) 747 require.Equal(t, n/2, b.GetCardinality()) 748 } 749 750 func TestCleanup2(t *testing.T) { 751 a := NewBitmap() 752 n := 10 753 for i := 0; i < n; i++ { 754 a.Set(uint64(i * (1 << 16))) 755 } 756 require.Equal(t, n, a.GetCardinality()) 757 require.Equal(t, n, a.keys.numKeys()) 758 759 for i := 0; i < n; i++ { 760 if i%2 == 1 { 761 a.Remove(uint64(i * (1 << 16))) 762 } 763 } 764 require.Equal(t, n/2, a.GetCardinality()) 765 require.Equal(t, n, a.keys.numKeys()) 766 767 a.Cleanup() 768 require.Equal(t, n/2, a.GetCardinality()) 769 require.Equal(t, n/2, a.keys.numKeys()) 770 } 771 772 func TestCleanupSplit(t *testing.T) { 773 a := NewBitmap() 774 n := int(1e8) 775 776 for i := 0; i < n; i++ { 777 a.Set(uint64(i)) 778 } 779 780 split := func() { 781 n := a.GetCardinality() 782 mid, err := a.Select(uint64(n / 2)) 783 require.NoError(t, err) 784 785 b := a.Clone() 786 a.RemoveRange(0, mid) 787 b.RemoveRange(mid, math.MaxUint64) 788 789 require.Equal(t, n, a.GetCardinality()+b.GetCardinality()) 790 } 791 for a.GetCardinality() > 1 { 792 split() 793 } 794 } 795 796 func TestIsEmpty(t *testing.T) { 797 a := NewBitmap() 798 require.True(t, a.IsEmpty()) 799 800 n := int(1e6) 801 for i := 0; i < n; i++ { 802 a.Set(uint64(i)) 803 } 804 require.False(t, a.IsEmpty()) 805 a.RemoveRange(0, math.MaxUint64) 806 require.True(t, a.IsEmpty()) 807 } 808 809 func TestRank(t *testing.T) { 810 a := NewBitmap() 811 n := int(1e6) 812 for i := uint64(0); i < uint64(n); i++ { 813 a.Set(i) 814 } 815 for i := 0; i < n; i++ { 816 require.Equal(t, i, a.Rank(uint64(i))) 817 } 818 require.Equal(t, -1, a.Rank(uint64(n))) 819 820 // Check ranks after removing an element. 821 a.Remove(100) 822 for i := 0; i < n; i++ { 823 if i < 100 { 824 require.Equal(t, i, a.Rank(uint64(i))) 825 } else if i == 100 { 826 require.Equal(t, -1, a.Rank(uint64(i))) 827 } else { 828 require.Equal(t, i-1, a.Rank(uint64(i))) 829 } 830 } 831 832 // Check ranks after removing a range of elements. 833 a.RemoveRange(0, uint64(1e4)) 834 for i := 0; i < n; i++ { 835 if i < 1e4 { 836 require.Equal(t, -1, a.Rank(uint64(n))) 837 } else { 838 require.Equal(t, i-1e4, a.Rank(uint64(i))) 839 } 840 } 841 } 842 843 func TestSplit(t *testing.T) { 844 run := func(n int) { 845 r := NewBitmap() 846 for i := 1; i <= n; i++ { 847 r.Set(uint64(i)) 848 } 849 f := func(start, end uint64) uint64 { return 0 } 850 851 // Split the bitmaps. 852 bms := r.Split(f, 1<<10) 853 var csum int 854 for _, bm := range bms { 855 csum += bm.GetCardinality() 856 } 857 require.Equal(t, n, csum) 858 859 id := uint64(1) 860 for _, bm := range bms { 861 itr := bm.NewIterator() 862 for cur := itr.Next(); cur != 0; cur = itr.Next() { 863 require.Equal(t, id, cur) 864 id++ 865 } 866 } 867 } 868 869 run(2) 870 run(11) 871 run(1e3) 872 run(1e6) 873 }