803 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			803 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
// 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
 | 
						||
 | 
						||
// TODO(adonovan):
 | 
						||
// - Add SymmetricDifference(x, y *Sparse), i.e. x ∆ y.
 | 
						||
// - 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): experiment with making the root block indirect (nil
 | 
						||
// iff IsEmpty).  This would reduce the memory usage when empty and
 | 
						||
// might simplify the aliasing invariants.
 | 
						||
 | 
						||
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.
 | 
						||
	// In a non-empty set, root.next points to the first block and
 | 
						||
	// root.prev to the last.
 | 
						||
	// root.offset and root.bits are unused.
 | 
						||
	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")
 | 
						||
}
 | 
						||
 | 
						||
// 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 --------------------------------------------------------------
 | 
						||
 | 
						||
// start returns the root's next block, which is the root block
 | 
						||
// (if s.IsEmpty()) or the first true block otherwise.
 | 
						||
// start has the side effect of ensuring that s is properly
 | 
						||
// initialized.
 | 
						||
//
 | 
						||
func (s *Sparse) start() *block {
 | 
						||
	root := &s.root
 | 
						||
	if root.next == nil {
 | 
						||
		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.
 | 
						||
		panic("A Sparse has been copied without (*Sparse).Copy()")
 | 
						||
	}
 | 
						||
 | 
						||
	return root.next
 | 
						||
}
 | 
						||
 | 
						||
// IsEmpty reports whether the set s is empty.
 | 
						||
func (s *Sparse) IsEmpty() bool {
 | 
						||
	return s.start() == &s.root
 | 
						||
}
 | 
						||
 | 
						||
// Len returns the number of elements in the set s.
 | 
						||
func (s *Sparse) Len() int {
 | 
						||
	var l int
 | 
						||
	for b := s.start(); b != &s.root; b = b.next {
 | 
						||
		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.next.min(false)
 | 
						||
}
 | 
						||
 | 
						||
// block returns the block that would contain offset,
 | 
						||
// or nil if s contains no such block.
 | 
						||
//
 | 
						||
func (s *Sparse) block(offset int) *block {
 | 
						||
	b := s.start()
 | 
						||
	for b != &s.root && b.offset <= offset {
 | 
						||
		if b.offset == offset {
 | 
						||
			return b
 | 
						||
		}
 | 
						||
		b = b.next
 | 
						||
	}
 | 
						||
	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.start()
 | 
						||
	for b != &s.root && b.offset <= offset {
 | 
						||
		if b.offset == offset {
 | 
						||
			return b.insert(i)
 | 
						||
		}
 | 
						||
		b = b.next
 | 
						||
	}
 | 
						||
 | 
						||
	// Insert new block before b.
 | 
						||
	new := &block{offset: offset}
 | 
						||
	new.next = b
 | 
						||
	new.prev = b.prev
 | 
						||
	new.prev.next = new
 | 
						||
	new.next.prev = new
 | 
						||
	return new.insert(i)
 | 
						||
}
 | 
						||
 | 
						||
func (s *Sparse) removeBlock(b *block) {
 | 
						||
	b.prev.next = b.next
 | 
						||
	b.next.prev = b.prev
 | 
						||
}
 | 
						||
 | 
						||
// 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.next = &s.root
 | 
						||
	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 {
 | 
						||
	head := s.start()
 | 
						||
	if head == &s.root {
 | 
						||
		return false
 | 
						||
	}
 | 
						||
	*p = head.min(true)
 | 
						||
	if head.empty() {
 | 
						||
		s.removeBlock(head)
 | 
						||
	}
 | 
						||
	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.start(); b != &s.root; b = b.next {
 | 
						||
		b.forEach(f)
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
// Copy sets s to the value of x.
 | 
						||
func (s *Sparse) Copy(x *Sparse) {
 | 
						||
	if s == x {
 | 
						||
		return
 | 
						||
	}
 | 
						||
 | 
						||
	xb := x.start()
 | 
						||
	sb := s.start()
 | 
						||
	for xb != &x.root {
 | 
						||
		if sb == &s.root {
 | 
						||
			sb = s.insertBlockBefore(sb)
 | 
						||
		}
 | 
						||
		sb.offset = xb.offset
 | 
						||
		sb.bits = xb.bits
 | 
						||
		xb = xb.next
 | 
						||
		sb = sb.next
 | 
						||
	}
 | 
						||
	s.discardTail(sb)
 | 
						||
}
 | 
						||
 | 
						||
// insertBlockBefore returns a new block, inserting it before next.
 | 
						||
func (s *Sparse) insertBlockBefore(next *block) *block {
 | 
						||
	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 != &s.root {
 | 
						||
		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.start()
 | 
						||
	sb := s.start()
 | 
						||
	for xb != &x.root && sb != &s.root {
 | 
						||
		switch {
 | 
						||
		case xb.offset < sb.offset:
 | 
						||
			xb = xb.next
 | 
						||
 | 
						||
		case xb.offset > sb.offset:
 | 
						||
			sb = sb.next
 | 
						||
			s.removeBlock(sb.prev)
 | 
						||
 | 
						||
		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 = sb.next
 | 
						||
			} else {
 | 
						||
				// sb will be overwritten or removed
 | 
						||
			}
 | 
						||
 | 
						||
			xb = xb.next
 | 
						||
		}
 | 
						||
	}
 | 
						||
 | 
						||
	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.start()
 | 
						||
	yb := y.start()
 | 
						||
	sb := s.start()
 | 
						||
	for xb != &x.root && yb != &y.root {
 | 
						||
		switch {
 | 
						||
		case xb.offset < yb.offset:
 | 
						||
			xb = xb.next
 | 
						||
			continue
 | 
						||
		case xb.offset > yb.offset:
 | 
						||
			yb = yb.next
 | 
						||
			continue
 | 
						||
		}
 | 
						||
 | 
						||
		if sb == &s.root {
 | 
						||
			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 = sb.next
 | 
						||
		} else {
 | 
						||
			// sb will be overwritten or removed
 | 
						||
		}
 | 
						||
 | 
						||
		xb = xb.next
 | 
						||
		yb = yb.next
 | 
						||
	}
 | 
						||
 | 
						||
	s.discardTail(sb)
 | 
						||
}
 | 
						||
 | 
						||
// 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.start()
 | 
						||
	sb := s.start()
 | 
						||
	for xb != &x.root {
 | 
						||
		if sb != &s.root && 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 = xb.next
 | 
						||
		} else if sb == &s.root || sb.offset > xb.offset {
 | 
						||
			sb = s.insertBlockBefore(sb)
 | 
						||
			sb.offset = xb.offset
 | 
						||
			sb.bits = xb.bits
 | 
						||
			changed = true
 | 
						||
 | 
						||
			xb = xb.next
 | 
						||
		}
 | 
						||
		sb = sb.next
 | 
						||
	}
 | 
						||
	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.start()
 | 
						||
	yb := y.start()
 | 
						||
	sb := s.start()
 | 
						||
	for xb != &x.root || yb != &y.root {
 | 
						||
		if sb == &s.root {
 | 
						||
			sb = s.insertBlockBefore(sb)
 | 
						||
		}
 | 
						||
		switch {
 | 
						||
		case yb == &y.root || (xb != &x.root && xb.offset < yb.offset):
 | 
						||
			sb.offset = xb.offset
 | 
						||
			sb.bits = xb.bits
 | 
						||
			xb = xb.next
 | 
						||
 | 
						||
		case xb == &x.root || (yb != &y.root && yb.offset < xb.offset):
 | 
						||
			sb.offset = yb.offset
 | 
						||
			sb.bits = yb.bits
 | 
						||
			yb = yb.next
 | 
						||
 | 
						||
		default:
 | 
						||
			sb.offset = xb.offset
 | 
						||
			for i := range xb.bits {
 | 
						||
				sb.bits[i] = xb.bits[i] | yb.bits[i]
 | 
						||
			}
 | 
						||
			xb = xb.next
 | 
						||
			yb = yb.next
 | 
						||
		}
 | 
						||
		sb = sb.next
 | 
						||
	}
 | 
						||
 | 
						||
	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.start()
 | 
						||
	sb := s.start()
 | 
						||
	for xb != &x.root && sb != &s.root {
 | 
						||
		switch {
 | 
						||
		case xb.offset > sb.offset:
 | 
						||
			sb = sb.next
 | 
						||
 | 
						||
		case xb.offset < sb.offset:
 | 
						||
			xb = xb.next
 | 
						||
 | 
						||
		default:
 | 
						||
			var sum word
 | 
						||
			for i := range sb.bits {
 | 
						||
				r := sb.bits[i] & ^xb.bits[i]
 | 
						||
				sb.bits[i] = r
 | 
						||
				sum |= r
 | 
						||
			}
 | 
						||
			sb = sb.next
 | 
						||
			xb = xb.next
 | 
						||
 | 
						||
			if sum == 0 {
 | 
						||
				s.removeBlock(sb.prev)
 | 
						||
			}
 | 
						||
		}
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
// 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.start()
 | 
						||
	yb := y.start()
 | 
						||
	sb := s.start()
 | 
						||
	for xb != &x.root && yb != &y.root {
 | 
						||
		if xb.offset > yb.offset {
 | 
						||
			// y has block, x has none
 | 
						||
			yb = yb.next
 | 
						||
			continue
 | 
						||
		}
 | 
						||
 | 
						||
		if sb == &s.root {
 | 
						||
			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 = sb.next
 | 
						||
 | 
						||
		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 = sb.next
 | 
						||
			} else {
 | 
						||
				// sb will be overrwritten or removed
 | 
						||
			}
 | 
						||
 | 
						||
			yb = yb.next
 | 
						||
		}
 | 
						||
		xb = xb.next
 | 
						||
	}
 | 
						||
 | 
						||
	for xb != &x.root {
 | 
						||
		if sb == &s.root {
 | 
						||
			sb = s.insertBlockBefore(sb)
 | 
						||
		}
 | 
						||
		sb.offset = xb.offset
 | 
						||
		sb.bits = xb.bits
 | 
						||
		sb = sb.next
 | 
						||
 | 
						||
		xb = xb.next
 | 
						||
	}
 | 
						||
 | 
						||
	s.discardTail(sb)
 | 
						||
}
 | 
						||
 | 
						||
// 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.start()
 | 
						||
	tb := t.start()
 | 
						||
	for {
 | 
						||
		switch {
 | 
						||
		case sb == &s.root && tb == &t.root:
 | 
						||
			return true
 | 
						||
		case sb == &s.root || tb == &t.root:
 | 
						||
			return false
 | 
						||
		case sb.offset != tb.offset:
 | 
						||
			return false
 | 
						||
		case sb.bits != tb.bits:
 | 
						||
			return false
 | 
						||
		}
 | 
						||
 | 
						||
		sb = sb.next
 | 
						||
		tb = tb.next
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
// 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.start(); b != &s.root; b = b.next {
 | 
						||
		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 {
 | 
						||
	if !s.root.empty() {
 | 
						||
		return fmt.Errorf("non-empty root block")
 | 
						||
	}
 | 
						||
	if s.root.offset != 0 {
 | 
						||
		return fmt.Errorf("root block has non-zero offset %d", s.root.offset)
 | 
						||
	}
 | 
						||
	for b := s.start(); b != &s.root; b = b.next {
 | 
						||
		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.prev != &s.root {
 | 
						||
			if b.offset <= b.prev.offset {
 | 
						||
				return fmt.Errorf("bad offset order: b.offset=%d, prev.offset=%d",
 | 
						||
					b.offset, b.prev.offset)
 | 
						||
			}
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return nil
 | 
						||
}
 |