Skip to content

Commit

Permalink
Merge pull request #55 from willf/go19-backward-compatibility
Browse files Browse the repository at this point in the history
Go19 backward compatibility
  • Loading branch information
Will Fitzgerald authored Aug 29, 2017
2 parents 988f4f2 + b77e40d commit d860f34
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 35 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ branches:

go:
- 1.8
- 1.9
- tip

matrix:
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ As an alternative to BitSets, one should check out the 'big' package, which prov

Godoc documentation is at: https://godoc.org/github.com/willf/bitset


## Implementation Note

Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed.

It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped.

## Installation

```bash
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.2
1.1.3
12 changes: 0 additions & 12 deletions bitset.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,17 +305,6 @@ func (b *BitSet) Count() uint {
return 0
}

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])
}

// Equal tests the equvalence of two BitSets.
// False if they are of different sizes, otherwise true
// only if all the same bits are set
Expand Down Expand Up @@ -441,7 +430,6 @@ func (b *BitSet) InPlaceIntersection(compare *BitSet) {
if compare.length > 0 {
b.extendSetMaybe(compare.length - 1)
}
return
}

// Union of base set and other set
Expand Down
45 changes: 45 additions & 0 deletions popcnt_19.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// +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
for i := range s {
cnt += bits.OnesCount64(s[i] &^ m[i])
}
return uint64(cnt)
}

func popcntAndSlice(s, m []uint64) uint64 {
var cnt int
for i := range s {
cnt += bits.OnesCount64(s[i] & m[i])
}
return uint64(cnt)
}

func popcntOrSlice(s, m []uint64) uint64 {
var cnt int
for i := range s {
cnt += bits.OnesCount64(s[i] | m[i])
}
return uint64(cnt)
}

func popcntXorSlice(s, m []uint64) uint64 {
var cnt int
for i := range s {
cnt += bits.OnesCount64(s[i] ^ m[i])
}
return uint64(cnt)
}
1 change: 1 addition & 0 deletions popcnt_amd64.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// +build !go1.9
// +build amd64,!appengine

package bitset
Expand Down
1 change: 1 addition & 0 deletions popcnt_amd64.s
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// +build !go1.9
// +build amd64,!appengine

TEXT ·hasAsm(SB),4,$0-1
Expand Down
1 change: 1 addition & 0 deletions popcnt_amd64_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// +build !go1.9
// +build amd64,!appengine

// This file tests the popcnt funtions
Expand Down
59 changes: 59 additions & 0 deletions popcnt_cmp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// +build !go1.9
// +build amd64,!appengine

// This file tests the popcnt funtions

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)
}
}
1 change: 1 addition & 0 deletions popcnt_generic.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// +build !go1.9
// +build !amd64 appengine

package bitset
Expand Down
56 changes: 56 additions & 0 deletions popcnt_go18_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// This file tests the popcnt funtions

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)
}
}
42 changes: 20 additions & 22 deletions popcnt_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// +build amd64,!appengine

// This file tests the popcnt funtions

package bitset
Expand All @@ -10,49 +8,49 @@ import (

func TestPopcntSlice(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)
res := popcntSlice(s)
const l uint64 = 27
if res != l {
t.Errorf("Wrong popcount %d != %d", res, l)
}
}

func TestPopcntMaskSlice(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)
res := popcntMaskSlice(s, m)
const l uint64 = 9
if res != l {
t.Errorf("Wrong mask %d != %d", res, l)
}
}

func TestPopcntAndSlice(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)
res := popcntAndSlice(s, m)
const l uint64 = 18
if res != l {
t.Errorf("Wrong And %d != %d", res, l)
}
}

func TestPopcntOrSlice(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)
res := popcntOrSlice(s, m)
const l uint64 = 50
if res != l {
t.Errorf("Wrong OR %d != %d", res, l)
}
}

func TestPopcntXorSlice(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)
res := popcntXorSlice(s, m)
const l uint64 = 32
if res != l {
t.Errorf("Wrong OR %d != %d", res, l)
}
}
14 changes: 14 additions & 0 deletions trailing_zeros_18.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// +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])
}
9 changes: 9 additions & 0 deletions trailing_zeros_19.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build go1.9

package bitset

import "math/bits"

func trailingZeroes64(v uint64) uint {
return uint(bits.TrailingZeros64(v))
}

0 comments on commit d860f34

Please sign in to comment.