+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package intsets provides Sparse, a compact and fast representation
+// for sparse sets of int values.
+//
+// The time complexity of the operations Len, Insert, Remove and Has
+// is in O(n) but in practice those methods are faster and more
+// space-efficient than equivalent operations on sets based on the Go
+// map type. The IsEmpty, Min, Max, Clear and TakeMin operations
+// require constant time.
+//
+package intsets // import "golang.org/x/tools/container/intsets"
+
+// TODO(adonovan):
+// - Add InsertAll(...int), RemoveAll(...int)
+// - Add 'bool changed' results for {Intersection,Difference}With too.
+//
+// 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.
+//
+// TODO(adonovan): opt: make UnionWith and Difference faster.
+// These are the hot-spots for go/pointer.
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// A Sparse is a set of int values.
+// Sparse operations (even queries) are not concurrency-safe.
+//
+// The zero value for Sparse is a valid empty set.
+//
+// Sparse sets must be copied using the Copy method, not by assigning
+// a Sparse value.
+//
+type Sparse struct {
+ // An uninitialized Sparse represents an empty set.
+ // An empty set may also be represented by
+ // root.next == root.prev == &root.
+ //
+ // The root is always the block with the smallest offset.
+ // It can be empty, but only if it is the only block; in that case, offset is
+ // MaxInt (which is not a valid offset).
+ root block
+}
+
+type word uintptr
+
+const (
+ _m = ^word(0)
+ bitsPerWord = 8 << (_m>>8&1 + _m>>16&1 + _m>>32&1)
+ bitsPerBlock = 256 // optimal value for go/pointer solver performance
+ wordsPerBlock = bitsPerBlock / bitsPerWord
+)
+
+// Limit values of implementation-specific int type.
+const (
+ MaxInt = int(^uint(0) >> 1)
+ MinInt = -MaxInt - 1
+)
+
+// -- block ------------------------------------------------------------
+
+// A set is represented as a circular doubly-linked list of blocks,
+// each containing an offset and a bit array of fixed size
+// bitsPerBlock; the blocks are ordered by increasing offset.
+//
+// The set contains an element x iff the block whose offset is x - (x
+// mod bitsPerBlock) has the bit (x mod bitsPerBlock) set, where mod
+// is the Euclidean remainder.
+//
+// A block may only be empty transiently.
+//
+type block struct {
+ offset int // offset mod bitsPerBlock == 0
+ bits [wordsPerBlock]word // contains at least one set bit
+ next, prev *block // doubly-linked list of blocks
+}
+
+// wordMask returns the word index (in block.bits)
+// and single-bit mask for the block's ith bit.
+func wordMask(i uint) (w uint, mask word) {
+ w = i / bitsPerWord
+ mask = 1 << (i % bitsPerWord)
+ return
+}
+
+// insert sets the block b's ith bit and
+// returns true if it was not already set.
+//
+func (b *block) insert(i uint) bool {
+ w, mask := wordMask(i)
+ if b.bits[w]&mask == 0 {
+ b.bits[w] |= mask
+ return true
+ }
+ return false
+}
+
+// remove clears the block's ith bit and
+// returns true if the bit was previously set.
+// NB: may leave the block empty.
+//
+func (b *block) remove(i uint) bool {
+ w, mask := wordMask(i)
+ if b.bits[w]&mask != 0 {
+ b.bits[w] &^= mask
+ return true
+ }
+ return false
+}
+
+// has reports whether the block's ith bit is set.
+func (b *block) has(i uint) bool {
+ w, mask := wordMask(i)
+ return b.bits[w]&mask != 0
+}
+
+// empty reports whether b.len()==0, but more efficiently.
+func (b *block) empty() bool {
+ for _, w := range b.bits {
+ if w != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// len returns the number of set bits in block b.
+func (b *block) len() int {
+ var l int
+ for _, w := range b.bits {
+ l += popcount(w)
+ }
+ return l
+}
+
+// max returns the maximum element of the block.
+// The block must not be empty.
+func (b *block) max() int {
+ bi := b.offset + bitsPerBlock
+ // 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 - nlz(w) - 1
+ }
+ bi -= bitsPerWord
+ }
+ panic("BUG: empty block")
+}
+
+// min returns the minimum element of the block,
+// and also removes it if take is set.
+// The block must not be initially empty.
+// NB: may leave the block empty.
+func (b *block) min(take bool) int {
+ for i, w := range b.bits {
+ if w != 0 {
+ tz := ntz(w)
+ if take {
+ b.bits[i] = w &^ (1 << uint(tz))
+ }
+ return b.offset + int(i*bitsPerWord) + tz
+ }
+ }
+ panic("BUG: empty block")
+}
+
+// lowerBound returns the smallest element of the block that is greater than or
+// equal to the element corresponding to the ith bit. If there is no such
+// element, the second return value is false.
+func (b *block) lowerBound(i uint) (int, bool) {
+ w := i / bitsPerWord
+ bit := i % bitsPerWord
+
+ if val := b.bits[w] >> bit; val != 0 {
+ return b.offset + int(i) + ntz(val), true
+ }
+
+ for w++; w < wordsPerBlock; w++ {
+ if val := b.bits[w]; val != 0 {
+ return b.offset + int(w*bitsPerWord) + ntz(val), true
+ }
+ }
+
+ return 0, false
+}
+
+// forEach calls f for each element of block b.
+// f must not mutate b's enclosing Sparse.
+func (b *block) forEach(f func(int)) {
+ for i, w := range b.bits {
+ offset := b.offset + i*bitsPerWord
+ for bi := 0; w != 0 && bi < bitsPerWord; bi++ {
+ if w&1 != 0 {
+ f(offset)
+ }
+ offset++
+ w >>= 1
+ }
+ }
+}
+
+// offsetAndBitIndex returns the offset of the block that would
+// contain x and the bit index of x within that block.
+//
+func offsetAndBitIndex(x int) (int, uint) {
+ mod := x % bitsPerBlock
+ if mod < 0 {
+ // Euclidean (non-negative) remainder
+ mod += bitsPerBlock
+ }
+ return x - mod, uint(mod)
+}
+
+// -- Sparse --------------------------------------------------------------
+
+// none is a shared, empty, sentinel block that indicates the end of a block
+// list.
+var none block
+
+// Dummy type used to generate an implicit panic. This must be defined at the
+// package level; if it is defined inside a function, it prevents the inlining
+// of that function.
+type to_copy_a_sparse_you_must_call_its_Copy_method struct{}
+
+// init ensures s is properly initialized.
+func (s *Sparse) init() {
+ root := &s.root
+ if root.next == nil {
+ root.offset = MaxInt
+ root.next = root
+ root.prev = root
+ } else if root.next.prev != root {
+ // Copying a Sparse x leads to pernicious corruption: the
+ // new Sparse y shares the old linked list, but iteration
+ // on y will never encounter &y.root so it goes into a
+ // loop. Fail fast before this occurs.
+ // We don't want to call panic here because it prevents the
+ // inlining of this function.
+ _ = (interface{}(nil)).(to_copy_a_sparse_you_must_call_its_Copy_method)
+ }
+}
+
+func (s *Sparse) first() *block {
+ s.init()
+ if s.root.offset == MaxInt {
+ return &none
+ }
+ return &s.root
+}
+
+// next returns the next block in the list, or end if b is the last block.
+func (s *Sparse) next(b *block) *block {
+ if b.next == &s.root {
+ return &none
+ }
+ return b.next
+}
+
+// prev returns the previous block in the list, or end if b is the first block.
+func (s *Sparse) prev(b *block) *block {
+ if b.prev == &s.root {
+ return &none
+ }
+ return b.prev
+}
+
+// IsEmpty reports whether the set s is empty.
+func (s *Sparse) IsEmpty() bool {
+ return s.root.next == nil || s.root.offset == MaxInt
+}
+
+// Len returns the number of elements in the set s.
+func (s *Sparse) Len() int {
+ var l int
+ for b := s.first(); b != &none; b = s.next(b) {
+ l += b.len()
+ }
+ return l
+}
+
+// Max returns the maximum element of the set s, or MinInt if s is empty.
+func (s *Sparse) Max() int {
+ if s.IsEmpty() {
+ return MinInt
+ }
+ return s.root.prev.max()
+}
+
+// Min returns the minimum element of the set s, or MaxInt if s is empty.
+func (s *Sparse) Min() int {
+ if s.IsEmpty() {
+ return MaxInt
+ }
+ return s.root.min(false)
+}
+
+// LowerBound returns the smallest element >= x, or MaxInt if there is no such
+// element.
+func (s *Sparse) LowerBound(x int) int {
+ offset, i := offsetAndBitIndex(x)
+ for b := s.first(); b != &none; b = s.next(b) {
+ if b.offset > offset {
+ return b.min(false)
+ }
+ if b.offset == offset {
+ if y, ok := b.lowerBound(i); ok {
+ return y
+ }
+ }
+ }
+ return MaxInt
+}
+
+// block returns the block that would contain offset,
+// or nil if s contains no such block.
+// Precondition: offset is a multiple of bitsPerBlock.
+func (s *Sparse) block(offset int) *block {
+ for b := s.first(); b != &none && b.offset <= offset; b = s.next(b) {
+ if b.offset == offset {
+ return b
+ }
+ }
+ return nil
+}
+
+// Insert adds x to the set s, and reports whether the set grew.
+func (s *Sparse) Insert(x int) bool {
+ offset, i := offsetAndBitIndex(x)
+
+ b := s.first()
+ for ; b != &none && b.offset <= offset; b = s.next(b) {
+ if b.offset == offset {
+ return b.insert(i)
+ }
+ }
+
+ // Insert new block before b.
+ new := s.insertBlockBefore(b)
+ new.offset = offset
+ return new.insert(i)
+}
+
+// removeBlock removes a block and returns the block that followed it (or end if
+// it was the last block).
+func (s *Sparse) removeBlock(b *block) *block {
+ if b != &s.root {
+ b.prev.next = b.next
+ b.next.prev = b.prev
+ if b.next == &s.root {
+ return &none
+ }
+ return b.next
+ }
+
+ first := s.root.next
+ if first == &s.root {
+ // This was the only block.
+ s.Clear()
+ return &none
+ }
+ s.root.offset = first.offset
+ s.root.bits = first.bits
+ if first.next == &s.root {
+ // Single block remaining.
+ s.root.next = &s.root
+ s.root.prev = &s.root
+ } else {
+ s.root.next = first.next
+ first.next.prev = &s.root
+ }
+ return &s.root
+}
+
+// Remove removes x from the set s, and reports whether the set shrank.
+func (s *Sparse) Remove(x int) bool {
+ offset, i := offsetAndBitIndex(x)
+ if b := s.block(offset); b != nil {
+ if !b.remove(i) {
+ return false
+ }
+ if b.empty() {
+ s.removeBlock(b)
+ }
+ return true
+ }
+ return false
+}
+
+// Clear removes all elements from the set s.
+func (s *Sparse) Clear() {
+ s.root = block{
+ offset: MaxInt,
+ next: &s.root,
+ prev: &s.root,
+ }
+}
+
+// If set s is non-empty, TakeMin sets *p to the minimum element of
+// the set s, removes that element from the set and returns true.
+// Otherwise, it returns false and *p is undefined.
+//
+// This method may be used for iteration over a worklist like so:
+//
+// var x int
+// for worklist.TakeMin(&x) { use(x) }
+//
+func (s *Sparse) TakeMin(p *int) bool {
+ if s.IsEmpty() {
+ return false
+ }
+ *p = s.root.min(true)
+ if s.root.empty() {
+ s.removeBlock(&s.root)
+ }
+ return true
+}
+
+// Has reports whether x is an element of the set s.
+func (s *Sparse) Has(x int) bool {
+ offset, i := offsetAndBitIndex(x)
+ if b := s.block(offset); b != nil {
+ return b.has(i)
+ }
+ return false
+}
+
+// forEach applies function f to each element of the set s in order.
+//
+// f must not mutate s. Consequently, forEach is not safe to expose
+// to clients. In any case, using "range s.AppendTo()" allows more
+// natural control flow with continue/break/return.
+//
+func (s *Sparse) forEach(f func(int)) {
+ for b := s.first(); b != &none; b = s.next(b) {
+ b.forEach(f)
+ }
+}
+
+// Copy sets s to the value of x.
+func (s *Sparse) Copy(x *Sparse) {
+ if s == x {
+ return
+ }
+
+ xb := x.first()
+ sb := s.first()
+ for xb != &none {
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ sb.offset = xb.offset
+ sb.bits = xb.bits
+ xb = x.next(xb)
+ sb = s.next(sb)
+ }
+ s.discardTail(sb)
+}
+
+// insertBlockBefore returns a new block, inserting it before next.
+// If next is the root, the root is replaced. If next is end, the block is
+// inserted at the end.
+func (s *Sparse) insertBlockBefore(next *block) *block {
+ if s.IsEmpty() {
+ if next != &none {
+ panic("BUG: passed block with empty set")
+ }
+ return &s.root
+ }
+
+ if next == &s.root {
+ // Special case: we need to create a new block that will become the root
+ // block.The old root block becomes the second block.
+ second := s.root
+ s.root = block{
+ next: &second,
+ }
+ if second.next == &s.root {
+ s.root.prev = &second
+ } else {
+ s.root.prev = second.prev
+ second.next.prev = &second
+ second.prev = &s.root
+ }
+ return &s.root
+ }
+ if next == &none {
+ // Insert before root.
+ next = &s.root
+ }
+ b := new(block)
+ b.next = next
+ b.prev = next.prev
+ b.prev.next = b
+ next.prev = b
+ return b
+}
+
+// discardTail removes block b and all its successors from s.
+func (s *Sparse) discardTail(b *block) {
+ if b != &none {
+ if b == &s.root {
+ s.Clear()
+ } else {
+ b.prev.next = &s.root
+ s.root.prev = b.prev
+ }
+ }
+}
+
+// IntersectionWith sets s to the intersection s ∩ x.
+func (s *Sparse) IntersectionWith(x *Sparse) {
+ if s == x {
+ return
+ }
+
+ xb := x.first()
+ sb := s.first()
+ for xb != &none && sb != &none {
+ switch {
+ case xb.offset < sb.offset:
+ xb = x.next(xb)
+
+ case xb.offset > sb.offset:
+ sb = s.removeBlock(sb)
+
+ default:
+ var sum word
+ for i := range sb.bits {
+ r := xb.bits[i] & sb.bits[i]
+ sb.bits[i] = r
+ sum |= r
+ }
+ if sum != 0 {
+ sb = s.next(sb)
+ } else {
+ // sb will be overwritten or removed
+ }
+
+ xb = x.next(xb)
+ }
+ }
+
+ s.discardTail(sb)
+}
+
+// Intersection sets s to the intersection x ∩ y.
+func (s *Sparse) Intersection(x, y *Sparse) {
+ switch {
+ case s == x:
+ s.IntersectionWith(y)
+ return
+ case s == y:
+ s.IntersectionWith(x)
+ return
+ case x == y:
+ s.Copy(x)
+ return
+ }
+
+ xb := x.first()
+ yb := y.first()
+ sb := s.first()
+ for xb != &none && yb != &none {
+ switch {
+ case xb.offset < yb.offset:
+ xb = x.next(xb)
+ continue
+ case xb.offset > yb.offset:
+ yb = y.next(yb)
+ continue
+ }
+
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ sb.offset = xb.offset
+
+ var sum word
+ for i := range sb.bits {
+ r := xb.bits[i] & yb.bits[i]
+ sb.bits[i] = r
+ sum |= r
+ }
+ if sum != 0 {
+ sb = s.next(sb)
+ } else {
+ // sb will be overwritten or removed
+ }
+
+ xb = x.next(xb)
+ yb = y.next(yb)
+ }
+
+ s.discardTail(sb)
+}
+
+// Intersects reports whether s ∩ x ≠ ∅.
+func (s *Sparse) Intersects(x *Sparse) bool {
+ sb := s.first()
+ xb := x.first()
+ for sb != &none && xb != &none {
+ switch {
+ case xb.offset < sb.offset:
+ xb = x.next(xb)
+ case xb.offset > sb.offset:
+ sb = s.next(sb)
+ default:
+ for i := range sb.bits {
+ if sb.bits[i]&xb.bits[i] != 0 {
+ return true
+ }
+ }
+ sb = s.next(sb)
+ xb = x.next(xb)
+ }
+ }
+ return false
+}
+
+// UnionWith sets s to the union s ∪ x, and reports whether s grew.
+func (s *Sparse) UnionWith(x *Sparse) bool {
+ if s == x {
+ return false
+ }
+
+ var changed bool
+ xb := x.first()
+ sb := s.first()
+ for xb != &none {
+ if sb != &none && sb.offset == xb.offset {
+ for i := range xb.bits {
+ if sb.bits[i] != xb.bits[i] {
+ sb.bits[i] |= xb.bits[i]
+ changed = true
+ }
+ }
+ xb = x.next(xb)
+ } else if sb == &none || sb.offset > xb.offset {
+ sb = s.insertBlockBefore(sb)
+ sb.offset = xb.offset
+ sb.bits = xb.bits
+ changed = true
+
+ xb = x.next(xb)
+ }
+ sb = s.next(sb)
+ }
+ return changed
+}
+
+// Union sets s to the union x ∪ y.
+func (s *Sparse) Union(x, y *Sparse) {
+ switch {
+ case x == y:
+ s.Copy(x)
+ return
+ case s == x:
+ s.UnionWith(y)
+ return
+ case s == y:
+ s.UnionWith(x)
+ return
+ }
+
+ xb := x.first()
+ yb := y.first()
+ sb := s.first()
+ for xb != &none || yb != &none {
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ switch {
+ case yb == &none || (xb != &none && xb.offset < yb.offset):
+ sb.offset = xb.offset
+ sb.bits = xb.bits
+ xb = x.next(xb)
+
+ case xb == &none || (yb != &none && yb.offset < xb.offset):
+ sb.offset = yb.offset
+ sb.bits = yb.bits
+ yb = y.next(yb)
+
+ default:
+ sb.offset = xb.offset
+ for i := range xb.bits {
+ sb.bits[i] = xb.bits[i] | yb.bits[i]
+ }
+ xb = x.next(xb)
+ yb = y.next(yb)
+ }
+ sb = s.next(sb)
+ }
+
+ s.discardTail(sb)
+}
+
+// DifferenceWith sets s to the difference s ∖ x.
+func (s *Sparse) DifferenceWith(x *Sparse) {
+ if s == x {
+ s.Clear()
+ return
+ }
+
+ xb := x.first()
+ sb := s.first()
+ for xb != &none && sb != &none {
+ switch {
+ case xb.offset > sb.offset:
+ sb = s.next(sb)
+
+ case xb.offset < sb.offset:
+ xb = x.next(xb)
+
+ default:
+ var sum word
+ for i := range sb.bits {
+ r := sb.bits[i] & ^xb.bits[i]
+ sb.bits[i] = r
+ sum |= r
+ }
+ if sum == 0 {
+ sb = s.removeBlock(sb)
+ } else {
+ sb = s.next(sb)
+ }
+ xb = x.next(xb)
+ }
+ }
+}
+
+// Difference sets s to the difference x ∖ y.
+func (s *Sparse) Difference(x, y *Sparse) {
+ switch {
+ case x == y:
+ s.Clear()
+ return
+ case s == x:
+ s.DifferenceWith(y)
+ return
+ case s == y:
+ var y2 Sparse
+ y2.Copy(y)
+ s.Difference(x, &y2)
+ return
+ }
+
+ xb := x.first()
+ yb := y.first()
+ sb := s.first()
+ for xb != &none && yb != &none {
+ if xb.offset > yb.offset {
+ // y has block, x has &none
+ yb = y.next(yb)
+ continue
+ }
+
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ sb.offset = xb.offset
+
+ switch {
+ case xb.offset < yb.offset:
+ // x has block, y has &none
+ sb.bits = xb.bits
+
+ sb = s.next(sb)
+
+ default:
+ // x and y have corresponding blocks
+ var sum word
+ for i := range sb.bits {
+ r := xb.bits[i] & ^yb.bits[i]
+ sb.bits[i] = r
+ sum |= r
+ }
+ if sum != 0 {
+ sb = s.next(sb)
+ } else {
+ // sb will be overwritten or removed
+ }
+
+ yb = y.next(yb)
+ }
+ xb = x.next(xb)
+ }
+
+ for xb != &none {
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ sb.offset = xb.offset
+ sb.bits = xb.bits
+ sb = s.next(sb)
+
+ xb = x.next(xb)
+ }
+
+ s.discardTail(sb)
+}
+
+// SymmetricDifferenceWith sets s to the symmetric difference s ∆ x.
+func (s *Sparse) SymmetricDifferenceWith(x *Sparse) {
+ if s == x {
+ s.Clear()
+ return
+ }
+
+ sb := s.first()
+ xb := x.first()
+ for xb != &none && sb != &none {
+ switch {
+ case sb.offset < xb.offset:
+ sb = s.next(sb)
+ case xb.offset < sb.offset:
+ nb := s.insertBlockBefore(sb)
+ nb.offset = xb.offset
+ nb.bits = xb.bits
+ xb = x.next(xb)
+ default:
+ var sum word
+ for i := range sb.bits {
+ r := sb.bits[i] ^ xb.bits[i]
+ sb.bits[i] = r
+ sum |= r
+ }
+ if sum == 0 {
+ sb = s.removeBlock(sb)
+ } else {
+ sb = s.next(sb)
+ }
+ xb = x.next(xb)
+ }
+ }
+
+ for xb != &none { // append the tail of x to s
+ sb = s.insertBlockBefore(sb)
+ sb.offset = xb.offset
+ sb.bits = xb.bits
+ sb = s.next(sb)
+ xb = x.next(xb)
+ }
+}
+
+// SymmetricDifference sets s to the symmetric difference x ∆ y.
+func (s *Sparse) SymmetricDifference(x, y *Sparse) {
+ switch {
+ case x == y:
+ s.Clear()
+ return
+ case s == x:
+ s.SymmetricDifferenceWith(y)
+ return
+ case s == y:
+ s.SymmetricDifferenceWith(x)
+ return
+ }
+
+ sb := s.first()
+ xb := x.first()
+ yb := y.first()
+ for xb != &none && yb != &none {
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ switch {
+ case yb.offset < xb.offset:
+ sb.offset = yb.offset
+ sb.bits = yb.bits
+ sb = s.next(sb)
+ yb = y.next(yb)
+ case xb.offset < yb.offset:
+ sb.offset = xb.offset
+ sb.bits = xb.bits
+ sb = s.next(sb)
+ xb = x.next(xb)
+ default:
+ var sum word
+ for i := range sb.bits {
+ r := xb.bits[i] ^ yb.bits[i]
+ sb.bits[i] = r
+ sum |= r
+ }
+ if sum != 0 {
+ sb.offset = xb.offset
+ sb = s.next(sb)
+ }
+ xb = x.next(xb)
+ yb = y.next(yb)
+ }
+ }
+
+ for xb != &none { // append the tail of x to s
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ sb.offset = xb.offset
+ sb.bits = xb.bits
+ sb = s.next(sb)
+ xb = x.next(xb)
+ }
+
+ for yb != &none { // append the tail of y to s
+ if sb == &none {
+ sb = s.insertBlockBefore(sb)
+ }
+ sb.offset = yb.offset
+ sb.bits = yb.bits
+ sb = s.next(sb)
+ yb = y.next(yb)
+ }
+
+ s.discardTail(sb)
+}
+
+// SubsetOf reports whether s ∖ x = ∅.
+func (s *Sparse) SubsetOf(x *Sparse) bool {
+ if s == x {
+ return true
+ }
+
+ sb := s.first()
+ xb := x.first()
+ for sb != &none {
+ switch {
+ case xb == &none || xb.offset > sb.offset:
+ return false
+ case xb.offset < sb.offset:
+ xb = x.next(xb)
+ default:
+ for i := range sb.bits {
+ if sb.bits[i]&^xb.bits[i] != 0 {
+ return false
+ }
+ }
+ sb = s.next(sb)
+ xb = x.next(xb)
+ }
+ }
+ return true
+}
+
+// Equals reports whether the sets s and t have the same elements.
+func (s *Sparse) Equals(t *Sparse) bool {
+ if s == t {
+ return true
+ }
+ sb := s.first()
+ tb := t.first()
+ for {
+ switch {
+ case sb == &none && tb == &none:
+ return true
+ case sb == &none || tb == &none:
+ return false
+ case sb.offset != tb.offset:
+ return false
+ case sb.bits != tb.bits:
+ return false
+ }
+
+ sb = s.next(sb)
+ tb = t.next(tb)
+ }
+}
+
+// String returns a human-readable description of the set s.
+func (s *Sparse) String() string {
+ var buf bytes.Buffer
+ buf.WriteByte('{')
+ s.forEach(func(x int) {
+ if buf.Len() > 1 {
+ buf.WriteByte(' ')
+ }
+ fmt.Fprintf(&buf, "%d", x)
+ })
+ buf.WriteByte('}')
+ return buf.String()
+}
+
+// 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"
+ }
+
+ 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) {
+ if x >= 0 {
+ x += len(".")
+ }
+ b[radix-x] = '1'
+ })
+ return string(b)
+}
+
+// GoString returns a string showing the internal representation of
+// the set s.
+//
+func (s *Sparse) GoString() string {
+ var buf bytes.Buffer
+ for b := s.first(); b != &none; b = s.next(b) {
+ fmt.Fprintf(&buf, "block %p {offset=%d next=%p prev=%p",
+ b, b.offset, b.next, b.prev)
+ for _, w := range b.bits {
+ fmt.Fprintf(&buf, " 0%016x", w)
+ }
+ fmt.Fprintf(&buf, "}\n")
+ }
+ return buf.String()
+}
+
+// AppendTo returns the result of appending the elements of s to slice
+// in order.
+func (s *Sparse) AppendTo(slice []int) []int {
+ s.forEach(func(x int) {
+ slice = append(slice, x)
+ })
+ return slice
+}
+
+// -- Testing/debugging ------------------------------------------------
+
+// check returns an error if the representation invariants of s are violated.
+func (s *Sparse) check() error {
+ s.init()
+ if s.root.empty() {
+ // An empty set must have only the root block with offset MaxInt.
+ if s.root.next != &s.root {
+ return fmt.Errorf("multiple blocks with empty root block")
+ }
+ if s.root.offset != MaxInt {
+ return fmt.Errorf("empty set has offset %d, should be MaxInt", s.root.offset)
+ }
+ return nil
+ }
+ for b := s.first(); ; b = s.next(b) {
+ if b.offset%bitsPerBlock != 0 {
+ return fmt.Errorf("bad offset modulo: %d", b.offset)
+ }
+ if b.empty() {
+ return fmt.Errorf("empty block")
+ }
+ if b.prev.next != b {
+ return fmt.Errorf("bad prev.next link")
+ }
+ if b.next.prev != b {
+ return fmt.Errorf("bad next.prev link")
+ }
+ if b.next == &s.root {
+ break
+ }
+ if b.offset >= b.next.offset {
+ return fmt.Errorf("bad offset order: b.offset=%d, b.next.offset=%d",
+ b.offset, b.next.offset)
+ }
+ }
+ return nil
+}