diff --git a/bitset.go b/bitset.go index abfbd41..cf11581 100644 --- a/bitset.go +++ b/bitset.go @@ -44,6 +44,7 @@ import ( "errors" "fmt" "io" + "math/bits" "strconv" ) @@ -491,7 +492,7 @@ func (b *BitSet) NextSet(i uint) (uint, bool) { w := b.set[x] w = w >> wordsIndex(i) if w != 0 { - return i + trailingZeroes64(w), true + return i + uint(bits.TrailingZeros64(w)), true } x++ // bounds check elimination in the loop @@ -500,7 +501,7 @@ func (b *BitSet) NextSet(i uint) (uint, bool) { } for x < len(b.set) { if b.set[x] != 0 { - return uint(x)*wordSize + trailingZeroes64(b.set[x]), true + return uint(x)*wordSize + uint(bits.TrailingZeros64(b.set[x])), true } x++ @@ -541,7 +542,7 @@ func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) { myanswer = myanswer[:capacity] size := int(0) for word != 0 { - r := trailingZeroes64(word) + r := uint(bits.TrailingZeros64(word)) t := word & ((^word) + 1) myanswer[size] = r + i size++ @@ -553,7 +554,7 @@ func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) { x++ for idx, word := range b.set[x:] { for word != 0 { - r := trailingZeroes64(word) + r := uint(bits.TrailingZeros64(word)) t := word & ((^word) + 1) myanswer[size] = r + (uint(x+idx) << 6) size++ @@ -581,7 +582,7 @@ func (b *BitSet) NextClear(i uint) (uint, bool) { w := b.set[x] w = w >> wordsIndex(i) wA := allBits >> wordsIndex(i) - index := i + trailingZeroes64(^w) + index := i + uint(bits.TrailingZeros64(^w)) if w != wA && index < b.length { return index, true } @@ -592,7 +593,7 @@ func (b *BitSet) NextClear(i uint) (uint, bool) { } for x < len(b.set) { if b.set[x] != allBits { - index = uint(x)*wordSize + trailingZeroes64(^b.set[x]) + index = uint(x)*wordSize + uint(bits.TrailingZeros64(^b.set[x])) if index < b.length { return index, true } @@ -614,12 +615,12 @@ func (b *BitSet) PreviousSet(i uint) (uint, bool) { // Clear the bits above the index w = w & ((1 << (wordsIndex(i) + 1)) - 1) if w != 0 { - return uint(x<= 0; x-- { w = b.set[x] if w != 0 { - return uint(x<= 0; x-- { w = b.set[x] w = ^w if w != 0 { - return uint(x<>6])) if leftover != 0 { - answer += uint(popcount(b.set[(index+1)>>6] << (64 - leftover))) + answer += uint(bits.OnesCount64(b.set[(index+1)>>6] << (64 - leftover))) } return answer } @@ -1302,7 +1303,7 @@ func (b *BitSet) Rank(index uint) uint { func (b *BitSet) Select(index uint) uint { leftover := index for idx, word := range b.set { - w := uint(popcount(word)) + w := uint(bits.OnesCount64(word)) if w > leftover { return uint(idx)*64 + select64(word, leftover) } @@ -1324,7 +1325,7 @@ func (b *BitSet) top() (uint, bool) { return 0, false } - return uint(idx)*wordSize + len64(b.set[idx]) - 1, true + return uint(idx)*wordSize + uint(bits.Len64(b.set[idx])) - 1, true } // ShiftLeft shifts the bitset like << operation would do. diff --git a/bitset_benchmark_test.go b/bitset_benchmark_test.go index 53267e1..13e669e 100644 --- a/bitset_benchmark_test.go +++ b/bitset_benchmark_test.go @@ -9,6 +9,7 @@ package bitset import ( "bytes" "fmt" + "math/bits" "math/rand" "testing" ) @@ -334,7 +335,7 @@ func good(set []uint64) (checksum uint) { for wordIdx, word := range set { var wordIdx = uint(wordIdx * 64) for word != 0 { - var bitIdx = uint(trailingZeroes64(word)) + var bitIdx = uint(bits.TrailingZeros64(word)) word ^= 1 << bitIdx var index = wordIdx + bitIdx checksum += index diff --git a/leading_zeros_18.go b/leading_zeros_18.go deleted file mode 100644 index 72af1d6..0000000 --- a/leading_zeros_18.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build !go1.9 -// +build !go1.9 - -package bitset - -var len8tab = "" + - "\x00\x01\x02\x02\x03\x03\x03\x03\x04\x04\x04\x04\x04\x04\x04\x04" + - "\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + - "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" + - "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" - -// len64 returns the minimum number of bits required to represent x; the result is 0 for x == 0. -func len64(x uint64) (n uint) { - if x >= 1<<32 { - x >>= 32 - n = 32 - } - if x >= 1<<16 { - x >>= 16 - n += 16 - } - if x >= 1<<8 { - x >>= 8 - n += 8 - } - return n + uint(len8tab[x]) -} - -func leadingZeroes64(v uint64) uint { - return 64 - len64(v) -} diff --git a/leading_zeros_19.go b/leading_zeros_19.go deleted file mode 100644 index 74a7942..0000000 --- a/leading_zeros_19.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build go1.9 -// +build go1.9 - -package bitset - -import "math/bits" - -func len64(v uint64) uint { - return uint(bits.Len64(v)) -} - -func leadingZeroes64(v uint64) uint { - return uint(bits.LeadingZeros64(v)) -} diff --git a/leading_zeros_test.go b/leading_zeros_test.go deleted file mode 100644 index 7c2b1ec..0000000 --- a/leading_zeros_test.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build !go1.9 -// +build !go1.9 - -package bitset - -import ( - "testing" -) - -func TestLen64(t *testing.T) { - for i := 0; i < 64; i++ { - received := len64(uint64(1) << i) - expected := uint(i + 1) - if received != expected { - t.Errorf("len64(%b) is incorrect: received %d, expected %d", uint64(1)<> 1) & 0x5555555555555555 - x = (x>>2)&0x3333333333333333 + x&0x3333333333333333 - x += x >> 4 - x &= 0x0f0f0f0f0f0f0f0f - x *= 0x0101010101010101 - return x >> 56 -} +import "math/bits" -func popcntSliceGo(s []uint64) uint64 { - cnt := uint64(0) +func popcntSlice(s []uint64) uint64 { + var cnt int for _, x := range s { - cnt += popcount(x) + cnt += bits.OnesCount64(x) } - return cnt + return uint64(cnt) } -func popcntMaskSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntMaskSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] &^ m[i]) + cnt += bits.OnesCount64(s[i] &^ m[i]) } - return cnt + return uint64(cnt) } -func popcntAndSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntAndSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] & m[i]) + cnt += bits.OnesCount64(s[i] & m[i]) } - return cnt + return uint64(cnt) } -func popcntOrSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntOrSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] | m[i]) + cnt += bits.OnesCount64(s[i] | m[i]) } - return cnt + return uint64(cnt) } -func popcntXorSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntXorSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] ^ m[i]) + cnt += bits.OnesCount64(s[i] ^ m[i]) } - return cnt + return uint64(cnt) } diff --git a/popcnt_19.go b/popcnt_19.go deleted file mode 100644 index 7855c04..0000000 --- a/popcnt_19.go +++ /dev/null @@ -1,62 +0,0 @@ -//go:build go1.9 -// +build go1.9 - -package bitset - -import "math/bits" - -func popcntSlice(s []uint64) uint64 { - var cnt int - for _, x := range s { - cnt += bits.OnesCount64(x) - } - return uint64(cnt) -} - -func popcntMaskSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] &^ m[i]) - } - return uint64(cnt) -} - -func popcntAndSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] & m[i]) - } - return uint64(cnt) -} - -func popcntOrSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] | m[i]) - } - return uint64(cnt) -} - -func popcntXorSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] ^ m[i]) - } - return uint64(cnt) -} diff --git a/popcnt_amd64.go b/popcnt_amd64.go deleted file mode 100644 index 116e044..0000000 --- a/popcnt_amd64.go +++ /dev/null @@ -1,68 +0,0 @@ -//go:build !go1.9 && amd64 && !appengine -// +build !go1.9,amd64,!appengine - -package bitset - -// *** the following functions are defined in popcnt_amd64.s - -//go:noescape - -func hasAsm() bool - -// useAsm is a flag used to select the GO or ASM implementation of the popcnt function -var useAsm = hasAsm() - -//go:noescape - -func popcntSliceAsm(s []uint64) uint64 - -//go:noescape - -func popcntMaskSliceAsm(s, m []uint64) uint64 - -//go:noescape - -func popcntAndSliceAsm(s, m []uint64) uint64 - -//go:noescape - -func popcntOrSliceAsm(s, m []uint64) uint64 - -//go:noescape - -func popcntXorSliceAsm(s, m []uint64) uint64 - -func popcntSlice(s []uint64) uint64 { - if useAsm { - return popcntSliceAsm(s) - } - return popcntSliceGo(s) -} - -func popcntMaskSlice(s, m []uint64) uint64 { - if useAsm { - return popcntMaskSliceAsm(s, m) - } - return popcntMaskSliceGo(s, m) -} - -func popcntAndSlice(s, m []uint64) uint64 { - if useAsm { - return popcntAndSliceAsm(s, m) - } - return popcntAndSliceGo(s, m) -} - -func popcntOrSlice(s, m []uint64) uint64 { - if useAsm { - return popcntOrSliceAsm(s, m) - } - return popcntOrSliceGo(s, m) -} - -func popcntXorSlice(s, m []uint64) uint64 { - if useAsm { - return popcntXorSliceAsm(s, m) - } - return popcntXorSliceGo(s, m) -} diff --git a/popcnt_amd64.s b/popcnt_amd64.s deleted file mode 100644 index 666c0dc..0000000 --- a/popcnt_amd64.s +++ /dev/null @@ -1,104 +0,0 @@ -// +build !go1.9 -// +build amd64,!appengine - -TEXT ·hasAsm(SB),4,$0-1 -MOVQ $1, AX -CPUID -SHRQ $23, CX -ANDQ $1, CX -MOVB CX, ret+0(FP) -RET - -#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2 - -TEXT ·popcntSliceAsm(SB),4,$0-32 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntSliceEnd -popcntSliceLoop: -BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX -ADDQ DX, AX -ADDQ $8, SI -LOOP popcntSliceLoop -popcntSliceEnd: -MOVQ AX, ret+24(FP) -RET - -TEXT ·popcntMaskSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntMaskSliceEnd -MOVQ m+24(FP), DI -popcntMaskSliceLoop: -MOVQ (DI), DX -NOTQ DX -ANDQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntMaskSliceLoop -popcntMaskSliceEnd: -MOVQ AX, ret+48(FP) -RET - -TEXT ·popcntAndSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntAndSliceEnd -MOVQ m+24(FP), DI -popcntAndSliceLoop: -MOVQ (DI), DX -ANDQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntAndSliceLoop -popcntAndSliceEnd: -MOVQ AX, ret+48(FP) -RET - -TEXT ·popcntOrSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntOrSliceEnd -MOVQ m+24(FP), DI -popcntOrSliceLoop: -MOVQ (DI), DX -ORQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntOrSliceLoop -popcntOrSliceEnd: -MOVQ AX, ret+48(FP) -RET - -TEXT ·popcntXorSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntXorSliceEnd -MOVQ m+24(FP), DI -popcntXorSliceLoop: -MOVQ (DI), DX -XORQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntXorSliceLoop -popcntXorSliceEnd: -MOVQ AX, ret+48(FP) -RET diff --git a/popcnt_amd64_test.go b/popcnt_amd64_test.go deleted file mode 100644 index 1bb05a7..0000000 --- a/popcnt_amd64_test.go +++ /dev/null @@ -1,79 +0,0 @@ -//go:build !go1.9 && amd64 && !appengine -// +build !go1.9,amd64,!appengine - -// This file tests the popcnt functions - -package bitset - -import ( - "testing" -) - -func TestPopcntSliceCond(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - oldUseAsm := useAsm - defer func() { useAsm = oldUseAsm }() - useAsm = false - resGo := popcntSlice(s) - useAsm = (true && oldUseAsm) - resAsm := popcntSlice(s) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestPopcntMaskSliceCond(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - oldUseAsm := useAsm - defer func() { useAsm = oldUseAsm }() - useAsm = false - resGo := popcntMaskSlice(s, m) - useAsm = (true && oldUseAsm) - resAsm := popcntMaskSlice(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestPopcntAndSliceCond(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - oldUseAsm := useAsm - defer func() { useAsm = oldUseAsm }() - useAsm = false - resGo := popcntAndSlice(s, m) - useAsm = (true && oldUseAsm) - resAsm := popcntAndSlice(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestPopcntOrSliceCond(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - oldUseAsm := useAsm - defer func() { useAsm = oldUseAsm }() - useAsm = false - resGo := popcntOrSlice(s, m) - useAsm = (true && oldUseAsm) - resAsm := popcntOrSlice(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestPopcntXorSliceCond(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - oldUseAsm := useAsm - defer func() { useAsm = oldUseAsm }() - useAsm = false - resGo := popcntXorSlice(s, m) - useAsm = (true && oldUseAsm) - resAsm := popcntXorSlice(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} diff --git a/popcnt_cmp_test.go b/popcnt_cmp_test.go deleted file mode 100644 index abbd400..0000000 --- a/popcnt_cmp_test.go +++ /dev/null @@ -1,59 +0,0 @@ -//go:build !go1.9 && amd64 && !appengine -// +build !go1.9,amd64,!appengine - -// This file tests the popcnt functions - -package bitset - -import ( - "testing" -) - -func TestComparePopcntSlice(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - resGo := popcntSliceGo(s) - resAsm := popcntSliceAsm(s) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestComparePopcntMaskSlice(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - resGo := popcntMaskSliceGo(s, m) - resAsm := popcntMaskSliceAsm(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestComparePopcntAndSlice(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - resGo := popcntAndSliceGo(s, m) - resAsm := popcntAndSliceAsm(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestComparePopcntOrSlice(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - resGo := popcntOrSliceGo(s, m) - resAsm := popcntOrSliceAsm(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} - -func TestComparePopcntXorSlice(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - resGo := popcntXorSliceGo(s, m) - resAsm := popcntXorSliceAsm(s, m) - if resGo != resAsm { - t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) - } -} diff --git a/popcnt_generic.go b/popcnt_generic.go deleted file mode 100644 index 9e0ad46..0000000 --- a/popcnt_generic.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build !go1.9 && (!amd64 || appengine) -// +build !go1.9 -// +build !amd64 appengine - -package bitset - -func popcntSlice(s []uint64) uint64 { - return popcntSliceGo(s) -} - -func popcntMaskSlice(s, m []uint64) uint64 { - return popcntMaskSliceGo(s, m) -} - -func popcntAndSlice(s, m []uint64) uint64 { - return popcntAndSliceGo(s, m) -} - -func popcntOrSlice(s, m []uint64) uint64 { - return popcntOrSliceGo(s, m) -} - -func popcntXorSlice(s, m []uint64) uint64 { - return popcntXorSliceGo(s, m) -} diff --git a/popcnt_go18_test.go b/popcnt_go18_test.go deleted file mode 100644 index 03b3574..0000000 --- a/popcnt_go18_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// This file tests the popcnt functions - -package bitset - -import ( - "testing" -) - -func TestPopcntSliceGo(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - res := popcntSliceGo(s) - const l uint64 = 27 - if res != l { - t.Errorf("Wrong popcount %d != %d", res, l) - } -} - -func TestPopcntMaskSliceGo(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - res := popcntMaskSliceGo(s, m) - const l uint64 = 9 - if res != l { - t.Errorf("Wrong mask %d != %d", res, l) - } -} - -func TestPopcntAndSliceGo(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - res := popcntAndSliceGo(s, m) - const l uint64 = 18 - if res != l { - t.Errorf("Wrong And %d != %d", res, l) - } -} - -func TestPopcntOrSliceGo(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - res := popcntOrSliceGo(s, m) - const l uint64 = 50 - if res != l { - t.Errorf("Wrong OR %d != %d", res, l) - } -} - -func TestPopcntXorSliceGo(t *testing.T) { - s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} - m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} - res := popcntXorSliceGo(s, m) - const l uint64 = 32 - if res != l { - t.Errorf("Wrong OR %d != %d", res, l) - } -} diff --git a/select.go b/select.go index f15e74a..a43c6bd 100644 --- a/select.go +++ b/select.go @@ -1,10 +1,12 @@ package bitset +import "math/bits" + func select64(w uint64, j uint) uint { seen := 0 // Divide 64bit part := w & 0xFFFFFFFF - n := uint(popcount(part)) + n := uint(bits.OnesCount64(part)) if n <= j { part = w >> 32 seen += 32 @@ -15,7 +17,7 @@ func select64(w uint64, j uint) uint { // Divide 32bit part = ww & 0xFFFF - n = uint(popcount(part)) + n = uint(bits.OnesCount64(part)) if n <= j { part = ww >> 16 seen += 16 @@ -25,7 +27,7 @@ func select64(w uint64, j uint) uint { // Divide 16bit part = ww & 0xFF - n = uint(popcount(part)) + n = uint(bits.OnesCount64(part)) if n <= j { part = ww >> 8 seen += 8 diff --git a/trailing_zeros_18.go b/trailing_zeros_18.go deleted file mode 100644 index 12336e7..0000000 --- a/trailing_zeros_18.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build !go1.9 -// +build !go1.9 - -package bitset - -var deBruijn = [...]byte{ - 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, - 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, - 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, - 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, -} - -func trailingZeroes64(v uint64) uint { - return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58]) -} diff --git a/trailing_zeros_19.go b/trailing_zeros_19.go deleted file mode 100644 index cfb0a84..0000000 --- a/trailing_zeros_19.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go1.9 -// +build go1.9 - -package bitset - -import "math/bits" - -func trailingZeroes64(v uint64) uint { - return uint(bits.TrailingZeros64(v)) -}