Skip to content

Commit 45a0bac

Browse files
authored
Merge pull request #500 from rogpeppe-contrib/unsetiterator-open-range
use open range for UnsetIterator
2 parents e2c9e47 + b429bc3 commit 45a0bac

File tree

3 files changed

+33
-28
lines changed

3 files changed

+33
-28
lines changed

iter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func Backward(b *Bitmap) func(func(uint32) bool) {
3232
// The iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
3333
func Unset(b *Bitmap, min, max uint32) func(func(uint32) bool) {
3434
return func(yield func(uint32) bool) {
35-
it := b.UnsetIterator(min, max)
35+
it := b.UnsetIterator(uint64(min), uint64(max)+1)
3636
for it.HasNext() {
3737
if !yield(it.Next()) {
3838
return

iter_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
315315
b.AddInt(5)
316316
b.AddInt(8)
317317

318-
it := b.UnsetIterator(3, 10)
318+
it := b.UnsetIterator(3, 11)
319319

320320
// First value should be 3
321321
assert.True(t, it.HasNext())
@@ -357,7 +357,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
357357
b.AddInt(8)
358358
b.AddInt(12)
359359

360-
it := b.UnsetIterator(1, 15)
360+
it := b.UnsetIterator(1, 16)
361361

362362
// Skip to values >= 7
363363
it.AdvanceIfNeeded(7)
@@ -394,7 +394,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
394394
b := New()
395395
b.AddInt(5)
396396

397-
it := b.UnsetIterator(10, 15)
397+
it := b.UnsetIterator(10, 16)
398398

399399
// Try to advance to a value before our range start
400400
it.AdvanceIfNeeded(5)
@@ -408,7 +408,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
408408
b := New()
409409
b.AddInt(5)
410410

411-
it := b.UnsetIterator(10, 15)
411+
it := b.UnsetIterator(10, 16)
412412

413413
// Advance beyond our range
414414
it.AdvanceIfNeeded(20)
@@ -420,7 +420,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
420420
t.Run("advance if needed on current value", func(t *testing.T) {
421421
b := New()
422422
b.AddRange(0, 0x10000)
423-
iter := b.UnsetIterator(0, 0x10002)
423+
iter := b.UnsetIterator(0, 0x10003)
424424
var got []uint32
425425
prev := uint32(0)
426426
for len(got) < 10 {
@@ -439,7 +439,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
439439
b := New()
440440
b.AddInt(5) // Set bit in middle of range
441441

442-
it := b.UnsetIterator(5, 5) // Range contains only the set bit
442+
it := b.UnsetIterator(5, 6) // Range contains only the set bit
443443

444444
// Should have no values
445445
assert.False(t, it.HasNext())
@@ -454,7 +454,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
454454
b := New()
455455
b.Add(4294967294) // Set the value before max
456456

457-
it := b.UnsetIterator(4294967294, 4294967295)
457+
it := b.UnsetIterator(4294967294, 4294967296)
458458

459459
// Should have 4294967295 (max uint32) as it's unset
460460
assert.True(t, it.HasNext())
@@ -469,7 +469,7 @@ func TestUnsetIteratorPeekable(t *testing.T) {
469469
b := New()
470470
b.Add(4294967295) // Set max uint32
471471

472-
it := b.UnsetIterator(4294967294, 4294967295)
472+
it := b.UnsetIterator(4294967294, 4294967296)
473473

474474
// Should have 4294967294 as it's unset, but not 4294967295
475475
assert.True(t, it.HasNext())

roaring.go

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -743,20 +743,25 @@ func (ii *manyIntIterator) Initialize(a *Bitmap) {
743743
}
744744

745745
type unsetIterator struct {
746-
min, max uint32
747-
current uint64 // use uint64 to avoid overflow
748-
it IntPeekable
749-
hasNext bool
746+
start, end uint64
747+
current uint64
748+
it IntPeekable
749+
hasNext bool
750750
}
751751

752-
// Initialize configures the unset iterator to iterate over values in [min, max] that are not in the bitmap
753-
func (ui *unsetIterator) Initialize(b *Bitmap, min, max uint32) {
754-
ui.min = min
755-
ui.max = max
756-
ui.current = uint64(min)
752+
// Initialize configures the unset iterator to iterate over values in [start, end) that are not in the bitmap
753+
func (ui *unsetIterator) Initialize(b *Bitmap, start, end uint64) {
754+
if end > 0x100000000 {
755+
panic("end > 0x100000000")
756+
}
757+
ui.start = start
758+
ui.end = end
759+
ui.current = start
757760
ui.it = b.Iterator()
758-
// Advance to first value >= min
759-
ui.it.AdvanceIfNeeded(min)
761+
// Advance to first value >= start
762+
if start <= MaxUint32 {
763+
ui.it.AdvanceIfNeeded(uint32(start))
764+
}
760765
ui.updateHasNext()
761766
}
762767

@@ -776,16 +781,16 @@ func (ui *unsetIterator) Next() uint32 {
776781
}
777782

778783
func (ui *unsetIterator) updateHasNext() {
779-
for ui.current <= uint64(ui.max) {
784+
for ui.current < ui.end {
780785
if !ui.it.HasNext() {
781786
// No more set bits, we have values to yield
782787
ui.hasNext = true
783788
return
784789
}
785790

786791
nextSet := ui.it.PeekNext()
787-
if nextSet > ui.max {
788-
// Next set bit is beyond our range, we have values to yield
792+
if uint64(nextSet) >= ui.end {
793+
// Next set bit is at or beyond our range, we have values to yield
789794
ui.hasNext = true
790795
return
791796
}
@@ -818,8 +823,8 @@ func (ui *unsetIterator) AdvanceIfNeeded(minval uint32) {
818823
return // Already at or past minval
819824
}
820825

821-
if minval > ui.max {
822-
// Beyond our range, no more values
826+
if uint64(minval) >= ui.end {
827+
// At or beyond our range, no more values
823828
ui.hasNext = false
824829
return
825830
}
@@ -915,11 +920,11 @@ func (rb *Bitmap) ManyIterator() ManyIntIterable {
915920
return p
916921
}
917922

918-
// UnsetIterator creates a new IntPeekable to iterate over values in the range [min, max] that are NOT contained in the bitmap.
923+
// UnsetIterator creates a new IntPeekable to iterate over values in the range [start, end) that are NOT contained in the bitmap.
919924
// The iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
920-
func (rb *Bitmap) UnsetIterator(min, max uint32) IntPeekable {
925+
func (rb *Bitmap) UnsetIterator(start, end uint64) IntPeekable {
921926
p := new(unsetIterator)
922-
p.Initialize(rb, min, max)
927+
p.Initialize(rb, start, end)
923928
return p
924929
}
925930

0 commit comments

Comments
 (0)