Skip to content

Commit

Permalink
Merge pull request #113 from steampoweredtaco/fix-copy-overflow-bits
Browse files Browse the repository at this point in the history
Clean last word of target bitset after using Copy.
  • Loading branch information
lemire authored Oct 27, 2022
2 parents e160993 + 9d0d90c commit e4f40f1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
3 changes: 3 additions & 0 deletions bitset.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,9 @@ func (b *BitSet) Copy(c *BitSet) (count uint) {
if b.length < c.length {
count = b.length
}
// Cleaning the last word is needed to keep the invariant that other functions, such as Count, require
// that any bits in the last word that would exceed the length of the bitmask are set to 0.
c.cleanLastWord()
return
}

Expand Down
28 changes: 28 additions & 0 deletions bitset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,34 @@ func TestCopy(t *testing.T) {
}
}

func TestCopyUnaligned(t *testing.T) {
a := New(16)
a.FlipRange(0, 16)
b := New(1)
a.Copy(b)
if b.Count() > b.Len() {
t.Errorf("targets copied set count (%d) should never be larger than target's length (%d)", b.Count(), b.Len())
}
if !b.Test(0) {
t.Errorf("first bit should still be set in copy: %+v", b)
}

// Test a more complex scenario with a mix of bits set in the unaligned space to verify no bits are lost.
a = New(32)
a.Set(0).Set(3).Set(4).Set(16).Set(17).Set(29).Set(31)
b = New(19)
a.Copy(b)

const expectedCount = 5
if b.Count() != expectedCount {
t.Errorf("targets copied set count: %d, want %d", b.Count(), expectedCount)
}

if !(b.Test(0) && b.Test(3) && b.Test(4) && b.Test(16) && b.Test(17)) {
t.Errorf("expected set bits are not set: %+v", b)
}
}

func TestCopyFull(t *testing.T) {
a := New(10)
b := &BitSet{}
Expand Down

0 comments on commit e4f40f1

Please sign in to comment.