Skip to content

Commit

Permalink
Merge pull request #62 from lemire/master
Browse files Browse the repository at this point in the history
Adding bulk iteration.
  • Loading branch information
lemire authored Apr 26, 2018
2 parents 1a37ad9 + 7f1803e commit 8ce1146
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ docs:
@echo '<html><head><meta http-equiv="refresh" content="0;./127.0.0.1:6060/pkg/'${CVSPATH}'/'${PROJECT}'/index.html"/></head><a href="./127.0.0.1:6060/pkg/'${CVSPATH}'/'${PROJECT}'/index.html">'${PKGNAME}' Documentation ...</a></html>' > target/docs/index.html

# Alias to run all quality-assurance checks
qa: fmtcheck test vet lint coverage cyclo ineffassign misspell structcheck varcheck errcheck gosimple astscan
qa: fmtcheck test vet lint coverage cyclo ineffassign misspell structcheck varcheck errcheck gosimple

# --- INSTALL ---

Expand Down
50 changes: 50 additions & 0 deletions bitset.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,56 @@ func (b *BitSet) NextSet(i uint) (uint, bool) {
return 0, false
}

// NextSetMany returns many next bit sets from the specified index,
// including possibly the current index and up to cap(buffer).
// If the returned slice has len zero, then no more set bits were found
//
// buffer := make([]uint, 256)
// j := uint(0)
// j, buffer = bitmap.NextSetMany(j, buffer)
// for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j,buffer) {
// for k := range buffer {
// do something with buffer[k]
// }
// j += 1
// }
//
func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) {
myanswer := buffer[:0]

x := int(i >> log2WordSize)
if x >= len(b.set) {
return 0, myanswer
}
w := b.set[x]
w = w >> (i & (wordSize - 1))
base := uint(x << 6)
capacity := cap(buffer)
for len(myanswer) < capacity {
for w != 0 {
t := w & ((^w) + 1)
r := trailingZeroes64(w)
myanswer = append(myanswer, r+base)
if len(myanswer) == capacity {
goto End
}
w = w ^ t
}
x += 1
if x == len(b.set) {
break
}
base += 64
w = b.set[x]
}
End:
if len(myanswer) > 0 {
return myanswer[len(myanswer)-1], myanswer
} else {
return 0, myanswer
}
}

// NextClear returns the next clear 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 set)
Expand Down
48 changes: 47 additions & 1 deletion bitset_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,57 @@ func BenchmarkLemireIterate(b *testing.B) {
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
for i, e := bitmap.NextSet(0); e; i, e = bitmap.NextSet(i + 1) {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
sum++
}
}
if sum == 0 { // added just to fool ineffassign
return
}
}

// go test -bench=LemireIterateb
// see http://lemire.me/blog/2016/09/22/swift-versus-java-the-bitset-performance-test/
func BenchmarkLemireIterateb(b *testing.B) {
bitmap := New(100000000)
for v := uint(0); v <= 100000000; v += 100 {
bitmap.Set(v)
}
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
sum += j
}
}

if sum == 0 { // added just to fool ineffassign
return
}
}

// go test -bench=BenchmarkLemireIterateManyb
// see http://lemire.me/blog/2016/09/22/swift-versus-java-the-bitset-performance-test/
func BenchmarkLemireIterateManyb(b *testing.B) {
bitmap := New(100000000)
for v := uint(0); v <= 100000000; v += 100 {
bitmap.Set(v)
}
b.ResetTimer()
sum := uint(0)
buffer := make([]uint, 256)
for i := 0; i < b.N; i++ {
j := uint(0)
j, buffer = bitmap.NextSetMany(j, buffer)
for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) {
for k := range buffer {
sum += buffer[k]
}
j += 1
}
}

if sum == 0 { // added just to fool ineffassign
return
}
}

0 comments on commit 8ce1146

Please sign in to comment.