11 type BitArray struct {
13 Bits int `json:"bits"` // NOTE: persisted via reflect, must be exported
14 Elems []uint64 `json:"elems"` // NOTE: persisted via reflect, must be exported
17 // There is no BitArray whose Size is 0. Use nil instead.
18 func NewBitArray(bits int) *BitArray {
24 Elems: make([]uint64, (bits+63)/64),
28 func (bA *BitArray) Size() int {
35 // NOTE: behavior is undefined if i >= bA.Bits
36 func (bA *BitArray) GetIndex(i int) bool {
45 func (bA *BitArray) getIndex(i int) bool {
49 return bA.Elems[i/64]&(uint64(1)<<uint(i%64)) > 0
52 // NOTE: behavior is undefined if i >= bA.Bits
53 func (bA *BitArray) SetIndex(i int, v bool) bool {
59 return bA.setIndex(i, v)
62 func (bA *BitArray) setIndex(i int, v bool) bool {
67 bA.Elems[i/64] |= (uint64(1) << uint(i%64))
69 bA.Elems[i/64] &= ^(uint64(1) << uint(i%64))
74 func (bA *BitArray) Copy() *BitArray {
83 func (bA *BitArray) copy() *BitArray {
84 c := make([]uint64, len(bA.Elems))
92 func (bA *BitArray) copyBits(bits int) *BitArray {
93 c := make([]uint64, (bits+63)/64)
101 // Returns a BitArray of larger bits size.
102 func (bA *BitArray) Or(o *BitArray) *BitArray {
107 defer bA.mtx.Unlock()
108 c := bA.copyBits(MaxInt(bA.Bits, o.Bits))
109 for i := 0; i < len(c.Elems); i++ {
110 c.Elems[i] |= o.Elems[i]
115 // Returns a BitArray of smaller bit size.
116 func (bA *BitArray) And(o *BitArray) *BitArray {
121 defer bA.mtx.Unlock()
125 func (bA *BitArray) and(o *BitArray) *BitArray {
126 c := bA.copyBits(MinInt(bA.Bits, o.Bits))
127 for i := 0; i < len(c.Elems); i++ {
128 c.Elems[i] &= o.Elems[i]
133 func (bA *BitArray) Not() *BitArray {
135 return nil // Degenerate
138 defer bA.mtx.Unlock()
140 for i := 0; i < len(c.Elems); i++ {
141 c.Elems[i] = ^c.Elems[i]
146 func (bA *BitArray) Sub(o *BitArray) *BitArray {
151 defer bA.mtx.Unlock()
152 if bA.Bits > o.Bits {
154 for i := 0; i < len(o.Elems)-1; i++ {
155 c.Elems[i] &= ^c.Elems[i]
157 i := len(o.Elems) - 1
159 for idx := i * 64; idx < o.Bits; idx++ {
160 // NOTE: each individual GetIndex() call to o is safe.
161 c.setIndex(idx, c.getIndex(idx) && !o.GetIndex(idx))
166 return bA.and(o.Not()) // Note degenerate case where o == nil
170 func (bA *BitArray) IsEmpty() bool {
172 return true // should this be opposite?
175 defer bA.mtx.Unlock()
176 for _, e := range bA.Elems {
184 func (bA *BitArray) IsFull() bool {
189 defer bA.mtx.Unlock()
191 // Check all elements except the last
192 for _, elem := range bA.Elems[:len(bA.Elems)-1] {
198 // Check that the last element has (lastElemBits) 1's
199 lastElemBits := (bA.Bits+63)%64 + 1
200 lastElem := bA.Elems[len(bA.Elems)-1]
201 return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
204 func (bA *BitArray) PickRandom() (int, bool) {
209 defer bA.mtx.Unlock()
211 length := len(bA.Elems)
215 randElemStart := rand.Intn(length)
216 for i := 0; i < length; i++ {
217 elemIdx := ((i + randElemStart) % length)
218 if elemIdx < length-1 {
219 if bA.Elems[elemIdx] > 0 {
220 randBitStart := rand.Intn(64)
221 for j := 0; j < 64; j++ {
222 bitIdx := ((j + randBitStart) % 64)
223 if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
224 return 64*elemIdx + bitIdx, true
227 PanicSanity("should not happen")
230 // Special case for last elem, to ignore straggler bits
231 elemBits := bA.Bits % 64
235 randBitStart := rand.Intn(elemBits)
236 for j := 0; j < elemBits; j++ {
237 bitIdx := ((j + randBitStart) % elemBits)
238 if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
239 return 64*elemIdx + bitIdx, true
247 func (bA *BitArray) String() string {
249 return "nil-BitArray"
252 defer bA.mtx.Unlock()
253 return bA.stringIndented("")
256 func (bA *BitArray) StringIndented(indent string) string {
258 return "nil-BitArray"
261 defer bA.mtx.Unlock()
262 return bA.stringIndented(indent)
265 func (bA *BitArray) stringIndented(indent string) string {
269 for i := 0; i < bA.Bits; i++ {
276 lines = append(lines, bits)
287 lines = append(lines, bits)
289 return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
292 func (bA *BitArray) Bytes() []byte {
294 defer bA.mtx.Unlock()
296 numBytes := (bA.Bits + 7) / 8
297 bytes := make([]byte, numBytes)
298 for i := 0; i < len(bA.Elems); i++ {
299 elemBytes := [8]byte{}
300 binary.LittleEndian.PutUint64(elemBytes[:], bA.Elems[i])
301 copy(bytes[i*8:], elemBytes[:])
306 // NOTE: other bitarray o is not locked when reading,
307 // so if necessary, caller must copy or lock o prior to calling Update.
308 // If bA is nil, does nothing.
309 func (bA *BitArray) Update(o *BitArray) {
314 defer bA.mtx.Unlock()
316 copy(bA.Elems, o.Elems)