act/vendor/github.com/soniakeys/bits/bits.go

464 lines
10 KiB
Go
Raw Normal View History

// Copyright 2017 Sonia Keys
// License MIT: http://opensource.org/licenses/MIT
// Bits implements methods on a bit array type.
//
// The Bits type holds a fixed size array of bits, numbered consecutively
// from zero. Some set-like operations are possible, but the API is more
// array-like or register-like.
package bits
import (
"fmt"
mb "math/bits"
)
// Bits holds a fixed number of bits.
//
// Bit number 0 is stored in the LSB, or bit 0, of the word indexed at 0.
//
// When Num is not a multiple of 64, the last element of Bits will hold some
// bits beyond Num. These bits are undefined. They are not required to be
// zero but do not have any meaning. Bits methods are not required to leave
// them undisturbed.
type Bits struct {
Num int // number of bits
Bits []uint64
}
// New constructs a Bits value with the given number of bits.
//
// It panics if num is negative.
func New(num int) Bits {
if num < 0 {
panic("negative number of bits")
}
return Bits{num, make([]uint64, (num+63)>>6)}
}
// NewGivens constructs a Bits value with the given bits nums set to 1.
//
// The number of bits will be just enough to hold the largest bit value
// listed. That is, the number of bits will be the max bit number plus one.
//
// It panics if any bit number is negative.
func NewGivens(nums ...int) Bits {
max := -1
for _, p := range nums {
if p > max {
max = p
}
}
b := New(max + 1)
for _, p := range nums {
b.SetBit(p, 1)
}
return b
}
// AllOnes returns true if all Num bits are 1.
func (b Bits) AllOnes() bool {
last := len(b.Bits) - 1
for _, w := range b.Bits[:last] {
if w != ^uint64(0) {
return false
}
}
return ^b.Bits[last]<<uint(64*len(b.Bits)-b.Num) == 0
}
// AllZeros returns true if all Num bits are 0.
func (b Bits) AllZeros() bool {
last := len(b.Bits) - 1
for _, w := range b.Bits[:last] {
if w != 0 {
return false
}
}
return b.Bits[last]<<uint(64*len(b.Bits)-b.Num) == 0
}
// And sets z = x & y.
//
// It panics if x and y do not have the same Num.
func (z *Bits) And(x, y Bits) {
if x.Num != y.Num {
panic("arguments have different number of bits")
}
if z.Num != x.Num {
*z = New(x.Num)
}
for i, w := range y.Bits {
z.Bits[i] = x.Bits[i] & w
}
}
// AndNot sets z = x &^ y.
//
// It panics if x and y do not have the same Num.
func (z *Bits) AndNot(x, y Bits) {
if x.Num != y.Num {
panic("arguments have different number of bits")
}
if z.Num != x.Num {
*z = New(x.Num)
}
for i, w := range y.Bits {
z.Bits[i] = x.Bits[i] &^ w
}
}
// Bit returns the value of the n'th bit of receiver b.
func (b Bits) Bit(n int) int {
if n < 0 || n >= b.Num {
panic("bit number out of range")
}
return int(b.Bits[n>>6] >> uint(n&63) & 1)
}
// ClearAll sets all bits to 0.
func (b Bits) ClearAll() {
for i := range b.Bits {
b.Bits[i] = 0
}
}
// ClearBits sets the given bits to 0 in receiver b.
//
// Other bits of b are left unchanged.
//
// It panics if any bit number is out of range.
// That is, negative or >= the number of bits.
func (b Bits) ClearBits(nums ...int) {
for _, p := range nums {
b.SetBit(p, 0)
}
}
// Equal returns true if all Num bits of a and b are equal.
//
// It panics if a and b have different Num.
func (a Bits) Equal(b Bits) bool {
if a.Num != b.Num {
panic("receiver and argument have different number of bits")
}
if a.Num == 0 {
return true
}
last := len(a.Bits) - 1
for i, w := range a.Bits[:last] {
if w != b.Bits[i] {
return false
}
}
return (a.Bits[last]^b.Bits[last])<<uint(len(a.Bits)*64-a.Num) == 0
}
// IterateOnes calls visitor function v for each bit with a value of 1, in order
// from lowest bit to highest bit.
//
// Iteration continues to the highest bit as long as v returns true.
// It stops if v returns false.
//
// IterateOnes returns true normally. It returns false if v returns false.
//
// IterateOnes may not be sensitive to changes if bits are changed during
// iteration, by the vistor function for example.
// See OneFrom for an iteration method sensitive to changes during iteration.
func (b Bits) IterateOnes(v func(int) bool) bool {
for x, w := range b.Bits {
if w != 0 {
t := mb.TrailingZeros64(w)
i := t // index in w of next 1 bit
for {
n := x<<6 | i
if n >= b.Num {
return true
}
if !v(x<<6 | i) {
return false
}
w >>= uint(t + 1)
if w == 0 {
break
}
t = mb.TrailingZeros64(w)
i += 1 + t
}
}
}
return true
}
// IterateZeros calls visitor function v for each bit with a value of 0,
// in order from lowest bit to highest bit.
//
// Iteration continues to the highest bit as long as v returns true.
// It stops if v returns false.
//
// IterateZeros returns true normally. It returns false if v returns false.
//
// IterateZeros may not be sensitive to changes if bits are changed during
// iteration, by the vistor function for example.
// See ZeroFrom for an iteration method sensitive to changes during iteration.
func (b Bits) IterateZeros(v func(int) bool) bool {
for x, w := range b.Bits {
w = ^w
if w != 0 {
t := mb.TrailingZeros64(w)
i := t // index in w of next 1 bit
for {
n := x<<6 | i
if n >= b.Num {
return true
}
if !v(x<<6 | i) {
return false
}
w >>= uint(t + 1)
if w == 0 {
break
}
t = mb.TrailingZeros64(w)
i += 1 + t
}
}
}
return true
}
// Not sets receiver z to the complement of b.
func (z *Bits) Not(b Bits) {
if z.Num != b.Num {
*z = New(b.Num)
}
for i, w := range b.Bits {
z.Bits[i] = ^w
}
}
// OneFrom returns the number of the first 1 bit at or after (from) bit num.
//
// It returns -1 if there is no one bit at or after num.
//
// This provides one way to iterate over one bits.
// To iterate over the one bits, call OneFrom with n = 0 to get the the first
// one bit, then call with the result + 1 to get successive one bits.
// Unlike the Iterate method, this technique is stateless and so allows
// bits to be changed between successive calls.
//
// There is no panic for calling OneFrom with an argument >= b.Num.
// In this case OneFrom simply returns -1.
//
// See also Iterate.
func (b Bits) OneFrom(num int) int {
if num >= b.Num {
return -1
}
x := num >> 6
// test for 1 in this word at or after n
if wx := b.Bits[x] >> uint(num&63); wx != 0 {
num += mb.TrailingZeros64(wx)
if num >= b.Num {
return -1
}
return num
}
x++
for y, wy := range b.Bits[x:] {
if wy != 0 {
num = (x+y)<<6 | mb.TrailingZeros64(wy)
if num >= b.Num {
return -1
}
return num
}
}
return -1
}
// Or sets z = x | y.
//
// It panics if x and y do not have the same Num.
func (z *Bits) Or(x, y Bits) {
if x.Num != y.Num {
panic("arguments have different number of bits")
}
if z.Num != x.Num {
*z = New(x.Num)
}
for i, w := range y.Bits {
z.Bits[i] = x.Bits[i] | w
}
}
// OnesCount returns the number of 1 bits.
func (b Bits) OnesCount() (c int) {
if b.Num == 0 {
return 0
}
last := len(b.Bits) - 1
for _, w := range b.Bits[:last] {
c += mb.OnesCount64(w)
}
c += mb.OnesCount64(b.Bits[last] << uint(len(b.Bits)*64-b.Num))
return
}
// Set sets the bits of z to the bits of x.
func (z *Bits) Set(b Bits) {
if z.Num != b.Num {
*z = New(b.Num)
}
copy(z.Bits, b.Bits)
}
// SetAll sets z to have all 1 bits.
func (b Bits) SetAll() {
for i := range b.Bits {
b.Bits[i] = ^uint64(0)
}
}
// SetBit sets the n'th bit to x, where x is a 0 or 1.
//
// It panics if n is out of range
func (b Bits) SetBit(n, x int) {
if n < 0 || n >= b.Num {
panic("bit number out of range")
}
if x == 0 {
b.Bits[n>>6] &^= 1 << uint(n&63)
} else {
b.Bits[n>>6] |= 1 << uint(n&63)
}
}
// SetBits sets the given bits to 1 in receiver b.
//
// Other bits of b are left unchanged.
//
// It panics if any bit number is out of range, negative or >= the number
// of bits.
func (b Bits) SetBits(nums ...int) {
for _, p := range nums {
b.SetBit(p, 1)
}
}
// Single returns true if b has exactly one 1 bit.
func (b Bits) Single() bool {
// like OnesCount, but stop as soon as two are found
if b.Num == 0 {
return false
}
c := 0
last := len(b.Bits) - 1
for _, w := range b.Bits[:last] {
c += mb.OnesCount64(w)
if c > 1 {
return false
}
}
c += mb.OnesCount64(b.Bits[last] << uint(len(b.Bits)*64-b.Num))
return c == 1
}
// Slice returns a slice with the bit numbers of each 1 bit.
func (b Bits) Slice() (s []int) {
for x, w := range b.Bits {
if w == 0 {
continue
}
t := mb.TrailingZeros64(w)
i := t // index in w of next 1 bit
for {
n := x<<6 | i
if n >= b.Num {
break
}
s = append(s, n)
w >>= uint(t + 1)
if w == 0 {
break
}
t = mb.TrailingZeros64(w)
i += 1 + t
}
}
return
}
// String returns a readable representation.
//
// The returned string is big-endian, with the highest number bit first.
//
// If Num is 0, an empty string is returned.
func (b Bits) String() (s string) {
if b.Num == 0 {
return ""
}
last := len(b.Bits) - 1
for _, w := range b.Bits[:last] {
s = fmt.Sprintf("%064b", w) + s
}
lb := b.Num - 64*last
return fmt.Sprintf("%0*b", lb,
b.Bits[last]&(^uint64(0)>>uint(64-lb))) + s
}
// Xor sets z = x ^ y.
func (z *Bits) Xor(x, y Bits) {
if x.Num != y.Num {
panic("arguments have different number of bits")
}
if z.Num != x.Num {
*z = New(x.Num)
}
for i, w := range y.Bits {
z.Bits[i] = x.Bits[i] ^ w
}
}
// ZeroFrom returns the number of the first 0 bit at or after (from) bit num.
//
// It returns -1 if there is no zero bit at or after num.
//
// This provides one way to iterate over zero bits.
// To iterate over the zero bits, call ZeroFrom with n = 0 to get the the first
// zero bit, then call with the result + 1 to get successive zero bits.
// Unlike the IterateZeros method, this technique is stateless and so allows
// bits to be changed between successive calls.
//
// There is no panic for calling ZeroFrom with an argument >= b.Num.
// In this case ZeroFrom simply returns -1.
//
// See also IterateZeros.
func (b Bits) ZeroFrom(num int) int {
// code much like OneFrom except words are negated before testing
if num >= b.Num {
return -1
}
x := num >> 6
// negate word to test for 0 at or after n
if wx := ^b.Bits[x] >> uint(num&63); wx != 0 {
num += mb.TrailingZeros64(wx)
if num >= b.Num {
return -1
}
return num
}
x++
for y, wy := range b.Bits[x:] {
wy = ^wy
if wy != 0 {
num = (x+y)<<6 | mb.TrailingZeros64(wy)
if num >= b.Num {
return -1
}
return num
}
}
return -1
}