From 65906ce503d95eb83df784bfd4a0ae81965b1118 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Tue, 20 May 2014 14:52:50 -0400 Subject: [PATCH] go.tools/container/intsets: support negative elements in BitString(). (I forgot about this when we added support for negative elements generally.) We use floating point for negative numbers. The order of the output is reversed from the previous (little-endian) behaviour since it makes for more readable floating point. LGTM=gri R=gri CC=golang-codereviews https://golang.org/cl/95570043 --- container/intsets/sparse.go | 33 ++++++++++++++++++++++++++++---- container/intsets/sparse_test.go | 28 +++++++++++++++++---------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/container/intsets/sparse.go b/container/intsets/sparse.go index be14d0559..763b38485 100644 --- a/container/intsets/sparse.go +++ b/container/intsets/sparse.go @@ -698,19 +698,44 @@ func (s *Sparse) String() string { return buf.String() } -// BitString returns the set s as a non-empty string of 1s and 0s. -// The ith character is 1 if the set contains i. +// BitString returns the set as a string of 1s and 0s denoting the sum +// of the i'th powers of 2, for each i in s. A radix point, always +// preceded by a digit, appears if the sum is non-integral. +// +// Examples: +// {}.BitString() = "0" +// {4,5}.BitString() = "110000" +// {-3}.BitString() = "0.001" +// {-3,0,4,5}.BitString() = "110001.001" // func (s *Sparse) BitString() string { if s.IsEmpty() { return "0" } - b := make([]byte, s.Max()+1) + + min, max := s.Min(), s.Max() + var nbytes int + if max > 0 { + nbytes = max + } + nbytes++ // zero bit + radix := nbytes + if min < 0 { + nbytes += len(".") - min + } + + b := make([]byte, nbytes) for i := range b { b[i] = '0' } + if radix < nbytes { + b[radix] = '.' + } s.forEach(func(x int) { - b[x] = '1' + if x >= 0 { + x += len(".") + } + b[radix-x] = '1' }) return string(b) } diff --git a/container/intsets/sparse_test.go b/container/intsets/sparse_test.go index 258291af1..bdbb8dfd5 100644 --- a/container/intsets/sparse_test.go +++ b/container/intsets/sparse_test.go @@ -23,9 +23,6 @@ func TestBasics(t *testing.T) { if s := s.String(); s != "{}" { t.Errorf("String({}): got %q, want \"{}\"", s) } - if s := s.BitString(); s != "0" { - t.Errorf("BitString({}): got %q, want \"0\"", s) - } if s.Has(3) { t.Errorf("Has(3): got true, want false") } @@ -421,13 +418,24 @@ func TestIntersectionWith(t *testing.T) { } func TestBitString(t *testing.T) { - var set intsets.Sparse - set.Insert(0) - set.Insert(7) - set.Insert(177) - want := "10000001" + strings.Repeat("0", 169) + "1" - if got := set.BitString(); got != want { - t.Errorf("BitString: got %s, want %s", got, want) + for _, test := range []struct { + input []int + want string + }{ + {nil, "0"}, + {[]int{0}, "1"}, + {[]int{0, 4, 5}, "110001"}, + {[]int{0, 7, 177}, "1" + strings.Repeat("0", 169) + "10000001"}, + {[]int{-3, 0, 4, 5}, "110001.001"}, + {[]int{-3}, "0.001"}, + } { + var set intsets.Sparse + for _, x := range test.input { + set.Insert(x) + } + if got := set.BitString(); got != test.want { + t.Errorf("BitString(%s) = %s, want %s", set.String(), got, test.want) + } } }