Skip to content

Commit

Permalink
Add PreviousClear and PreviousSet functions
Browse files Browse the repository at this point in the history
These are analogous to NextClear and NextSet but scan backwards.

The current implementations are naive.
  • Loading branch information
lukesandberg committed Nov 14, 2024
1 parent 417751b commit c77dfc3
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
40 changes: 40 additions & 0 deletions bitset.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,46 @@ func (b *BitSet) NextClear(i uint) (uint, bool) {
return 0, false
}

// PreviousSet returns the previous set bit from the specified index,
// including possibly the current index
// along with an error code (true = valid, false = no bit found i.e. all bits are clear)
func (b *BitSet) PreviousSet(i uint) (uint, bool) {
x := int(i >> log2WordSize)
if x >= len(b.set) {
return 0, false
}
for {
if b.Test(i) {
return i, true
}
if i == 0 {
break
}
i--
}
return 0, false
}

// PreviousClear returns the previous clear bit from the specified index,
// including possibly the current index
// along with an error code (true = valid, false = no clear bit found i.e. all bits are set)
func (b *BitSet) PreviousClear(i uint) (uint, bool) {
x := int(i >> log2WordSize)
if x >= len(b.set) {
return 0, false
}
for {
if !b.Test(i) {
return i, true
}
if i == 0 {
break
}
i--
}
return 0, false
}

// ClearAll clears the entire BitSet.
// It does not free the memory.
func (b *BitSet) ClearAll() *BitSet {
Expand Down
54 changes: 54 additions & 0 deletions bitset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2087,3 +2087,57 @@ func TestWord(t *testing.T) {
})
}
}

func TestPreviousSet(t *testing.T) {
v := New(10)
v.Set(0)
v.Set(2)
v.Set(4)
for _, tt := range []struct {
index uint
want uint
wantFound bool
}{
{0, 0, true},
{1, 0, true},
{2, 2, true},
{3, 2, true},
{4, 4, true},
{5, 4, true},
{1024, 0, false},
} {
t.Run(fmt.Sprintf("@%d", tt.index), func(t *testing.T) {
got, found := v.PreviousSet(tt.index)
if got != tt.want || found != tt.wantFound {
t.Errorf("PreviousSet(%d) = %d, %v, want %d, %v", tt.index, got, found, tt.want, tt.wantFound)
}
})
}
}

func TestPreviousClear(t *testing.T) {
v := New(10)
v.Set(0)
v.Set(2)
v.Set(4)
for _, tt := range []struct {
index uint
want uint
wantFound bool
}{
{0, 0, false},
{1, 1, true},
{2, 1, true},
{3, 3, true},
{4, 3, true},
{5, 5, true},
{1024, 0, false},
} {
t.Run(fmt.Sprintf("@%d", tt.index), func(t *testing.T) {
got, found := v.PreviousClear(tt.index)
if got != tt.want || found != tt.wantFound {
t.Errorf("PreviousClear(%d) = %d, %v, want %d, %v", tt.index, got, found, tt.want, tt.wantFound)
}
})
}
}

0 comments on commit c77dfc3

Please sign in to comment.