lib/uint64set: optimize Set.AppendTo

This commit is contained in:
Aliaksandr Valialkin 2019-09-25 00:34:09 +03:00
parent b986516fbe
commit 2cb811b42f
2 changed files with 20 additions and 11 deletions

View file

@ -1,6 +1,7 @@
package uint64set package uint64set
import ( import (
"math/bits"
"sort" "sort"
) )
@ -299,11 +300,19 @@ func (b *bucket16) appendTo(dst []uint64, hi uint32, hi16 uint16) []uint64 {
hi64 := uint64(hi)<<32 | uint64(hi16)<<16 hi64 := uint64(hi)<<32 | uint64(hi16)<<16
var wordNum uint64 var wordNum uint64
for _, word := range b.bits { for _, word := range b.bits {
for bitNum := uint64(0); bitNum < 64; bitNum++ { if word == 0 {
if word&(uint64(1)<<bitNum) != 0 { wordNum++
x := hi64 | uint64(wordNum)*64 | bitNum continue
dst = append(dst, x) }
x64 := hi64 | (wordNum * 64)
for {
tzn := uint64(bits.TrailingZeros64(word))
if tzn >= 64 {
break
} }
word &^= uint64(1) << tzn
x := x64 | tzn
dst = append(dst, x)
} }
wordNum++ wordNum++
} }

View file

@ -48,14 +48,14 @@ func testSetBasicOps(t *testing.T, itemsCount int) {
// Verify Has on existing bits // Verify Has on existing bits
for i := 0; i < itemsCount; i++ { for i := 0; i < itemsCount; i++ {
if !s.Has(uint64(i) + offset) { if !s.Has(uint64(i) + offset) {
t.Fatalf("missing bit %d", i) t.Fatalf("missing bit %d", uint64(i)+offset)
} }
} }
// Verify Has on missing bits // Verify Has on missing bits
for i := itemsCount; i < 2*itemsCount; i++ { for i := itemsCount; i < 2*itemsCount; i++ {
if s.Has(uint64(i) + offset) { if s.Has(uint64(i) + offset) {
t.Fatalf("unexpected bit found: %d", i) t.Fatalf("unexpected bit found: %d", uint64(i)+offset)
} }
} }
@ -66,7 +66,7 @@ func testSetBasicOps(t *testing.T, itemsCount int) {
} }
for i := 0; i < itemsCount; i++ { for i := 0; i < itemsCount; i++ {
if !sCopy.Has(uint64(i) + offset) { if !sCopy.Has(uint64(i) + offset) {
t.Fatalf("missing bit %d on sCopy", i) t.Fatalf("missing bit %d on sCopy", uint64(i)+offset)
} }
} }
@ -84,7 +84,7 @@ func testSetBasicOps(t *testing.T, itemsCount int) {
} }
for i := 0; i < itemsCount; i++ { for i := 0; i < itemsCount; i++ {
if !m[uint64(i)+offset] { if !m[uint64(i)+offset] {
t.Fatalf("missing bit %d in the exported bits; array:\n%d", i, a) t.Fatalf("missing bit %d in the exported bits; array:\n%d", uint64(i)+offset, a)
} }
} }
@ -106,11 +106,11 @@ func testSetBasicOps(t *testing.T, itemsCount int) {
for i := 0; i < itemsCount; i++ { for i := 0; i < itemsCount; i++ {
if i >= itemsCount/2 && i < itemsCount-itemsCount/4 { if i >= itemsCount/2 && i < itemsCount-itemsCount/4 {
if m[uint64(i)+offset] { if m[uint64(i)+offset] {
t.Fatalf("unexpected bit found after deleting: %d", i) t.Fatalf("unexpected bit found after deleting: %d", uint64(i)+offset)
} }
} else { } else {
if !m[uint64(i)+offset] { if !m[uint64(i)+offset] {
t.Fatalf("missing bit %d in the exported bits after deleting", i) t.Fatalf("missing bit %d in the exported bits after deleting", uint64(i)+offset)
} }
} }
} }
@ -131,7 +131,7 @@ func testSetBasicOps(t *testing.T, itemsCount int) {
} }
for i := 0; i < itemsCount; i++ { for i := 0; i < itemsCount; i++ {
if !sCopy.Has(uint64(i) + offset) { if !sCopy.Has(uint64(i) + offset) {
t.Fatalf("missing bit %d on sCopy", i) t.Fatalf("missing bit %d on sCopy", uint64(i)+offset)
} }
} }
} }