| // 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. |
| _ = (interface{}(nil)).(to_copy_a_sparse_you_must_call_its_Copy_method) |
| } |
| } |
| |
| func (s *Sparse) first() *block { |
| s.init() |
| if s.root.offset == MaxInt { |
| return &none |
| } |
| return &s.root |
| } |
| |
| // next returns the next block in the list, or end if b is the last block. |
| func (s *Sparse) next(b *block) *block { |
| if b.next == &s.root { |
| return &none |
| } |
| return b.next |
| } |
| |
| // prev returns the previous block in the list, or end if b is the first block. |
| func (s *Sparse) prev(b *block) *block { |
| if b.prev == &s.root { |
| return &none |
| } |
| return b.prev |
| } |
| |
| // IsEmpty reports whether the set s is empty. |
| func (s *Sparse) IsEmpty() bool { |
| return s.root.next == nil || s.root.offset == MaxInt |
| } |
| |
| // Len returns the number of elements in the set s. |
| func (s *Sparse) Len() int { |
| var l int |
| for b := s.first(); b != &none; b = s.next(b) { |
| l += b.len() |
| } |
| return l |
| } |
| |
| // Max returns the maximum element of the set s, or MinInt if s is empty. |
| func (s *Sparse) Max() int { |
| if s.IsEmpty() { |
| return MinInt |
| } |
| return s.root.prev.max() |
| } |
| |
| // Min returns the minimum element of the set s, or MaxInt if s is empty. |
| func (s *Sparse) Min() int { |
| if s.IsEmpty() { |
| return MaxInt |
| } |
| return s.root.min(false) |
| } |
| |
| // LowerBound returns the smallest element >= x, or MaxInt if there is no such |
| // element. |
| func (s *Sparse) LowerBound(x int) int { |
| offset, i := offsetAndBitIndex(x) |
| for b := s.first(); b != &none; b = s.next(b) { |
| if b.offset > offset { |
| return b.min(false) |
| } |
| if b.offset == offset { |
| if y, ok := b.lowerBound(i); ok { |
| return y |
| } |
| } |
| } |
| return MaxInt |
| } |
| |
| // block returns the block that would contain offset, |
| // or nil if s contains no such block. |
| // Precondition: offset is a multiple of bitsPerBlock. |
| func (s *Sparse) block(offset int) *block { |
| for b := s.first(); b != &none && b.offset <= offset; b = s.next(b) { |
| if b.offset == offset { |
| return b |
| } |
| } |
| return nil |
| } |
| |
| // Insert adds x to the set s, and reports whether the set grew. |
| func (s *Sparse) Insert(x int) bool { |
| offset, i := offsetAndBitIndex(x) |
| |
| b := s.first() |
| for ; b != &none && b.offset <= offset; b = s.next(b) { |
| if b.offset == offset { |
| return b.insert(i) |
| } |
| } |
| |
| // Insert new block before b. |
| new := s.insertBlockBefore(b) |
| new.offset = offset |
| return new.insert(i) |
| } |
| |
| // removeBlock removes a block and returns the block that followed it (or end if |
| // it was the last block). |
| func (s *Sparse) removeBlock(b *block) *block { |
| if b != &s.root { |
| b.prev.next = b.next |
| b.next.prev = b.prev |
| if b.next == &s.root { |
| return &none |
| } |
| return b.next |
| } |
| |
| first := s.root.next |
| if first == &s.root { |
| // This was the only block. |
| s.Clear() |
| return &none |
| } |
| s.root.offset = first.offset |
| s.root.bits = first.bits |
| if first.next == &s.root { |
| // Single block remaining. |
| s.root.next = &s.root |
| s.root.prev = &s.root |
| } else { |
| s.root.next = first.next |
| first.next.prev = &s.root |
| } |
| return &s.root |
| } |
| |
| // Remove removes x from the set s, and reports whether the set shrank. |
| func (s *Sparse) Remove(x int) bool { |
| offset, i := offsetAndBitIndex(x) |
| if b := s.block(offset); b != nil { |
| if !b.remove(i) { |
| return false |
| } |
| if b.empty() { |
| s.removeBlock(b) |
| } |
| return true |
| } |
| return false |
| } |
| |
| // Clear removes all elements from the set s. |
| func (s *Sparse) Clear() { |
| s.root = block{ |
| offset: MaxInt, |
| next: &s.root, |
| prev: &s.root, |
| } |
| } |
| |
| // If set s is non-empty, TakeMin sets *p to the minimum element of |
| // the set s, removes that element from the set and returns true. |
| // Otherwise, it returns false and *p is undefined. |
| // |
| // This method may be used for iteration over a worklist like so: |
| // |
| // var x int |
| // for worklist.TakeMin(&x) { use(x) } |
| func (s *Sparse) TakeMin(p *int) bool { |
| if s.IsEmpty() { |
| return false |
| } |
| *p = s.root.min(true) |
| if s.root.empty() { |
| s.removeBlock(&s.root) |
| } |
| return true |
| } |
| |
| // Has reports whether x is an element of the set s. |
| func (s *Sparse) Has(x int) bool { |
| offset, i := offsetAndBitIndex(x) |
| if b := s.block(offset); b != nil { |
| return b.has(i) |
| } |
| return false |
| } |
| |
| // forEach applies function f to each element of the set s in order. |
| // |
| // f must not mutate s. Consequently, forEach is not safe to expose |
| // to clients. In any case, using "range s.AppendTo()" allows more |
| // natural control flow with continue/break/return. |
| func (s *Sparse) forEach(f func(int)) { |
| for b := s.first(); b != &none; b = s.next(b) { |
| b.forEach(f) |
| } |
| } |
| |
| // Copy sets s to the value of x. |
| func (s *Sparse) Copy(x *Sparse) { |
| if s == x { |
| return |
| } |
| |
| xb := x.first() |
| sb := s.first() |
| for xb != &none { |
| if sb == &none { |
| sb = s.insertBlockBefore(sb) |
| } |
| sb.offset = xb.offset |
| sb.bits = xb.bits |
| xb = x.next(xb) |
| sb = s.next(sb) |
| } |
| s.discardTail(sb) |
| } |
| |
| // insertBlockBefore returns a new block, inserting it before next. |
| // If next is the root, the root is replaced. If next is end, the block is |
| // inserted at the end. |
| func (s *Sparse) insertBlockBefore(next *block) *block { |
| if s.IsEmpty() { |
| if next != &none { |
| panic("BUG: passed block with empty set") |
| } |
| return &s.root |
| } |
| |
| if next == &s.root { |
| // Special case: we need to create a new block that will become the root |
| // block.The old root block becomes the second block. |
| second := s.root |
| s.root = block{ |
| next: &second, |
| } |
| if second.next == &s.root { |
| s.root.prev = &second |
| } else { |
| s.root.prev = second.prev |
| second.next.prev = &second |
| second.prev = &s.root |
| } |
| return &s.root |
| } |
| if next == &none { |
| // Insert before root. |
| next = &s.root |
| } |
| b := new(block) |
| b.next = next |
| b.prev = next.prev |
| b.prev.next = b |
| next.prev = b |
| return b |
| } |
| |
| // discardTail removes block b and all its successors from s. |
| func (s *Sparse) discardTail(b *block) { |
| if b != &none { |
| if b == &s.root { |
| s.Clear() |
| } else { |
| b.prev.next = &s.root |
| s.root.prev = b.prev |
| } |
| } |
| } |
| |
| // IntersectionWith sets s to the intersection s ∩ x. |
| func (s *Sparse) IntersectionWith(x *Sparse) { |
| if s == x { |
| return |
| } |
| |
| xb := x.first() |
| sb := s.first() |
| for xb != &none && sb != &none { |
| switch { |
| case xb.offset < sb.offset: |
| xb = x.next(xb) |
| |
| case xb.offset > sb.offset: |
| sb = s.removeBlock(sb) |
| |
| default: |
| var sum word |
| for i := range sb.bits { |
| r := xb.bits[i] & sb.bits[i] |
| sb.bits[i] = r |
| sum |= r |
| } |
| if sum != 0 { |
| sb = s.next(sb) |
| } else { |
| // sb will be overwritten or removed |
| } |
| |
| xb = x.next(xb) |
| } |
| } |
| |
| s.discardTail(sb) |
| } |
| |
| // Intersection sets s to the intersection x ∩ y. |
| func (s *Sparse) Intersection(x, y *Sparse) { |
| switch { |
| case s == x: |
| s.IntersectionWith(y) |
| return |
| case s == y: |
| s.IntersectionWith(x) |
| return |
| case x == y: |
| s.Copy(x) |
| return |
| } |
| |
| xb := x.first() |
| yb := y.first() |
| sb := s.first() |
| for xb != &none && yb != &none { |
| switch { |
| case xb.offset < yb.offset: |
| xb = x.next(xb) |
| continue |
| case xb.offset > yb.offset: |
| yb = y.next(yb) |
| continue |
| } |
| |
| if sb == &none { |
| sb = s.insertBlockBefore(sb) |
| } |
| sb.offset = xb.offset |
| |
| var sum word |
| for i := range sb.bits { |
| r := xb.bits[i] & yb.bits[i] |
| sb.bits[i] = r |
| sum |= r |
| } |
| if sum != 0 { |
| sb = s.next(sb) |
| } else { |
| // sb will be overwritten or removed |
| } |
| |
| xb = x.next(xb) |
| yb = y.next(yb) |
| } |
| |
| s.discardTail(sb) |
| } |
| |
| // Intersects reports whether s ∩ x ≠ ∅. |
| func (s *Sparse) Intersects(x *Sparse) bool { |
| sb := s.first() |
| xb := x.first() |
| for sb != &none && xb != &none { |
| switch { |
| case xb.offset < sb.offset: |
| xb = x.next(xb) |
| case xb.offset > sb.offset: |
| sb = s.next(sb) |
| default: |
| for i := range sb.bits { |
| if sb.bits[i]&xb.bits[i] != 0 { |
| return true |
| } |
| } |
| sb = s.next(sb) |
| xb = x.next(xb) |
| } |
| } |
| return false |
| } |
| |
| // UnionWith sets s to the union s ∪ x, and reports whether s grew. |
| func (s *Sparse) UnionWith(x *Sparse) bool { |
| if s == x { |
| return false |
| } |
| |
| var changed bool |
| xb := x.first() |
| sb := s.first() |
| for xb != &none { |
| if sb != &none && sb.offset == xb.offset { |
| for i := range xb.bits { |
| 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. |
| 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 |
| } |