Skip to content

Commit

Permalink
adding support for iter (Go 1.23+)
Browse files Browse the repository at this point in the history
  • Loading branch information
lemire committed Feb 25, 2025
1 parent 5bdbff1 commit 18fd6ee
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.16.x, 1.17.x, 1.18.x, 1.19.x,1.20.x]
go-version: [1.16.x, 1.17.x, 1.18.x, 1.19.x,1.20.x,1.21.x,1.22.x,1.23.x,1.24.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down
23 changes: 23 additions & 0 deletions bitset_iter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build go1.23
// +build go1.23

package bitset

import (
"iter"
"math/bits"
)

func (b *BitSet) EachSet() iter.Seq[uint] {
return func(yield func(uint) bool) {
for wordIndex, word := range b.set {
idx := 0
for trail := bits.TrailingZeros64(word); trail != 64; trail = bits.TrailingZeros64(word >> idx) {
if !yield(uint(wordIndex<<log2WordSize + idx + trail)) {
return
}
idx += trail + 1
}
}
}
}
74 changes: 74 additions & 0 deletions bitset_iter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//go:build go1.23
// +build go1.23

package bitset

import (
"testing"
)

func TestIter(t *testing.T) {
var b BitSet
b.Set(0).Set(3).Set(5).Set(6).Set(63).Set(64).Set(65).Set(127).Set(128).Set(1000000)

// Expected values that should be set
expected := []uint{0, 3, 5, 6, 63, 64, 65, 127, 128, 1000000}
got := make([]uint, 0)

// Collect all values from iterator
for i := range b.EachSet() {
got = append(got, i)
}

// Test 1: Check length matches expected
if len(got) != len(expected) {
t.Errorf("Expected %d elements, got %d", len(expected), len(got))
}

// Test 2: Check all expected values are present and in correct order
for i, want := range expected {
if i >= len(got) {
t.Errorf("Missing expected value %d at position %d", want, i)
continue
}
if got[i] != want {
t.Errorf("At position %d: expected %d, got %d", i, want, got[i])
}
}

// Test 3: Check no extra values
if len(got) > len(expected) {
t.Errorf("Got extra values: %v", got[len(expected):])
}
}
func BenchmarkIter(b *testing.B) {
b.StopTimer()
s := New(10000)
for i := 0; i < 10000; i += 3 {
s.Set(uint(i))
}

b.StartTimer()
for j := 0; j < b.N; j++ {
c := uint(0)
for range s.EachSet() {
c++
}
}
}

func BenchmarkNonInter(b *testing.B) {
b.StopTimer()
s := New(10000)
for i := 0; i < 10000; i += 3 {
s.Set(uint(i))
}

b.StartTimer()
for j := 0; j < b.N; j++ {
c := uint(0)
for i, e := s.NextSet(0); e; i, e = s.NextSet(i + 1) {
c++
}
}
}

0 comments on commit 18fd6ee

Please sign in to comment.