github.com/djordje200179/extendedlibrary/datastructures@v1.7.1-0.20240227175559-d09520a92dd4/cols/bitarray/array.go (about) 1 package bitarray 2 3 import ( 4 "github.com/djordje200179/extendedlibrary/datastructures/cols" 5 "strings" 6 ) 7 8 // Array is an optimized array of boolean values. 9 // The zero value is ready to use. Do not copy a non-zero Array. 10 type Array struct { 11 slice []uint8 12 lastElemOff uint8 13 } 14 15 // New creates an empty Array. 16 func New() *Array { 17 return &Array{ 18 slice: make([]uint8, 0), 19 } 20 } 21 22 // NewWithSize creates an empty Array with the specified initial size. 23 func NewWithSize(initialSize int) *Array { 24 arrSize := (initialSize + 7) / 8 25 26 return &Array{ 27 slice: make([]uint8, arrSize), 28 lastElemOff: uint8(initialSize % 8), 29 } 30 } 31 32 // NewWithCapacity creates an empty Array with the specified initial capacity. 33 func NewWithCapacity(initialCapacity int) *Array { 34 arrCapacity := (initialCapacity + 7) / 8 35 36 return &Array{ 37 slice: make([]uint8, 0, arrCapacity), 38 lastElemOff: 0, 39 } 40 } 41 42 // NewFromSlice creates an Array from the specified slice. 43 func NewFromSlice(slice []bool) *Array { 44 arr := NewWithSize(len(slice)) 45 46 for i, val := range slice { 47 arr.Set(i, val) 48 } 49 50 return arr 51 } 52 53 // Size returns the number of bits in the Array. 54 func (array *Array) Size() int { 55 if array.lastElemOff == 0 { 56 return len(array.slice) * 8 57 } else { 58 return (len(array.slice)-1)*8 + int(array.lastElemOff) 59 } 60 } 61 62 // Capacity returns the number of bits that the Array can hold without reallocating. 63 func (array *Array) Capacity() int { 64 return cap(array.slice) * 8 65 } 66 67 func (array *Array) getRealIndex(index int) int { 68 size := array.Size() 69 70 if index >= size || index < -size { 71 panic(cols.IndexOutOfBoundsError{Index: index, Length: size}) 72 } 73 74 if index < 0 { 75 index += size 76 } 77 78 return index 79 } 80 81 // Get returns the bit at the specified index. 82 // Negative indices are interpreted as relative to the end of the Array. 83 // Panics if the index is out of bounds. 84 func (array *Array) Get(index int) bool { 85 index = array.getRealIndex(index) 86 87 elemIndex := index / 8 88 elemOff := index % 8 89 masked := array.slice[elemIndex] & (1 << elemOff) 90 91 return masked != 0 92 } 93 94 // Set sets the bit at the specified index to the specified value. 95 // Negative indices are interpreted as relative to the end of the Array. 96 // Panics if the index is out of bounds. 97 func (array *Array) Set(index int, value bool) { 98 index = array.getRealIndex(index) 99 100 elemIndex := index / 8 101 elemOff := index % 8 102 elem := array.slice[elemIndex] 103 104 mask := uint8(1) << elemOff 105 if value { 106 elem |= mask 107 } else { 108 elem &= ^mask 109 } 110 111 array.slice[elemIndex] = elem 112 } 113 114 // SetAll sets all bits in the Array to the specified value. 115 func (array *Array) SetAll(value bool) { 116 var elem uint8 117 if value { 118 elem = 0xFF 119 } 120 121 for i := range array.slice { 122 array.slice[i] = elem 123 } 124 } 125 126 // Flip flips the bit at the specified index. 127 func (array *Array) Flip(index int) { 128 index = array.getRealIndex(index) 129 130 elemIndex := index / 8 131 elemOff := index % 8 132 elem := array.slice[elemIndex] 133 134 mask := uint8(1) << elemOff 135 elem ^= mask 136 137 array.slice[elemIndex] = elem 138 } 139 140 // FlipAll flips all bits in the Array. 141 func (array *Array) FlipAll() { 142 for i, val := range array.slice { 143 array.slice[i] = ^val 144 } 145 } 146 147 // Append appends the specified bit value to the end of the Array. 148 func (array *Array) Append(value bool) { 149 if array.lastElemOff == 0 { 150 array.slice = append(array.slice, 0) 151 } 152 153 array.lastElemOff = (array.lastElemOff + 1) % 8 154 155 array.Set(array.Size()-1, value) 156 } 157 158 // Insert inserts the specified bit value at the specified index. 159 func (array *Array) Insert(index int, value bool) { 160 index = array.getRealIndex(index) 161 162 elemIndex := index / 8 163 elemOff := index % 8 164 165 if array.lastElemOff == 0 { 166 array.slice = append(array.slice, 0) 167 } 168 array.lastElemOff = (array.lastElemOff + 1) % 8 169 170 var lastBit bool 171 if elemOff != 0 { 172 elem := array.slice[elemIndex] 173 174 lastBit = elem&(1<<7) != 0 175 higherBits := elem >> elemOff << (elemOff + 1) 176 lowerBits := elem << (8 - elemOff) >> (8 - elemOff) 177 178 var shiftedValue uint8 179 if value { 180 shiftedValue = 1 << elemOff 181 } 182 183 newElem := higherBits | lowerBits | shiftedValue 184 185 array.slice[elemIndex] = newElem 186 } 187 188 for i := elemIndex + 1; i < len(array.slice); i++ { 189 elem := array.slice[i] 190 191 newLastBit := elem&(1<<7) != 0 192 elem = elem << 1 193 194 if lastBit { 195 elem |= 1 196 } 197 198 array.slice[i] = elem 199 lastBit = newLastBit 200 } 201 } 202 203 // Remove removes the bit at the specified index. 204 func (array *Array) Remove(index int) { 205 index = array.getRealIndex(index) 206 207 elemIndex := index / 8 208 elemOff := index % 8 209 210 var firstBit bool 211 for i := len(array.slice) - 1; i > elemIndex; i-- { 212 elem := array.slice[i] 213 214 newFirstBit := elem&1 != 0 215 elem = elem >> 1 216 217 if firstBit { 218 elem |= 1 << 7 219 } 220 221 array.slice[i] = elem 222 firstBit = newFirstBit 223 } 224 225 if elemOff != 0 { 226 elem := array.slice[elemIndex] 227 228 higherBits := elem >> elemOff << elemOff 229 lowerBits := elem << (8 - elemOff) >> (8 - elemOff) 230 231 newElem := higherBits | lowerBits 232 233 array.slice[elemIndex] = newElem 234 } 235 236 array.lastElemOff = (array.lastElemOff - 1) % 8 237 if array.lastElemOff == 0 { 238 array.slice = array.slice[:len(array.slice)-1] 239 } 240 } 241 242 // Clear removes all bits from the Array. 243 func (array *Array) Clear() { 244 array.slice = make([]uint8, 0) 245 array.lastElemOff = 0 246 } 247 248 // Reverse reverses the order of the bits in the Array. 249 func (array *Array) Reverse() { 250 panic("not implemented") 251 } 252 253 // Join appends all bits from the specified Array to the end of the Array. 254 func (array *Array) Join(other *Array) { 255 if array.lastElemOff == 0 { 256 array.slice = append(array.slice, other.slice...) 257 array.lastElemOff = other.lastElemOff 258 } else { 259 for i := range other.Size() { 260 array.Append(other.Get(i)) 261 } 262 } 263 264 other.Clear() 265 } 266 267 // Clone returns a shallow copy of the Array. 268 func (array *Array) Clone() *Array { 269 cloned := NewWithSize(array.Size()) 270 cloned.lastElemOff = array.lastElemOff 271 copy(cloned.slice, array.slice) 272 273 return cloned 274 } 275 276 // String returns a string representation of the Array. 277 func (array *Array) String() string { 278 var sb strings.Builder 279 280 for i := range array.Size() { 281 val := array.Get(i) 282 283 var char byte 284 if val { 285 char = '1' 286 } else { 287 char = '0' 288 } 289 290 sb.WriteByte(char) 291 } 292 293 return sb.String() 294 }