2018-03-13 07:32:44 +03:00
|
|
|
|
// 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.
|
2018-03-13 08:24:04 +03:00
|
|
|
|
//
|
|
|
|
|
// 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).
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 07:32:44 +03:00
|
|
|
|
// 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 --------------------------------------------------------------
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// 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() {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
root := &s.root
|
|
|
|
|
if root.next == nil {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
root.offset = MaxInt
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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.
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// 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)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
}
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
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
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsEmpty reports whether the set s is empty.
|
|
|
|
|
func (s *Sparse) IsEmpty() bool {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
return s.root.next == nil || s.root.offset == MaxInt
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Len returns the number of elements in the set s.
|
|
|
|
|
func (s *Sparse) Len() int {
|
|
|
|
|
var l int
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for b := s.first(); b != &none; b = s.next(b) {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
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
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// block returns the block that would contain offset,
|
|
|
|
|
// or nil if s contains no such block.
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// Precondition: offset is a multiple of bitsPerBlock.
|
2018-03-13 07:32:44 +03:00
|
|
|
|
func (s *Sparse) block(offset int) *block {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for b := s.first(); b != &none && b.offset <= offset; b = s.next(b) {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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)
|
2018-03-13 08:24:04 +03:00
|
|
|
|
|
|
|
|
|
b := s.first()
|
|
|
|
|
for ; b != &none && b.offset <= offset; b = s.next(b) {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
if b.offset == offset {
|
|
|
|
|
return b.insert(i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert new block before b.
|
2018-03-13 08:24:04 +03:00
|
|
|
|
new := s.insertBlockBefore(b)
|
|
|
|
|
new.offset = offset
|
2018-03-13 07:32:44 +03:00
|
|
|
|
return new.insert(i)
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// 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
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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() {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
s.root = block{
|
|
|
|
|
offset: MaxInt,
|
|
|
|
|
next: &s.root,
|
|
|
|
|
prev: &s.root,
|
|
|
|
|
}
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
if s.IsEmpty() {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
return false
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
*p = s.root.min(true)
|
|
|
|
|
if s.root.empty() {
|
|
|
|
|
s.removeBlock(&s.root)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
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)) {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for b := s.first(); b != &none; b = s.next(b) {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
b.forEach(f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy sets s to the value of x.
|
|
|
|
|
func (s *Sparse) Copy(x *Sparse) {
|
|
|
|
|
if s == x {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb := x.first()
|
|
|
|
|
sb := s.first()
|
|
|
|
|
for xb != &none {
|
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
}
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
sb.bits = xb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
s.discardTail(sb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// insertBlockBefore returns a new block, inserting it before next.
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// If next is the root, the root is replaced. If next is end, the block is
|
|
|
|
|
// inserted at the end.
|
2018-03-13 07:32:44 +03:00
|
|
|
|
func (s *Sparse) insertBlockBefore(next *block) *block {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
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
|
|
|
|
|
}
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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) {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
if b != &none {
|
|
|
|
|
if b == &s.root {
|
|
|
|
|
s.Clear()
|
|
|
|
|
} else {
|
|
|
|
|
b.prev.next = &s.root
|
|
|
|
|
s.root.prev = b.prev
|
|
|
|
|
}
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IntersectionWith sets s to the intersection s ∩ x.
|
|
|
|
|
func (s *Sparse) IntersectionWith(x *Sparse) {
|
|
|
|
|
if s == x {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb := x.first()
|
|
|
|
|
sb := s.first()
|
|
|
|
|
for xb != &none && sb != &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
switch {
|
|
|
|
|
case xb.offset < sb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
|
|
|
|
case xb.offset > sb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.removeBlock(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
|
|
|
|
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 {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
} else {
|
|
|
|
|
// sb will be overwritten or removed
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb := x.first()
|
|
|
|
|
yb := y.first()
|
|
|
|
|
sb := s.first()
|
|
|
|
|
for xb != &none && yb != &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
switch {
|
|
|
|
|
case xb.offset < yb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
continue
|
|
|
|
|
case xb.offset > yb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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 {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
} else {
|
|
|
|
|
// sb will be overwritten or removed
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.discardTail(sb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Intersects reports whether s ∩ x ≠ ∅.
|
|
|
|
|
func (s *Sparse) Intersects(x *Sparse) bool {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb := s.first()
|
|
|
|
|
xb := x.first()
|
|
|
|
|
for sb != &none && xb != &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
switch {
|
|
|
|
|
case xb.offset < sb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
case xb.offset > sb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
default:
|
|
|
|
|
for i := range sb.bits {
|
|
|
|
|
if sb.bits[i]&xb.bits[i] != 0 {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb := x.first()
|
|
|
|
|
sb := s.first()
|
|
|
|
|
for xb != &none {
|
|
|
|
|
if sb != &none && sb.offset == xb.offset {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
for i := range xb.bits {
|
|
|
|
|
if sb.bits[i] != xb.bits[i] {
|
|
|
|
|
sb.bits[i] |= xb.bits[i]
|
|
|
|
|
changed = true
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
|
|
|
|
} else if sb == &none || sb.offset > xb.offset {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
sb.bits = xb.bits
|
|
|
|
|
changed = true
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb := x.first()
|
|
|
|
|
yb := y.first()
|
|
|
|
|
sb := s.first()
|
|
|
|
|
for xb != &none || yb != &none {
|
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
}
|
|
|
|
|
switch {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
case yb == &none || (xb != &none && xb.offset < yb.offset):
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
sb.bits = xb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
case xb == &none || (yb != &none && yb.offset < xb.offset):
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb.offset = yb.offset
|
|
|
|
|
sb.bits = yb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
for i := range xb.bits {
|
|
|
|
|
sb.bits[i] = xb.bits[i] | yb.bits[i]
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.discardTail(sb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DifferenceWith sets s to the difference s ∖ x.
|
|
|
|
|
func (s *Sparse) DifferenceWith(x *Sparse) {
|
|
|
|
|
if s == x {
|
|
|
|
|
s.Clear()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb := x.first()
|
|
|
|
|
sb := s.first()
|
|
|
|
|
for xb != &none && sb != &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
switch {
|
|
|
|
|
case xb.offset > sb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
|
|
|
|
case xb.offset < sb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
|
|
|
|
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 {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.removeBlock(sb)
|
|
|
|
|
} else {
|
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb := x.first()
|
|
|
|
|
yb := y.first()
|
|
|
|
|
sb := s.first()
|
|
|
|
|
for xb != &none && yb != &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
if xb.offset > yb.offset {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// y has block, x has &none
|
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
}
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
case xb.offset < yb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
// x has block, y has &none
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb.bits = xb.bits
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
|
|
|
|
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 {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
} else {
|
|
|
|
|
// sb will be overwritten or removed
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for xb != &none {
|
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
}
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
sb.bits = xb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.discardTail(sb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SymmetricDifferenceWith sets s to the symmetric difference s ∆ x.
|
|
|
|
|
func (s *Sparse) SymmetricDifferenceWith(x *Sparse) {
|
|
|
|
|
if s == x {
|
|
|
|
|
s.Clear()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb := s.first()
|
|
|
|
|
xb := x.first()
|
|
|
|
|
for xb != &none && sb != &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
switch {
|
|
|
|
|
case sb.offset < xb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
case xb.offset < sb.offset:
|
|
|
|
|
nb := s.insertBlockBefore(sb)
|
|
|
|
|
nb.offset = xb.offset
|
|
|
|
|
nb.bits = xb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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 {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.removeBlock(sb)
|
|
|
|
|
} else {
|
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for xb != &none { // append the tail of x to s
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
sb.bits = xb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb := s.first()
|
|
|
|
|
xb := x.first()
|
|
|
|
|
yb := y.first()
|
|
|
|
|
for xb != &none && yb != &none {
|
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
}
|
|
|
|
|
switch {
|
|
|
|
|
case yb.offset < xb.offset:
|
|
|
|
|
sb.offset = yb.offset
|
|
|
|
|
sb.bits = yb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
case xb.offset < yb.offset:
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
sb.bits = xb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for xb != &none { // append the tail of x to s
|
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
}
|
|
|
|
|
sb.offset = xb.offset
|
|
|
|
|
sb.bits = xb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for yb != &none { // append the tail of y to s
|
|
|
|
|
if sb == &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
sb = s.insertBlockBefore(sb)
|
|
|
|
|
}
|
|
|
|
|
sb.offset = yb.offset
|
|
|
|
|
sb.bits = yb.bits
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
yb = y.next(yb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.discardTail(sb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SubsetOf reports whether s ∖ x = ∅.
|
|
|
|
|
func (s *Sparse) SubsetOf(x *Sparse) bool {
|
|
|
|
|
if s == x {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb := s.first()
|
|
|
|
|
xb := x.first()
|
|
|
|
|
for sb != &none {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
switch {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
case xb == &none || xb.offset > sb.offset:
|
2018-03-13 07:32:44 +03:00
|
|
|
|
return false
|
|
|
|
|
case xb.offset < sb.offset:
|
2018-03-13 08:24:04 +03:00
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
default:
|
|
|
|
|
for i := range sb.bits {
|
|
|
|
|
if sb.bits[i]&^xb.bits[i] != 0 {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
xb = x.next(xb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb := s.first()
|
|
|
|
|
tb := t.first()
|
2018-03-13 07:32:44 +03:00
|
|
|
|
for {
|
|
|
|
|
switch {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
case sb == &none && tb == &none:
|
2018-03-13 07:32:44 +03:00
|
|
|
|
return true
|
2018-03-13 08:24:04 +03:00
|
|
|
|
case sb == &none || tb == &none:
|
2018-03-13 07:32:44 +03:00
|
|
|
|
return false
|
|
|
|
|
case sb.offset != tb.offset:
|
|
|
|
|
return false
|
|
|
|
|
case sb.bits != tb.bits:
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 08:24:04 +03:00
|
|
|
|
sb = s.next(sb)
|
|
|
|
|
tb = t.next(tb)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for b := s.first(); b != &none; b = s.next(b) {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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 {
|
2018-03-13 08:24:04 +03:00
|
|
|
|
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
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
for b := s.first(); ; b = s.next(b) {
|
2018-03-13 07:32:44 +03:00
|
|
|
|
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")
|
|
|
|
|
}
|
2018-03-13 08:24:04 +03:00
|
|
|
|
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)
|
2018-03-13 07:32:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|