| 149 | typename Word = typename std::decay< |
| 150 | internal::call_traits::argument_type<0, Visitor&&>>::type::value_type> |
| 151 | static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) { |
| 152 | constexpr int64_t kBitWidth = sizeof(Word) * 8; |
| 153 | |
| 154 | // local, mutable variables which will be sliced/decremented to represent consumption: |
| 155 | Bitmap bitmaps[N]; |
| 156 | int64_t offsets[N]; |
| 157 | int64_t bit_length = BitLength(bitmaps_arg, N); |
| 158 | std::span<const Word> words[N]; |
| 159 | for (size_t i = 0; i < N; ++i) { |
| 160 | bitmaps[i] = bitmaps_arg[i]; |
| 161 | offsets[i] = bitmaps[i].template word_offset<Word>(); |
| 162 | assert(offsets[i] >= 0 && offsets[i] < kBitWidth); |
| 163 | words[i] = bitmaps[i].template words<Word>(); |
| 164 | } |
| 165 | |
| 166 | auto consume = [&](int64_t consumed_bits) { |
| 167 | for (size_t i = 0; i < N; ++i) { |
| 168 | bitmaps[i] = bitmaps[i].Slice(consumed_bits, bit_length - consumed_bits); |
| 169 | offsets[i] = bitmaps[i].template word_offset<Word>(); |
| 170 | assert(offsets[i] >= 0 && offsets[i] < kBitWidth); |
| 171 | words[i] = bitmaps[i].template words<Word>(); |
| 172 | } |
| 173 | bit_length -= consumed_bits; |
| 174 | }; |
| 175 | |
| 176 | std::array<Word, N> visited_words; |
| 177 | visited_words.fill(0); |
| 178 | |
| 179 | if (bit_length <= kBitWidth * 2) { |
| 180 | // bitmaps fit into one or two words so don't bother with optimization |
| 181 | while (bit_length > 0) { |
| 182 | auto leading_bits = std::min(bit_length, kBitWidth); |
| 183 | SafeLoadWords(bitmaps, 0, leading_bits, false, &visited_words); |
| 184 | visitor(visited_words); |
| 185 | consume(leading_bits); |
| 186 | } |
| 187 | return 0; |
| 188 | } |
| 189 | |
| 190 | int64_t max_offset = *std::max_element(offsets, offsets + N); |
| 191 | int64_t min_offset = *std::min_element(offsets, offsets + N); |
| 192 | if (max_offset > 0) { |
| 193 | // consume leading bits |
| 194 | auto leading_bits = kBitWidth - min_offset; |
| 195 | SafeLoadWords(bitmaps, 0, leading_bits, true, &visited_words); |
| 196 | visitor(visited_words); |
| 197 | consume(leading_bits); |
| 198 | } |
| 199 | assert(*std::min_element(offsets, offsets + N) == 0); |
| 200 | |
| 201 | int64_t whole_word_count = bit_length / kBitWidth; |
| 202 | assert(whole_word_count >= 1); |
| 203 | |
| 204 | if (min_offset == max_offset) { |
| 205 | // all offsets were identical, all leading bits have been consumed |
| 206 | assert( |
| 207 | std::all_of(offsets, offsets + N, [](int64_t offset) { return offset == 0; })); |
| 208 | |