// 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"
	"math/bits"
)

// 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
)

// popcount returns the number of set bits in w.
func popcount(x word) int {
	// Avoid OnesCount(uint): don't assume uint = uintptr.
	if bitsPerWord == 32 {
		return bits.OnesCount32(uint32(x))
	} else {
		return bits.OnesCount64(uint64(x))
	}
}

// nlz returns the number of leading zeros of x.
func nlz(x word) int {
	// Avoid LeadingZeros(uint): don't assume uint = uintptr.
	if bitsPerWord == 32 {
		return bits.LeadingZeros32(uint32(x))
	} else {
		return bits.LeadingZeros64(uint64(x))
	}
}

// ntz returns the number of trailing zeros of x.
func ntz(x word) int {
	// Avoid TrailingZeros(uint): don't assume uint = uintptr.
	if bitsPerWord == 32 {
		return bits.TrailingZeros32(uint32(x))
	} else {
		return bits.TrailingZeros64(uint64(x))
	}
}

// -- 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 + 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.
		_ = (any(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
}

// 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 {
				union := sb.bits[i] | xb.bits[i]
				if sb.bits[i] != union {
					sb.bits[i] = union
					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.
// (unused; retained for debugging)
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
}
