From 2d4e848981b72dab472b0ab5c5f42faeaef7fe05 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 17 Aug 2018 15:19:24 -0400 Subject: [PATCH] Answer to https://github.com/willf/bitset/issues/65 --- bitset.go | 4 ++-- bitset_benchmark_test.go | 48 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/bitset.go b/bitset.go index d107e15..c187395 100644 --- a/bitset.go +++ b/bitset.go @@ -258,13 +258,13 @@ func (b *BitSet) NextSet(i uint) (uint, bool) { // 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)) + skip := i & (wordSize - 1) + w = (w >> skip) << skip base := uint(x << 6) capacity := cap(buffer) for len(myanswer) < capacity { diff --git a/bitset_benchmark_test.go b/bitset_benchmark_test.go index c09da86..39ee722 100644 --- a/bitset_benchmark_test.go +++ b/bitset_benchmark_test.go @@ -180,3 +180,51 @@ func BenchmarkLemireIterateManyb(b *testing.B) { return } } + +func setRnd(bits []uint64, halfings int) { + var rnd = rand.NewSource(0).(rand.Source64) + for i := range bits { + bits[i] = 0xFFFFFFFFFFFFFFFF + for j := 0; j < halfings; j++ { + bits[i] &= rnd.Uint64() + } + } +} + +// go test -bench=BenchmarkFlorianUekermannIterateMany +func BenchmarkFlorianUekermannIterateMany(b *testing.B) { + var input = make([]uint64, 68) + setRnd(input, 4) + var bitmap = From(input) + b.ResetTimer() + var checksum = uint(0) + for i := 0; i < b.N; i++ { + buffer := make([]uint, 256) + var last, batch = bitmap.NextSetMany(0, buffer) + for len(batch) > 0 { + for _, idx := range batch { + checksum += idx + } + last, batch = bitmap.NextSetMany(last+1, batch) + } + } + if checksum == 0 { // added just to fool ineffassign + return + } +} + +func BenchmarkFlorianUekermannIterateManyReg(b *testing.B) { + var input = make([]uint64, 68) + setRnd(input, 4) + var bitmap = From(input) + b.ResetTimer() + var checksum = uint(0) + for i := 0; i < b.N; i++ { + for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) { + checksum += j + } + } + if checksum == 0 { // added just to fool ineffassign + return + } +}