// Package bits provides a bit vector backed with uints
package bits
import (
"strconv"
)
// The Vector interface defines methods on the bit vector
type Vector interface {
// Retrieves the bit at the designated position
Peek(uint) bool
// Sets the bit at the designated position
Poke(uint, bool)
// Flips the bit at the designated position
Flip(uint)
// Returns the total number of elements supported by the vector
Len() uint
}
type boolvector []bool
// Retrieves the bit at the designated position
func (v boolvector) Peek(pos uint) bool {
return v[pos]
}
// Sets the bit at the designated position
func (v boolvector) Poke(pos uint, val bool) {
v[pos] = val
}
// Flips the bit at the designated position
func (v boolvector) Flip(pos uint) {
v[pos] = !v[pos]
}
// Returns the total number of elements supported by the vector
func (v boolvector) Len() uint {
return uint(len(v))
}
type vector []uint
// Retrieves the bit at the designated position
func (v vector) Peek(pos uint) bool {
var slot, offset uint = at(pos)
return (v[slot] & (1 << offset)) > 0
}
// Sets the bit at the designated position
func (v vector) Poke(pos uint, val bool) {
var slot, offset uint = at(pos)
if val {
v[slot] |= (1 << offset)
} else {
v[slot] &^= (1 << offset)
}
}
// Flips the bit at the designated position
func (v vector) Flip(pos uint) {
var slot, offset uint = at(pos)
v[slot] ^= (1 << offset)
}
// Returns the total number of elements supported by the vector
func (v vector) Len() uint {
return uint(len(v) * strconv.IntSize)
}
func at(pos uint) (uint, uint) {
return pos / strconv.IntSize, pos % strconv.IntSize
}
// Create a new bit vector sized up to the desired number of elements
func New(size uint) Vector {
var length uint = size / strconv.IntSize
if size%strconv.IntSize > 0 {
// Allocate one additional slot if the desired
// size is does not divide by 32/64
length++
}
var slice []uint = make([]uint, length)
return vector(slice)
}
func NewBool(size uint) Vector {
var slice []bool = make([]bool, size)
return boolvector(slice)
}