llvm.org GIT mirror llvm / 66b46e1
[BitVector] Add find_[first,last]_[set,unset]_in. A lot of code is duplicated between the first_last and the next / prev methods. All of this code can be shared if they are implemented in terms of find_first_in(Begin, End) etc, in which case find_first = find_first_in(0, Size) and find_next is find_first_in(Prev+1, Size), with similar reductions for the other methods. Differential Revision: https://reviews.llvm.org/D33104 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303269 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 2 years ago
2 changed file(s) with 297 addition(s) and 124 deletion(s). Raw diff Collapse all Expand all
202202 return !any();
203203 }
204204
205 /// find_first_in - Returns the index of the first set bit in the range
206 /// [Begin, End). Returns -1 if all bits in the range are unset.
207 int find_first_in(unsigned Begin, unsigned End) const {
208 assert(Begin <= End && End <= Size);
209 if (Begin == End)
210 return -1;
211
212 unsigned FirstWord = Begin / BITWORD_SIZE;
213 unsigned LastWord = (End - 1) / BITWORD_SIZE;
214
215 // Check subsequent words.
216 for (unsigned i = FirstWord; i <= LastWord; ++i) {
217 BitWord Copy = Bits[i];
218
219 if (i == FirstWord) {
220 unsigned FirstBit = Begin % BITWORD_SIZE;
221 Copy &= maskTrailingZeros(FirstBit);
222 }
223
224 if (i == LastWord) {
225 unsigned LastBit = (End - 1) % BITWORD_SIZE;
226 Copy &= maskTrailingOnes(LastBit + 1);
227 }
228 if (Copy != 0)
229 return i * BITWORD_SIZE + countTrailingZeros(Copy);
230 }
231 return -1;
232 }
233
234 /// find_last_in - Returns the index of the last set bit in the range
235 /// [Begin, End). Returns -1 if all bits in the range are unset.
236 int find_last_in(unsigned Begin, unsigned End) const {
237 assert(Begin <= End && End <= Size);
238 if (Begin == End)
239 return -1;
240
241 unsigned LastWord = (End - 1) / BITWORD_SIZE;
242 unsigned FirstWord = Begin / BITWORD_SIZE;
243
244 for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) {
245 unsigned CurrentWord = i - 1;
246
247 BitWord Copy = Bits[CurrentWord];
248 if (CurrentWord == LastWord) {
249 unsigned LastBit = (End - 1) % BITWORD_SIZE;
250 Copy &= maskTrailingOnes(LastBit + 1);
251 }
252
253 if (CurrentWord == FirstWord) {
254 unsigned FirstBit = Begin % BITWORD_SIZE;
255 Copy &= maskTrailingZeros(FirstBit);
256 }
257
258 if (Copy != 0)
259 return (CurrentWord + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
260 }
261
262 return -1;
263 }
264
265 /// find_first_unset_in - Returns the index of the first unset bit in the
266 /// range [Begin, End). Returns -1 if all bits in the range are set.
267 int find_first_unset_in(unsigned Begin, unsigned End) const {
268 assert(Begin <= End && End <= Size);
269 if (Begin == End)
270 return -1;
271
272 unsigned FirstWord = Begin / BITWORD_SIZE;
273 unsigned LastWord = (End - 1) / BITWORD_SIZE;
274
275 // Check subsequent words.
276 for (unsigned i = FirstWord; i <= LastWord; ++i) {
277 BitWord Copy = Bits[i];
278
279 if (i == FirstWord) {
280 unsigned FirstBit = Begin % BITWORD_SIZE;
281 Copy |= maskTrailingOnes(FirstBit);
282 }
283
284 if (i == LastWord) {
285 unsigned LastBit = (End - 1) % BITWORD_SIZE;
286 Copy |= maskTrailingZeros(LastBit + 1);
287 }
288 if (Copy != ~0UL) {
289 unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Copy);
290 return Result < size() ? Result : -1;
291 }
292 }
293 return -1;
294 }
295
296 /// find_last_unset_in - Returns the index of the last unset bit in the
297 /// range [Begin, End). Returns -1 if all bits in the range are set.
298 int find_last_unset_in(unsigned Begin, unsigned End) const {
299 assert(Begin <= End && End <= Size);
300 if (Begin == End)
301 return -1;
302
303 unsigned LastWord = (End - 1) / BITWORD_SIZE;
304 unsigned FirstWord = Begin / BITWORD_SIZE;
305
306 for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) {
307 unsigned CurrentWord = i - 1;
308
309 BitWord Copy = Bits[CurrentWord];
310 if (CurrentWord == LastWord) {
311 unsigned LastBit = (End - 1) % BITWORD_SIZE;
312 Copy |= maskTrailingZeros(LastBit + 1);
313 }
314
315 if (CurrentWord == FirstWord) {
316 unsigned FirstBit = Begin % BITWORD_SIZE;
317 Copy |= maskTrailingOnes(FirstBit);
318 }
319
320 if (Copy != ~0UL) {
321 unsigned Result =
322 (CurrentWord + 1) * BITWORD_SIZE - countLeadingOnes(Copy) - 1;
323 return Result < Size ? Result : -1;
324 }
325 }
326 return -1;
327 }
328
205329 /// find_first - Returns the index of the first set bit, -1 if none
206330 /// of the bits are set.
207 int find_first() const {
208 for (unsigned i = 0; i < NumBitWords(size()); ++i)
209 if (Bits[i] != 0)
210 return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
211 return -1;
212 }
331 int find_first() const { return find_first_in(0, Size); }
213332
214333 /// find_last - Returns the index of the last set bit, -1 if none of the bits
215334 /// are set.
216 int find_last() const {
217 if (Size == 0)
218 return -1;
219
220 unsigned N = NumBitWords(size());
221 assert(N > 0);
222
223 unsigned i = N - 1;
224 while (i > 0 && Bits[i] == BitWord(0))
225 --i;
226
227 return int((i + 1) * BITWORD_SIZE - countLeadingZeros(Bits[i])) - 1;
228 }
335 int find_last() const { return find_last_in(0, Size); }
336
337 /// find_next - Returns the index of the next set bit following the
338 /// "Prev" bit. Returns -1 if the next set bit is not found.
339 int find_next(unsigned Prev) const { return find_first_in(Prev + 1, Size); }
340
341 /// find_prev - Returns the index of the first set bit that precedes the
342 /// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
343 int find_prev(unsigned PriorTo) const { return find_last_in(0, PriorTo); }
229344
230345 /// find_first_unset - Returns the index of the first unset bit, -1 if all
231346 /// of the bits are set.
232 int find_first_unset() const {
233 for (unsigned i = 0; i < NumBitWords(size()); ++i)
234 if (Bits[i] != ~0UL) {
235 unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Bits[i]);
236 return Result < size() ? Result : -1;
237 }
238 return -1;
239 }
240
241 /// find_last_unset - Returns the index of the last unset bit, -1 if all of
242 /// the bits are set.
243 int find_last_unset() const {
244 if (Size == 0)
245 return -1;
246
247 const unsigned N = NumBitWords(size());
248 assert(N > 0);
249
250 unsigned i = N - 1;
251 BitWord W = Bits[i];
252
253 // The last word in the BitVector has some unused bits, so we need to set
254 // them all to 1 first. Set them all to 1 so they don't get treated as
255 // valid unset bits.
256 unsigned UnusedCount = BITWORD_SIZE - size() % BITWORD_SIZE;
257 W |= maskLeadingOnes(UnusedCount);
258
259 while (W == ~BitWord(0) && --i > 0)
260 W = Bits[i];
261
262 return int((i + 1) * BITWORD_SIZE - countLeadingOnes(W)) - 1;
263 }
264
265 /// find_next - Returns the index of the next set bit following the
266 /// "Prev" bit. Returns -1 if the next set bit is not found.
267 int find_next(unsigned Prev) const {
268 ++Prev;
269 if (Prev >= Size)
270 return -1;
271
272 unsigned WordPos = Prev / BITWORD_SIZE;
273 unsigned BitPos = Prev % BITWORD_SIZE;
274 BitWord Copy = Bits[WordPos];
275 // Mask off previous bits.
276 Copy &= maskTrailingZeros(BitPos);
277
278 if (Copy != 0)
279 return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
280
281 // Check subsequent words.
282 for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
283 if (Bits[i] != 0)
284 return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
285 return -1;
286 }
347 int find_first_unset() const { return find_first_unset_in(0, Size); }
287348
288349 /// find_next_unset - Returns the index of the next unset bit following the
289350 /// "Prev" bit. Returns -1 if all remaining bits are set.
290351 int find_next_unset(unsigned Prev) const {
291 ++Prev;
292 if (Prev >= Size)
293 return -1;
294
295 unsigned WordPos = Prev / BITWORD_SIZE;
296 unsigned BitPos = Prev % BITWORD_SIZE;
297 BitWord Copy = Bits[WordPos];
298 // Mask in previous bits.
299 BitWord Mask = (1 << BitPos) - 1;
300 Copy |= Mask;
301
302 if (Copy != ~0UL)
303 return next_unset_in_word(WordPos, Copy);
304
305 // Check subsequent words.
306 for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
307 if (Bits[i] != ~0UL)
308 return next_unset_in_word(i, Bits[i]);
309 return -1;
310 }
311
312 /// find_prev - Returns the index of the first set bit that precedes the
313 /// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
314 int find_prev(unsigned PriorTo) const {
315 if (PriorTo == 0)
316 return -1;
317
318 --PriorTo;
319
320 unsigned WordPos = PriorTo / BITWORD_SIZE;
321 unsigned BitPos = PriorTo % BITWORD_SIZE;
322 BitWord Copy = Bits[WordPos];
323 // Mask off next bits.
324 Copy &= maskTrailingOnes(BitPos + 1);
325
326 if (Copy != 0)
327 return (WordPos + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
328
329 // Check previous words.
330 for (unsigned i = 1; i <= WordPos; ++i) {
331 unsigned Index = WordPos - i;
332 if (Bits[Index] == 0)
333 continue;
334 return (Index + 1) * BITWORD_SIZE - countLeadingZeros(Bits[Index]) - 1;
335 }
336 return -1;
352 return find_first_unset_in(Prev + 1, Size);
353 }
354
355 /// find_last_unset - Returns the index of the last unset bit, -1 if all of
356 /// the bits are set.
357 int find_last_unset() const { return find_last_unset_in(0, Size); }
358
359 /// find_prev_unset - Returns the index of the first unset bit that precedes
360 /// the bit at \p PriorTo. Returns -1 if all previous bits are set.
361 int find_prev_unset(unsigned PriorTo) {
362 return find_last_unset_in(0, PriorTo);
337363 }
338364
339365 /// clear - Removes all bits from the bitvector. Does not change capacity.
181181 EXPECT_TRUE(Vec.empty());
182182 }
183183
184 TYPED_TEST(BitVectorTest, FindOperations) {
184 TYPED_TEST(BitVectorTest, SimpleFindOps) {
185185 // Test finding in an empty BitVector.
186186 TypeParam A;
187187 EXPECT_EQ(-1, A.find_first());
188188 EXPECT_EQ(-1, A.find_last());
189189 EXPECT_EQ(-1, A.find_first_unset());
190190 EXPECT_EQ(-1, A.find_last_unset());
191 EXPECT_EQ(-1, A.find_next(0));
192 EXPECT_EQ(-1, A.find_next_unset(0));
193191
194192 // Test finding next set and unset bits in a BitVector with multiple words
195193 A.resize(100);
221219 A.set(0, 100);
222220 EXPECT_EQ(100U, A.count());
223221 EXPECT_EQ(0, A.find_first());
224 EXPECT_EQ(99, A.find_last());
225222 EXPECT_EQ(-1, A.find_first_unset());
226223 EXPECT_EQ(-1, A.find_last_unset());
224 EXPECT_EQ(99, A.find_last());
225 EXPECT_EQ(99, A.find_next(98));
227226
228227 A.reset(0, 100);
229228 EXPECT_EQ(0U, A.count());
231230 EXPECT_EQ(-1, A.find_last());
232231 EXPECT_EQ(0, A.find_first_unset());
233232 EXPECT_EQ(99, A.find_last_unset());
233 EXPECT_EQ(99, A.find_next_unset(98));
234234
235235 // Also test with a vector that is small enough to fit in 1 word.
236236 A.resize(20);
255255 EXPECT_EQ(5, A.find_next_unset(4));
256256 EXPECT_EQ(13, A.find_next_unset(12));
257257 EXPECT_EQ(17, A.find_next_unset(15));
258 }
259
260 TEST(BitVectorTest, FindInRangeMultiWord) {
261 BitVector Vec;
262
263 Vec.resize(200);
264 Vec.set(3, 7);
265 Vec.set(24, 35);
266 Vec.set(50, 70);
267 Vec.set(150);
268 Vec.set(152);
269 Vec.set(154);
270
271 // find first
272 EXPECT_EQ(-1, Vec.find_first_in(0, 0));
273 EXPECT_EQ(-1, Vec.find_first_in(24, 24));
274 EXPECT_EQ(-1, Vec.find_first_in(7, 24));
275
276 EXPECT_EQ(3, Vec.find_first_in(0, 10));
277 EXPECT_EQ(4, Vec.find_first_in(4, 10));
278 EXPECT_EQ(150, Vec.find_first_in(100, 200));
279 EXPECT_EQ(152, Vec.find_first_in(151, 200));
280 EXPECT_EQ(154, Vec.find_first_in(153, 200));
281
282 EXPECT_EQ(-1, Vec.find_first_in(155, 200));
283 Vec.set(199);
284 EXPECT_EQ(199, Vec.find_first_in(199, 200));
285 Vec.reset(199);
286
287 // find last
288 EXPECT_EQ(-1, Vec.find_last_in(0, 0));
289 EXPECT_EQ(-1, Vec.find_last_in(24, 24));
290 EXPECT_EQ(-1, Vec.find_last_in(7, 24));
291
292 EXPECT_EQ(6, Vec.find_last_in(0, 10));
293 EXPECT_EQ(5, Vec.find_last_in(0, 6));
294 EXPECT_EQ(154, Vec.find_last_in(100, 155));
295 EXPECT_EQ(152, Vec.find_last_in(100, 154));
296 EXPECT_EQ(150, Vec.find_last_in(100, 152));
297 EXPECT_EQ(-1, Vec.find_last_in(100, 150));
298 Vec.set(199);
299 EXPECT_EQ(199, Vec.find_last_in(199, 200));
300 Vec.reset(199);
301
302 // find first unset
303 EXPECT_EQ(-1, Vec.find_first_unset_in(0, 0));
304 EXPECT_EQ(-1, Vec.find_first_unset_in(23, 23));
305 EXPECT_EQ(-1, Vec.find_first_unset_in(24, 35));
306
307 EXPECT_EQ(0, Vec.find_first_unset_in(0, 10));
308 EXPECT_EQ(1, Vec.find_first_unset_in(1, 10));
309 EXPECT_EQ(7, Vec.find_first_unset_in(5, 25));
310 EXPECT_EQ(151, Vec.find_first_unset_in(150, 200));
311 EXPECT_EQ(151, Vec.find_first_unset_in(151, 200));
312 EXPECT_EQ(153, Vec.find_first_unset_in(152, 200));
313 EXPECT_EQ(153, Vec.find_first_unset_in(153, 200));
314 EXPECT_EQ(155, Vec.find_first_unset_in(154, 200));
315 EXPECT_EQ(155, Vec.find_first_unset_in(155, 200));
316 EXPECT_EQ(199, Vec.find_first_unset_in(199, 200));
317
318 // find last unset
319 EXPECT_EQ(-1, Vec.find_last_unset_in(0, 0));
320 EXPECT_EQ(-1, Vec.find_last_unset_in(23, 23));
321 EXPECT_EQ(-1, Vec.find_last_unset_in(24, 35));
322
323 EXPECT_EQ(9, Vec.find_last_unset_in(0, 10));
324 EXPECT_EQ(8, Vec.find_last_unset_in(0, 9));
325 EXPECT_EQ(2, Vec.find_last_unset_in(0, 7));
326 EXPECT_EQ(149, Vec.find_last_unset_in(100, 151));
327 EXPECT_EQ(151, Vec.find_last_unset_in(100, 152));
328 EXPECT_EQ(151, Vec.find_last_unset_in(100, 153));
329 EXPECT_EQ(153, Vec.find_last_unset_in(100, 154));
330 EXPECT_EQ(153, Vec.find_last_unset_in(100, 155));
331 EXPECT_EQ(155, Vec.find_last_unset_in(100, 156));
332 EXPECT_EQ(199, Vec.find_last_unset_in(199, 200));
333 }
334
335 TEST(BitVectorTest, FindInRangeSingleWord) {
336 // When the bit vector contains only a single word, this is slightly different
337 // than when the bit vector contains multiple words, because masks are applied
338 // to the front and back of the same word. So make sure this works.
339 BitVector Vec;
340
341 Vec.resize(25);
342 Vec.set(2, 4);
343 Vec.set(6, 9);
344 Vec.set(12, 15);
345 Vec.set(19);
346 Vec.set(21);
347 Vec.set(23);
348
349 // find first
350 EXPECT_EQ(-1, Vec.find_first_in(0, 0));
351 EXPECT_EQ(-1, Vec.find_first_in(24, 24));
352 EXPECT_EQ(-1, Vec.find_first_in(9, 12));
353
354 EXPECT_EQ(2, Vec.find_first_in(0, 10));
355 EXPECT_EQ(6, Vec.find_first_in(4, 10));
356 EXPECT_EQ(19, Vec.find_first_in(18, 25));
357 EXPECT_EQ(21, Vec.find_first_in(20, 25));
358 EXPECT_EQ(23, Vec.find_first_in(22, 25));
359 EXPECT_EQ(-1, Vec.find_first_in(24, 25));
360
361 // find last
362 EXPECT_EQ(-1, Vec.find_last_in(0, 0));
363 EXPECT_EQ(-1, Vec.find_last_in(24, 24));
364 EXPECT_EQ(-1, Vec.find_last_in(9, 12));
365
366 EXPECT_EQ(8, Vec.find_last_in(0, 10));
367 EXPECT_EQ(3, Vec.find_last_in(0, 6));
368 EXPECT_EQ(23, Vec.find_last_in(18, 25));
369 EXPECT_EQ(21, Vec.find_last_in(18, 23));
370 EXPECT_EQ(19, Vec.find_last_in(18, 21));
371 EXPECT_EQ(-1, Vec.find_last_in(18, 19));
372
373 // find first unset
374 EXPECT_EQ(-1, Vec.find_first_unset_in(0, 0));
375 EXPECT_EQ(-1, Vec.find_first_unset_in(23, 23));
376 EXPECT_EQ(-1, Vec.find_first_unset_in(6, 9));
377
378 EXPECT_EQ(0, Vec.find_first_unset_in(0, 6));
379 EXPECT_EQ(1, Vec.find_first_unset_in(1, 6));
380 EXPECT_EQ(9, Vec.find_first_unset_in(7, 13));
381 EXPECT_EQ(18, Vec.find_first_unset_in(18, 25));
382 EXPECT_EQ(20, Vec.find_first_unset_in(19, 25));
383 EXPECT_EQ(20, Vec.find_first_unset_in(20, 25));
384 EXPECT_EQ(22, Vec.find_first_unset_in(21, 25));
385 EXPECT_EQ(22, Vec.find_first_unset_in(22, 25));
386 EXPECT_EQ(24, Vec.find_first_unset_in(23, 25));
387 EXPECT_EQ(24, Vec.find_first_unset_in(24, 25));
388
389 // find last unset
390 EXPECT_EQ(-1, Vec.find_last_unset_in(0, 0));
391 EXPECT_EQ(-1, Vec.find_last_unset_in(23, 23));
392 EXPECT_EQ(-1, Vec.find_last_unset_in(6, 9));
393
394 EXPECT_EQ(5, Vec.find_last_unset_in(0, 6));
395 EXPECT_EQ(4, Vec.find_last_unset_in(0, 5));
396 EXPECT_EQ(1, Vec.find_last_unset_in(0, 4));
397 EXPECT_EQ(11, Vec.find_last_unset_in(7, 13));
398 EXPECT_EQ(24, Vec.find_last_unset_in(18, 25));
399 EXPECT_EQ(22, Vec.find_last_unset_in(18, 24));
400 EXPECT_EQ(22, Vec.find_last_unset_in(18, 23));
401 EXPECT_EQ(20, Vec.find_last_unset_in(18, 22));
402 EXPECT_EQ(20, Vec.find_last_unset_in(18, 21));
403 EXPECT_EQ(18, Vec.find_last_unset_in(18, 20));
404 EXPECT_EQ(18, Vec.find_last_unset_in(18, 19));
258405 }
259406
260407 TYPED_TEST(BitVectorTest, CompoundAssignment) {