diff --git a/container/intsets/sparse.go b/container/intsets/sparse.go index 4c77ae4cd1..be4c5a66cf 100644 --- a/container/intsets/sparse.go +++ b/container/intsets/sparse.go @@ -18,9 +18,9 @@ package intsets // - Add InsertAll(...int), RemoveAll(...int) // - Add 'bool changed' results for {Intersection,Difference}With too. // -// TODO(adonovan): implement Dense, a sparse bit vector with a similar -// API. The space usage would be proportional to Max(), not Len(), -// and the implementation would be based upon big.Int. +// TODO(adonovan): implement Dense, a dense bit vector with a similar API. +// The space usage would be proportional to Max(), not Len(), and the +// implementation would be based upon big.Int. import ( "bytes" @@ -131,7 +131,7 @@ func (b *block) empty() bool { func (b *block) len() int { var l int for _, w := range b.bits { - l += int(popcount(w)) + l += popcount(w) } return l } @@ -144,7 +144,7 @@ func (b *block) max() int { // Decrement bi by number of high zeros in last.bits. for i := len(b.bits) - 1; i >= 0; i-- { if w := b.bits[i]; w != 0 { - return bi - int(nlz(w)) - 1 + return bi - nlz(w) - 1 } bi -= bitsPerWord } diff --git a/container/intsets/util.go b/container/intsets/util.go index fe26f29e17..a626048122 100644 --- a/container/intsets/util.go +++ b/container/intsets/util.go @@ -19,8 +19,8 @@ func init() { } // popcount returns the population count (number of set bits) of x. -func popcount(x word) word { - return word(a[byte(x>>(0*8))] + +func popcount(x word) int { + return int(a[byte(x>>(0*8))] + a[byte(x>>(1*8))] + a[byte(x>>(2*8))] + a[byte(x>>(3*8))] + @@ -32,7 +32,7 @@ func popcount(x word) word { // nlz returns the number of leading zeros of x. // From Hacker's Delight, fig 5.11. -func nlz(x word) word { +func nlz(x word) int { x |= (x >> 1) x |= (x >> 2) x |= (x >> 4) diff --git a/container/intsets/util_test.go b/container/intsets/util_test.go index 900c8cb660..92a4bc58bc 100644 --- a/container/intsets/util_test.go +++ b/container/intsets/util_test.go @@ -7,8 +7,17 @@ package intsets import "testing" func TestNLZ(t *testing.T) { - if x := nlz(0x0000801000000000); x != 16 { - t.Errorf("bad %d", x) + // Test the platform-specific edge case. + // NB: v must be a var (not const) so that the word() conversion is dynamic. + // Otherwise the compiler will report an error. + v := uint64(0x0000801000000000) + n := nlz(word(v)) + want := 32 // (on 32-bit) + if bitsPerWord == 64 { + want = 16 + } + if n != want { + t.Errorf("%d-bit nlz(%d) = %d, want %d", bitsPerWord, v, n, want) } }