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