func (b *Bitset) At(index int) bool {
	if index >= b.numBits {
		log.Panicf("Index %d out of range", index)
	}
	return (b.bits[index/8] & (0x80 >> byte(index%8))) != 0
}
At returns the value of the bit at |index|.
package bitset
import (
	"bytes"
	"fmt"
	"log"
)
const (
	b0 = false
	b1 = true
)
type Bitset struct {
	numBits int
	bits []byte
}
func New(v ...bool) *Bitset {
	b := &Bitset{numBits: 0, bits: make([]byte, 0)}
	b.AppendBools(v...)
	return b
}
func Clone(from *Bitset) *Bitset {
	return &Bitset{numBits: from.numBits, bits: from.bits[:]}
}
func (b *Bitset) Substr(start int, end int) *Bitset {
	if start > end || end > b.numBits {
		log.Panicf("Out of range start=%d end=%d numBits=%d", start, end, b.numBits)
	}
	result := New()
	result.ensureCapacity(end - start)
	for i := start; i < end; i++ {
		if b.At(i) {
			result.bits[result.numBits/8] |= 0x80 >> uint(result.numBits%8)
		}
		result.numBits++
	}
	return result
}
func NewFromBase2String(b2string string) *Bitset {
	b := &Bitset{numBits: 0, bits: make([]byte, 0)}
	for _, c := range b2string {
		switch c {
		case '1':
			b.AppendBools(true)
		case '0':
			b.AppendBools(false)
		case ' ':
		default:
			log.Panicf("Invalid char %c in NewFromBase2String", c)
		}
	}
	return b
}
func (b *Bitset) AppendBytes(data []byte) {
	for _, d := range data {
		b.AppendByte(d, 8)
	}
}
func (b *Bitset) AppendByte(value byte, numBits int) {
	b.ensureCapacity(numBits)
	if numBits > 8 {
		log.Panicf("numBits %d out of range 0-8", numBits)
	}
	for i := numBits - 1; i >= 0; i-- {
		if value&(1<<uint(i)) != 0 {
			b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
		}
		b.numBits++
	}
}
func (b *Bitset) AppendUint32(value uint32, numBits int) {
	b.ensureCapacity(numBits)
	if numBits > 32 {
		log.Panicf("numBits %d out of range 0-32", numBits)
	}
	for i := numBits - 1; i >= 0; i-- {
		if value&(1<<uint(i)) != 0 {
			b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
		}
		b.numBits++
	}
}
func (b *Bitset) ensureCapacity(numBits int) {
	numBits += b.numBits
	newNumBytes := numBits / 8
	if numBits%8 != 0 {
		newNumBytes++
	}
	if len(b.bits) >= newNumBytes {
		return
	}
	b.bits = append(b.bits, make([]byte, newNumBytes+2*len(b.bits))...)
}
func (b *Bitset) Append(other *Bitset) {
	b.ensureCapacity(other.numBits)
	for i := 0; i < other.numBits; i++ {
		if other.At(i) {
			b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
		}
		b.numBits++
	}
}
func (b *Bitset) AppendBools(bits ...bool) {
	b.ensureCapacity(len(bits))
	for _, v := range bits {
		if v {
			b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
		}
		b.numBits++
	}
}
func (b *Bitset) AppendNumBools(num int, value bool) {
	for i := 0; i < num; i++ {
		b.AppendBools(value)
	}
}
func (b *Bitset) String() string {
	var bitString string
	for i := 0; i < b.numBits; i++ {
		if (i % 8) == 0 {
			bitString += " "
		}
		if (b.bits[i/8] & (0x80 >> byte(i%8))) != 0 {
			bitString += "1"
		} else {
			bitString += "0"
		}
	}
	return fmt.Sprintf("numBits=%d, bits=%s", b.numBits, bitString)
}
func (b *Bitset) Len() int {
	return b.numBits
}
func (b *Bitset) Bits() []bool {
	result := make([]bool, b.numBits)
	var i int
	for i = 0; i < b.numBits; i++ {
		result[i] = (b.bits[i/8] & (0x80 >> byte(i%8))) != 0
	}
	return result
}