| 88 | } |
| 89 | |
| 90 | std::size_t BitVector::countNulls(std::size_t num_bits) const { |
| 91 | const std::size_t num_bytes = bytesForBits(num_bits); |
| 92 | const uint8_t* ptr = bytes_.data(); |
| 93 | |
| 94 | std::size_t total_set_bits = 0; |
| 95 | |
| 96 | // Process full bytes |
| 97 | const std::size_t full_bytes = num_bits / 8; |
| 98 | for (std::size_t i = 0; i < full_bytes; ++i) { |
| 99 | total_set_bits += static_cast<std::size_t>(std::popcount(ptr[i])); |
| 100 | } |
| 101 | |
| 102 | // Process remaining bits in the last partial byte (if any) |
| 103 | const std::size_t remaining_bits = num_bits % 8; |
| 104 | if (remaining_bits > 0 && num_bytes > 0) { |
| 105 | const uint8_t mask = static_cast<uint8_t>((1u << remaining_bits) - 1u); |
| 106 | total_set_bits += static_cast<std::size_t>(std::popcount(static_cast<uint8_t>(ptr[full_bytes] & mask))); |
| 107 | } |
| 108 | |
| 109 | return num_bits - total_set_bits; |
| 110 | } |
| 111 | |
| 112 | void BitVector::assignBytes(Span<const uint8_t> bytes, std::size_t bit_count) { |
| 113 | bytes_.assign(bytes.begin(), bytes.end()); |