From 30284c1b2b63c6bafb9757c7b1e2274aa60287d9 Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 12:30:13 -0400 Subject: [PATCH 01/10] support for 1.9 bit counts --- popcnt_19.go | 45 ++++++++++++++++++++++++++++ popcnt_test.go => popcnt_cmp_test.go | 0 2 files changed, 45 insertions(+) create mode 100644 popcnt_19.go rename popcnt_test.go => popcnt_cmp_test.go (100%) diff --git a/popcnt_19.go b/popcnt_19.go new file mode 100644 index 0000000..fc8ff4f --- /dev/null +++ b/popcnt_19.go @@ -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) +} diff --git a/popcnt_test.go b/popcnt_cmp_test.go similarity index 100% rename from popcnt_test.go rename to popcnt_cmp_test.go From ad0865fb4fa1d16ed888ee0c30a0babb86a536c9 Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 12:30:54 -0400 Subject: [PATCH 02/10] support for 1.9 bit counts --- popcnt_amd64.go | 1 + popcnt_amd64_test.go | 1 + popcnt_cmp_test.go | 1 + popcnt_generic.go | 1 + popcnt_go18_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++++ popcnt_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+) create mode 100644 popcnt_go18_test.go create mode 100644 popcnt_test.go diff --git a/popcnt_amd64.go b/popcnt_amd64.go index 665a864..4cf64f2 100644 --- a/popcnt_amd64.go +++ b/popcnt_amd64.go @@ -1,3 +1,4 @@ +// +build !go1.9 // +build amd64,!appengine package bitset diff --git a/popcnt_amd64_test.go b/popcnt_amd64_test.go index 611949b..c79d009 100644 --- a/popcnt_amd64_test.go +++ b/popcnt_amd64_test.go @@ -1,3 +1,4 @@ +// +build !go1.9 // +build amd64,!appengine // This file tests the popcnt funtions diff --git a/popcnt_cmp_test.go b/popcnt_cmp_test.go index 08bfff5..190e83a 100644 --- a/popcnt_cmp_test.go +++ b/popcnt_cmp_test.go @@ -1,3 +1,4 @@ +// +build !go1.9 // +build amd64,!appengine // This file tests the popcnt funtions diff --git a/popcnt_generic.go b/popcnt_generic.go index 6b21cb7..21e0ff7 100644 --- a/popcnt_generic.go +++ b/popcnt_generic.go @@ -1,3 +1,4 @@ +// +build !go1.9 // +build !amd64 appengine package bitset diff --git a/popcnt_go18_test.go b/popcnt_go18_test.go new file mode 100644 index 0000000..df6921c --- /dev/null +++ b/popcnt_go18_test.go @@ -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) + } +} diff --git a/popcnt_test.go b/popcnt_test.go new file mode 100644 index 0000000..d9fbb34 --- /dev/null +++ b/popcnt_test.go @@ -0,0 +1,56 @@ +// This file tests the popcnt funtions + +package bitset + +import ( + "testing" +) + +func TestPopcntSlice(t *testing.T) { + s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} + 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} + 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} + 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} + 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} + res := popcntXorSlice(s, m) + const l uint64 = 32 + if res != l { + t.Errorf("Wrong OR %d != %d", res, l) + } +} From c0127cea238cdbba13260ccaa72ddadbe816e7b8 Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 12:31:20 -0400 Subject: [PATCH 03/10] ask travis to test 1.8 and 1.9 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d4eee61..9413dc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ branches: go: - 1.8 + - 1.9 - tip matrix: From e2d3b02eaeded7c3c9ec60e99213d04145c72f95 Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 12:40:12 -0400 Subject: [PATCH 04/10] support for 1.9 bit counts --- popcnt_amd64.s | 1 + popcnt_cmp_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/popcnt_amd64.s b/popcnt_amd64.s index 18f5878..666c0dc 100644 --- a/popcnt_amd64.s +++ b/popcnt_amd64.s @@ -1,3 +1,4 @@ +// +build !go1.9 // +build amd64,!appengine TEXT ·hasAsm(SB),4,$0-1 diff --git a/popcnt_cmp_test.go b/popcnt_cmp_test.go index 190e83a..8a06dc9 100644 --- a/popcnt_cmp_test.go +++ b/popcnt_cmp_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -func TestPopcntSlice(t *testing.T) { +func TestComparePopcntSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} resGo := popcntSliceGo(s) resAsm := popcntSliceAsm(s) @@ -18,7 +18,7 @@ func TestPopcntSlice(t *testing.T) { } } -func TestPopcntMaskSlice(t *testing.T) { +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) @@ -28,7 +28,7 @@ func TestPopcntMaskSlice(t *testing.T) { } } -func TestPopcntAndSlice(t *testing.T) { +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) @@ -38,7 +38,7 @@ func TestPopcntAndSlice(t *testing.T) { } } -func TestPopcntOrSlice(t *testing.T) { +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) @@ -48,7 +48,7 @@ func TestPopcntOrSlice(t *testing.T) { } } -func TestPopcntXorSlice(t *testing.T) { +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) From 332dbec5dfe2cdcd5621e8a254ad5cf7c2961cad Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 12:45:00 -0400 Subject: [PATCH 05/10] remove unneeded return --- bitset.go | 1 - 1 file changed, 1 deletion(-) diff --git a/bitset.go b/bitset.go index a6d236e..19883aa 100644 --- a/bitset.go +++ b/bitset.go @@ -441,7 +441,6 @@ func (b *BitSet) InPlaceIntersection(compare *BitSet) { if compare.length > 0 { b.extendSetMaybe(compare.length - 1) } - return } // Union of base set and other set From e50f6331a528e717b638f91ee5b9d672b6951037 Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 12:49:43 -0400 Subject: [PATCH 06/10] uses math/bits for trailing zeros --- bitset.go | 11 ----------- trailing_zeros_18.go | 14 ++++++++++++++ trailing_zeros_19.go | 9 +++++++++ 3 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 trailing_zeros_18.go create mode 100644 trailing_zeros_19.go diff --git a/bitset.go b/bitset.go index 19883aa..dbd1708 100644 --- a/bitset.go +++ b/bitset.go @@ -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 diff --git a/trailing_zeros_18.go b/trailing_zeros_18.go new file mode 100644 index 0000000..c52b61b --- /dev/null +++ b/trailing_zeros_18.go @@ -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]) +} diff --git a/trailing_zeros_19.go b/trailing_zeros_19.go new file mode 100644 index 0000000..36a988e --- /dev/null +++ b/trailing_zeros_19.go @@ -0,0 +1,9 @@ +// +build go1.9 + +package bitset + +import "math/bits" + +func trailingZeroes64(v uint64) uint { + return uint(bits.TrailingZeros64(v)) +} From 10d0e8feceaa7c374db350f44f4311e226e2f6ba Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 13:02:06 -0400 Subject: [PATCH 07/10] support to 1.7 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9413dc4..6ecf285 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ branches: - travis go: + - 1.7 - 1.8 - 1.9 - tip From d53da8f248f7a800722fe8c729aea29a627321fb Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 13:02:26 -0400 Subject: [PATCH 08/10] update README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d5817ad..6c62b20 100644 --- a/README.md +++ b/README.md @@ -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 From 137ee1ab11e3a90d30cb5595f912c995a4d0ed60 Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 13:02:39 -0400 Subject: [PATCH 09/10] bump version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 45a1b3f..781dcb0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.2 +1.1.3 From b77e40d9e7c5702f8f2d94076e76595e1724a6f4 Mon Sep 17 00:00:00 2001 From: Will Fitzgerald Date: Mon, 28 Aug 2017 13:05:29 -0400 Subject: [PATCH 10/10] just go back to 1.8 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6ecf285..9413dc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,6 @@ branches: - travis go: - - 1.7 - 1.8 - 1.9 - tip