github.com/tunabay/go-bitarray@v1.3.1/util.go (about) 1 // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved. 2 // Use of this source code is governed by the MIT license that can be found in 3 // the LICENSE file. 4 5 package bitarray 6 7 import ( 8 "fmt" 9 "unsafe" 10 ) 11 12 // dstOff < 8, srcOff < 8, nBits < 8, dstOff + nBits <= 8 13 func copyBits7(dst *byte, src []byte, dstOff, srcOff, nBits int) bool { 14 nBits0, srcBits0 := nBits, 8-srcOff 15 if srcBits0 < nBits { 16 nBits0 = srcBits0 17 } 18 mask := byte(0xff) << (8 - nBits0) >> dstOff 19 *dst &= ^mask 20 *dst |= mask & (src[0] << srcOff >> dstOff) 21 22 zf := src[0] == 0 23 if nBits0 < nBits { 24 zf2 := copyBits7(dst, src[1:], dstOff+nBits0, 0, nBits-nBits0) 25 zf = zf && zf2 26 } 27 28 return zf 29 } 30 31 func copyBits(dst, src []byte, dstOff, srcOff, nBits int) bool { 32 dst, src = dst[dstOff>>3:], src[srcOff>>3:] 33 dstOff, srcOff = dstOff&7, srcOff&7 34 35 zf := true 36 if dstOff != 0 { 37 nBits0 := 8 - dstOff 38 if nBits <= nBits0 { 39 zf2 := copyBits7(&dst[0], src, dstOff, srcOff, nBits) 40 return zf2 41 } 42 zf2 := copyBits7(&dst[0], src, dstOff, srcOff, nBits0) 43 zf = zf && zf2 44 45 nBits -= nBits0 46 dst = dst[1:] 47 srcOff += nBits0 48 src = src[srcOff>>3:] 49 srcOff &= 7 50 } 51 52 if nBytes1 := nBits >> 3; 0 < nBytes1 { 53 if srcOff == 0 { 54 copy(dst, src[:nBytes1]) 55 zf = false 56 } else { 57 rsh := 8 - srcOff 58 for i := 0; i < nBytes1; i++ { 59 dst[i] = src[i]<<srcOff | src[i+1]>>rsh 60 zf = zf && dst[i] == 0 61 } 62 } 63 nBits &= 7 64 if nBits == 0 { 65 return zf 66 } 67 dst = dst[nBytes1:] 68 src = src[nBytes1:] 69 } 70 71 zf2 := copyBits7(&dst[0], src, 0, srcOff, nBits) 72 73 return zf && zf2 74 } 75 76 func clearBits(b []byte, off, nBits int) { 77 b = b[off>>3:] 78 off &= 7 79 80 if off != 0 { 81 nBits0 := 8 - off 82 if nBits <= nBits0 { 83 b[0] &^= byte(0xff) << (8 - nBits) >> off 84 return 85 } 86 b[0] &= byte(0xff) << nBits0 87 nBits -= nBits0 88 b = b[1:] 89 } 90 91 if nBytes1 := nBits >> 3; 0 < nBytes1 { 92 for i := 0; i < nBits>>3; i++ { 93 b[i] = 0 94 } 95 nBits &= 7 96 b = b[nBytes1:] 97 } 98 99 if nBits != 0 { 100 b[0] &= byte(0xff) >> nBits 101 } 102 } 103 104 func setBits(b []byte, off, nBits int) { 105 b = b[off>>3:] 106 off &= 7 107 108 if off != 0 { 109 nBits0 := 8 - off 110 if nBits <= nBits0 { 111 b[0] |= byte(0xff) << (8 - nBits) >> off 112 return 113 } 114 b[0] |= byte(0xff) >> off 115 nBits -= nBits0 116 b = b[1:] 117 } 118 119 if nBytes1 := nBits >> 3; 0 < nBytes1 { 120 for i := 0; i < nBits>>3; i++ { 121 b[i] = 0xff 122 } 123 nBits &= 7 124 b = b[nBytes1:] 125 } 126 127 if nBits != 0 { 128 b[0] |= byte(0xff) << (8 - nBits) 129 } 130 } 131 132 func toggleBits(b []byte, off, nBits int) { 133 b = b[off>>3:] 134 off &= 7 135 136 if off != 0 { 137 nBits0 := 8 - off 138 if nBits <= nBits0 { 139 b[0] ^= byte(0xff) << (8 - nBits) >> off 140 return 141 } 142 b[0] ^= byte(0xff) >> off 143 nBits -= nBits0 144 b = b[1:] 145 } 146 147 if nBytes1 := nBits >> 3; 0 < nBytes1 { 148 for i := 0; i < nBits>>3; i++ { 149 b[i] ^= 0xff 150 } 151 nBits &= 7 152 b = b[nBytes1:] 153 } 154 155 if nBits != 0 { 156 b[0] ^= byte(0xff) << (8 - nBits) 157 } 158 } 159 160 // dstOff < 8, srcOff < 8, nBits < 8, dstOff + nBits <= 8 161 func andBits7(dst *byte, src []byte, dstOff, srcOff, nBits int) { 162 nBits0, srcBits0 := nBits, 8-srcOff 163 if srcBits0 < nBits { 164 nBits0 = srcBits0 165 } 166 mask := byte(0xff) << (8 - nBits0) >> dstOff 167 *dst &= ^mask | (src[0] << srcOff >> dstOff) 168 169 if nBits0 < nBits { 170 andBits7(dst, src[1:], dstOff+nBits0, 0, nBits-nBits0) 171 } 172 } 173 174 func andBits(dst, src []byte, dstOff, srcOff, nBits int) { 175 dst, src = dst[dstOff>>3:], src[srcOff>>3:] 176 dstOff, srcOff = dstOff&7, srcOff&7 177 178 if dstOff != 0 { 179 nBits0 := 8 - dstOff 180 if nBits <= nBits0 { 181 andBits7(&dst[0], src, dstOff, srcOff, nBits) 182 return 183 } 184 andBits7(&dst[0], src, dstOff, srcOff, nBits0) 185 186 nBits -= nBits0 187 dst = dst[1:] 188 srcOff += nBits0 189 src = src[srcOff>>3:] 190 srcOff &= 7 191 } 192 193 // TODO: maybe can be optimized using asUint64Slice() 194 if nBytes1 := nBits >> 3; 0 < nBytes1 { 195 if srcOff == 0 { 196 for i := 0; i < nBytes1; i++ { 197 dst[i] &= src[i] 198 } 199 } else { 200 rsh := 8 - srcOff 201 for i := 0; i < nBytes1; i++ { 202 dst[i] &= src[i]<<srcOff | src[i+1]>>rsh 203 } 204 } 205 nBits &= 7 206 if nBits == 0 { 207 return 208 } 209 dst = dst[nBytes1:] 210 src = src[nBytes1:] 211 } 212 213 andBits7(&dst[0], src, 0, srcOff, nBits) 214 } 215 216 // dstOff < 8, srcOff < 8, nBits < 8, dstOff + nBits <= 8 217 func orBits7(dst *byte, src []byte, dstOff, srcOff, nBits int) { 218 nBits0, srcBits0 := nBits, 8-srcOff 219 if srcBits0 < nBits { 220 nBits0 = srcBits0 221 } 222 mask := byte(0xff) << (8 - nBits0) >> dstOff 223 *dst |= mask & (src[0] << srcOff >> dstOff) 224 225 if nBits0 < nBits { 226 orBits7(dst, src[1:], dstOff+nBits0, 0, nBits-nBits0) 227 } 228 } 229 230 func orBits(dst, src []byte, dstOff, srcOff, nBits int) { 231 dst, src = dst[dstOff>>3:], src[srcOff>>3:] 232 dstOff, srcOff = dstOff&7, srcOff&7 233 234 if dstOff != 0 { 235 nBits0 := 8 - dstOff 236 if nBits <= nBits0 { 237 orBits7(&dst[0], src, dstOff, srcOff, nBits) 238 return 239 } 240 orBits7(&dst[0], src, dstOff, srcOff, nBits0) 241 242 nBits -= nBits0 243 dst = dst[1:] 244 srcOff += nBits0 245 src = src[srcOff>>3:] 246 srcOff &= 7 247 } 248 249 // TODO: maybe can be optimized using asUint64Slice() 250 if nBytes1 := nBits >> 3; 0 < nBytes1 { 251 if srcOff == 0 { 252 for i := 0; i < nBytes1; i++ { 253 dst[i] |= src[i] 254 } 255 } else { 256 rsh := 8 - srcOff 257 for i := 0; i < nBytes1; i++ { 258 dst[i] |= src[i]<<srcOff | src[i+1]>>rsh 259 } 260 } 261 nBits &= 7 262 if nBits == 0 { 263 return 264 } 265 dst = dst[nBytes1:] 266 src = src[nBytes1:] 267 } 268 269 orBits7(&dst[0], src, 0, srcOff, nBits) 270 } 271 272 // dstOff < 8, srcOff < 8, nBits < 8, dstOff + nBits <= 8 273 func xorBits7(dst *byte, src []byte, dstOff, srcOff, nBits int) { 274 nBits0, srcBits0 := nBits, 8-srcOff 275 if srcBits0 < nBits { 276 nBits0 = srcBits0 277 } 278 mask := byte(0xff) << (8 - nBits0) >> dstOff 279 *dst ^= mask & (src[0] << srcOff >> dstOff) 280 281 if nBits0 < nBits { 282 xorBits7(dst, src[1:], dstOff+nBits0, 0, nBits-nBits0) 283 } 284 } 285 286 func xorBits(dst, src []byte, dstOff, srcOff, nBits int) { 287 dst, src = dst[dstOff>>3:], src[srcOff>>3:] 288 dstOff, srcOff = dstOff&7, srcOff&7 289 290 if dstOff != 0 { 291 nBits0 := 8 - dstOff 292 if nBits <= nBits0 { 293 xorBits7(&dst[0], src, dstOff, srcOff, nBits) 294 return 295 } 296 xorBits7(&dst[0], src, dstOff, srcOff, nBits0) 297 298 nBits -= nBits0 299 dst = dst[1:] 300 srcOff += nBits0 301 src = src[srcOff>>3:] 302 srcOff &= 7 303 } 304 305 // TODO: maybe can be optimized using asUint64Slice() 306 if nBytes1 := nBits >> 3; 0 < nBytes1 { 307 if srcOff == 0 { 308 for i := 0; i < nBytes1; i++ { 309 dst[i] ^= src[i] 310 } 311 } else { 312 rsh := 8 - srcOff 313 for i := 0; i < nBytes1; i++ { 314 dst[i] ^= src[i]<<srcOff | src[i+1]>>rsh 315 } 316 } 317 nBits &= 7 318 if nBits == 0 { 319 return 320 } 321 dst = dst[nBytes1:] 322 src = src[nBytes1:] 323 } 324 325 xorBits7(&dst[0], src, 0, srcOff, nBits) 326 } 327 328 func allBytesZero(b []byte) bool { 329 for _, u64 := range asUint64Slice(b) { 330 if u64 != 0 { 331 return false 332 } 333 } 334 return true 335 } 336 337 func panicf(format string, v ...interface{}) { 338 panic("bitarray: " + fmt.Sprintf(format, v...)) 339 } 340 341 func allocByteSlice(nBytes int) []byte { 342 return make([]byte, nBytes, (nBytes+7) & ^7) 343 } 344 345 func asUint64Slice(b []byte) []uint64 { 346 return unsafe.Slice((*uint64)(unsafe.Pointer(&b[0])), (len(b)+7)>>3) 347 } 348 349 func fill00(b []byte) { 350 // This seems to get optimized into a memclr. 351 for i := range b { 352 b[i] = 0 353 } 354 // copy(b, []byte{0, 0, 0, 0, 0, 0, 0, 0}) 355 // for n := 8; n < len(b); n <<= 1 { 356 // copy(b[n:], b[:n]) 357 // } 358 } 359 360 func fillFF(b []byte) { 361 copy(b, []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) 362 for n := 8; n < len(b); n <<= 1 { 363 copy(b[n:], b[:n]) 364 } 365 } 366 367 func fill30(b []byte) { 368 copy(b, []byte{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}) 369 for n := 8; n < len(b); n <<= 1 { 370 copy(b[n:], b[:n]) 371 } 372 } 373 374 // ba != nil 375 func (ba *BitArray) bits8() []byte { 376 b8 := make([]byte, ba.nBits) 377 if ba.b == nil { 378 return b8 379 } 380 for i := 0; i < ba.nBits; i++ { 381 b8[i] = ba.b[i>>3] >> (7 - i&7) & 1 382 } 383 return b8 384 }