From c6ff00561d0ed27d0a0e092c713812a3279272b1 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 24 Jan 2023 10:43:58 -0500 Subject: [PATCH 1/2] Fixing issue 116. --- bitset.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/bitset.go b/bitset.go index fbf0496..d0fbff9 100644 --- a/bitset.go +++ b/bitset.go @@ -115,6 +115,12 @@ func wordsNeeded(i uint) int { return int((i + (wordSize - 1)) >> log2WordSize) } +// wordsNeededUnbound calculates the number of words needed for i bits, possibly exceeding the capacity. +// This function is useful if you know that the capacity cannot be exceeded (e.g., you have an existing bitmap). +func wordsNeededUnbound(i uint) int { + return int((i + (wordSize - 1)) >> log2WordSize) +} + // wordsIndex calculates the index of words in a `uint64` func wordsIndex(i uint) uint { return i & (wordSize - 1) @@ -530,7 +536,7 @@ func (b *BitSet) ClearAll() *BitSet { // wordCount returns the number of words used in a bit set func (b *BitSet) wordCount() int { - return len(b.set) + return wordsNeededUnbound(b.length) } // Clone this BitSet @@ -606,10 +612,9 @@ func (b *BitSet) Equal(c *BitSet) bool { if b.length == 0 { // if they have both length == 0, then could have nil set return true } - // testing for equality shoud not transform the bitset (no call to safeSet) - - for p, v := range b.set { - if c.set[p] != v { + wn := b.wordCount() + for p:= 0; p < wn; p++ { + if c.set[p] != b.set[p] { return false } } @@ -898,7 +903,7 @@ func (b *BitSet) DumpAsBits() string { // BinaryStorageSize returns the binary storage requirements func (b *BitSet) BinaryStorageSize() int { - nWords := wordsNeeded(b.length) + nWords := b.wordCount() return binary.Size(uint64(0)) + binary.Size(b.set[:nWords]) } @@ -917,7 +922,7 @@ func (b *BitSet) WriteTo(stream io.Writer) (int64, error) { // binary.Write for large set writer := bufio.NewWriter(stream) var item = make([]byte, binary.Size(uint64(0))) // for serializing one uint64 - nWords := wordsNeeded(uint(length)) + nWords := b.wordCount() for i := range b.set[:nWords] { binaryOrder.PutUint64(item, b.set[i]) if nn, err := writer.Write(item); err != nil { @@ -948,7 +953,7 @@ func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) { } var item [8]byte - nWords := wordsNeeded(uint(length)) + nWords := wordsNeeded(uint(length))//b.wordCount() reader := bufio.NewReader(io.LimitReader(stream, 8*int64(nWords))) for i := 0; i < nWords; i++ { if _, err := io.ReadFull(reader, item[:]); err != nil { From 184222871a2a579150c6f7a797e2c948514461d5 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 24 Jan 2023 10:49:18 -0500 Subject: [PATCH 2/2] Verifying. --- bitset.go | 2 +- bitset_test.go | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/bitset.go b/bitset.go index d0fbff9..5751b68 100644 --- a/bitset.go +++ b/bitset.go @@ -953,7 +953,7 @@ func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) { } var item [8]byte - nWords := wordsNeeded(uint(length))//b.wordCount() + nWords := wordsNeeded(uint(length)) reader := bufio.NewReader(io.LimitReader(stream, 8*int64(nWords))) for i := 0; i < nWords; i++ { if _, err := io.ReadFull(reader, item[:]); err != nil { diff --git a/bitset_test.go b/bitset_test.go index efa202f..601c274 100644 --- a/bitset_test.go +++ b/bitset_test.go @@ -1395,6 +1395,16 @@ func TestSetBitsetFrom(t *testing.T) { } } +func TestIssue116(t *testing.T) { + a := []uint64{2, 3, 5, 7, 11} + b := []uint64{2, 3, 5, 7, 11, 0, 1} + bitset1 := FromWithLength(320, a) + bitset2 := FromWithLength(320, b) + if !bitset1.Equal(bitset2) || !bitset2.Equal(bitset1) { + t.Error("Bitsets should be equal irrespective of the underlying capacity") + } +} + func TestFrom(t *testing.T) { u := []uint64{2, 3, 5, 7, 11} b := From(u)