Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ go_library(
"bitlist.go",
"bitlist64.go",
"bitvector128.go",
"bitvector2.go",
"bitvector256.go",
"bitvector32.go",
"bitvector4.go",
Expand All @@ -76,6 +77,7 @@ go_test(
"bitlist_test.go",
"bitvector128_test.go",
"bitvector256_test.go",
"bitvector2_test.go",
"bitvector32_test.go",
"bitvector4_test.go",
"bitvector512_test.go",
Expand Down
108 changes: 108 additions & 0 deletions bitvector2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package bitfield

import (
"math/bits"
)

var _ = Bitfield(Bitvector2{})

// Bitvector2 is a bitfield with a known size of 2. There is no length bit
// present in the underlying byte array.
type Bitvector2 []byte

const bitvector2ByteSize = 1
const bitvector2BitSize = 2

// NewBitvector2 creates a new bitvector of size 2.
func NewBitvector2() Bitvector2 {
byteArray := [bitvector2ByteSize]byte{}
return byteArray[:]
}

// BitAt returns the bit value at the given index. If the index requested
// exceeds the number of bits in the bitvector, then this method returns false.
func (b Bitvector2) BitAt(idx uint64) bool {
// Out of bounds, must be false.
if idx >= b.Len() || len(b) != bitvector2ByteSize {
return false
}

i := uint8(1 << idx)
return b[0]&i == i

}

// SetBitAt will set the bit at the given index to the given value. If the index
// requested exceeds the number of bits in the bitvector, then this method returns
// false.
func (b Bitvector2) SetBitAt(idx uint64, val bool) {
// Out of bounds, do nothing.
if idx >= b.Len() || len(b) != bitvector2ByteSize {
return
}

bit := uint8(1 << idx)
if val {
b[0] |= bit
} else {
b[0] &^= bit
}
}

// Len returns the number of bits in the bitvector.
func (b Bitvector2) Len() uint64 {
return bitvector2BitSize
}

// Count returns the number of 1s in the bitvector.
func (b Bitvector2) Count() uint64 {
if len(b) == 0 {
return 0
}
return uint64(bits.OnesCount8(b.Bytes()[0]))
}

// Bytes returns the bytes data representing the bitvector2. This method
// bitmasks the underlying data to ensure that it is an accurate representation.
func (b Bitvector2) Bytes() []byte {
if len(b) == 0 {
return []byte{}
}
return []byte{b[0] & 0x03}
}

// Shift bitvector by i. If i >= 0, perform left shift, otherwise right shift.
func (b Bitvector2) Shift(i int) {
if len(b) == 0 {
return
}

// Shifting greater than 2 bits is pointless and can have unexpected behavior.
if i > 2 {
i = 2
} else if i < -2 {
i = -2
}

if i >= 0 {
b[0] <<= uint8(i)
} else {
b[0] >>= uint8(i * -1)
}
b[0] &= 0x03
}

// BitIndices returns the list of indices that are set to 1.
func (b Bitvector2) BitIndices() []int {
indices := make([]int, 0, 2)
for i, bt := range b {
for j := 0; j < 8; j++ {
bit := byte(1 << uint(j))
if bt&bit == bit {
indices = append(indices, i*8+j)
}
}
}

return indices
}
Loading