Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
bitset.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Various utility functions on bitsets.
15
16#ifndef OR_TOOLS_UTIL_BITSET_H_
17#define OR_TOOLS_UTIL_BITSET_H_
18
19#include <string.h>
20
21#include <algorithm>
22#include <cstddef>
23#include <cstdint>
24#include <iterator>
25#include <string>
26#include <tuple>
27#include <vector>
28
29#include "absl/log/check.h"
31
32namespace operations_research {
33
34// Basic bit operations
35
36// Useful constants: word and double word will all bits set.
37static const uint64_t kAllBits64 = uint64_t{0xFFFFFFFFFFFFFFFF};
38static const uint64_t kAllBitsButLsb64 = uint64_t{0xFFFFFFFFFFFFFFFE};
39static const uint32_t kAllBits32 = 0xFFFFFFFFU;
40
41// Returns a word with only bit pos set.
42inline uint64_t OneBit64(int pos) { return uint64_t{1} << pos; }
43inline uint32_t OneBit32(int pos) { return 1U << pos; }
44
45// Returns the number of bits set in n.
46inline uint64_t BitCount64(uint64_t n) {
47 const uint64_t m1 = uint64_t{0x5555555555555555};
48 const uint64_t m2 = uint64_t{0x3333333333333333};
49 const uint64_t m4 = uint64_t{0x0F0F0F0F0F0F0F0F};
50 const uint64_t h01 = uint64_t{0x0101010101010101};
51 n -= (n >> 1) & m1;
52 n = (n & m2) + ((n >> 2) & m2);
53 n = (n + (n >> 4)) & m4;
54 n = (n * h01) >> 56;
55 return n;
56}
57inline uint32_t BitCount32(uint32_t n) {
58 n -= (n >> 1) & 0x55555555UL;
59 n = (n & 0x33333333) + ((n >> 2) & 0x33333333UL);
60 n = (n + (n >> 4)) & 0x0F0F0F0FUL;
61 n = n + (n >> 8);
62 n = n + (n >> 16);
63 return n & 0x0000003FUL;
64}
65
66// Returns a word with only the least significant bit of n set.
67inline uint64_t LeastSignificantBitWord64(uint64_t n) { return n & ~(n - 1); }
68inline uint32_t LeastSignificantBitWord32(uint32_t n) { return n & ~(n - 1); }
69
70// Returns the least significant bit position in n.
71// Discussion around lsb computation:
72// De Bruijn is almost as fast as the bsr/bsf-instruction-based intrinsics.
73// Both are always much faster than the Default algorithm.
74#define USE_DEBRUIJN true // if true, use de Bruijn bit forward scanner.
75#if defined(__GNUC__) || defined(__llvm__)
76#define USE_FAST_LEAST_SIGNIFICANT_BIT true // if true, use fast lsb.
77#endif
78
79#if defined(USE_FAST_LEAST_SIGNIFICANT_BIT)
80inline int LeastSignificantBitPosition64Fast(uint64_t n) {
81 return __builtin_ctzll(n);
82}
83#endif
84
86 static const uint64_t kSeq = uint64_t{0x0218a392dd5fb34f};
87 static const int kTab[64] = {
88 // initialized by 'kTab[(kSeq << i) >> 58] = i
89 0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 52, 20, 58,
90 5, 17, 26, 56, 15, 38, 29, 40, 10, 49, 53, 31, 21, 34, 59, 42,
91 63, 6, 12, 18, 24, 27, 51, 57, 16, 55, 37, 39, 48, 30, 33, 41,
92 62, 11, 23, 50, 54, 36, 47, 32, 61, 22, 35, 46, 60, 45, 44, 43,
93 };
94 return kTab[((n & (~n + 1)) * kSeq) >> 58];
95}
96
98 DCHECK_NE(n, 0);
99 int pos = 63;
100 if (n & 0x00000000FFFFFFFFLL) {
101 pos -= 32;
102 } else {
103 n >>= 32;
104 }
105 if (n & 0x000000000000FFFFLL) {
106 pos -= 16;
107 } else {
108 n >>= 16;
109 }
110 if (n & 0x00000000000000FFLL) {
111 pos -= 8;
112 } else {
113 n >>= 8;
114 }
115 if (n & 0x000000000000000FLL) {
116 pos -= 4;
117 } else {
118 n >>= 4;
119 }
120 if (n & 0x0000000000000003LL) {
121 pos -= 2;
122 } else {
123 n >>= 2;
124 }
125 if (n & 0x0000000000000001LL) {
126 pos -= 1;
127 }
128 return pos;
129}
130
131inline int LeastSignificantBitPosition64(uint64_t n) {
132 DCHECK_NE(n, 0);
133#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
134 return LeastSignificantBitPosition64Fast(n);
135#elif defined(USE_DEBRUIJN)
137#else
139#endif
140}
141
142#if defined(USE_FAST_LEAST_SIGNIFICANT_BIT)
143inline int LeastSignificantBitPosition32Fast(uint32_t n) {
144 return __builtin_ctzl(n);
145}
146#endif
147
149 static const uint32_t kSeq = 0x077CB531U; // de Bruijn sequence
150 static const int kTab[32] = {// initialized by 'kTab[(kSeq << i) >> 27] = i
151 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20,
152 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19,
153 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
154 return kTab[((n & (~n + 1)) * kSeq) >> 27];
155}
156
158 DCHECK_NE(n, 0);
159 int pos = 31;
160 if (n & 0x0000FFFFL) {
161 pos -= 16;
162 } else {
163 n >>= 16;
164 }
165 if (n & 0x000000FFL) {
166 pos -= 8;
167 } else {
168 n >>= 8;
169 }
170 if (n & 0x0000000FL) {
171 pos -= 4;
172 } else {
173 n >>= 4;
174 }
175 if (n & 0x00000003L) {
176 pos -= 2;
177 } else {
178 n >>= 2;
179 }
180 if (n & 0x00000001L) {
181 pos -= 1;
182 }
183 return pos;
184}
185
186inline int LeastSignificantBitPosition32(uint32_t n) {
187 DCHECK_NE(n, 0);
188#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
189 return LeastSignificantBitPosition32Fast(n);
190#elif defined(USE_DEBRUIJN)
192#else
194#endif
195}
196
197// Returns the most significant bit position in n.
198#if USE_FAST_LEAST_SIGNIFICANT_BIT
199inline int MostSignificantBitPosition64Fast(uint64_t n) {
200 // __builtin_clzll(1) should always return 63. There is no penalty in
201 // using offset, and the code looks more like its uint32_t counterpart.
202 const int offset = __builtin_clzll(1);
203 return n == 0 ? 0 : (offset - __builtin_clzll(n));
204}
205#endif
206
208 int b = 0;
209 if (0 != (n & (kAllBits64 << (1 << 5)))) {
210 b |= (1 << 5);
211 n >>= (1 << 5);
212 }
213 if (0 != (n & (kAllBits64 << (1 << 4)))) {
214 b |= (1 << 4);
215 n >>= (1 << 4);
216 }
217 if (0 != (n & (kAllBits64 << (1 << 3)))) {
218 b |= (1 << 3);
219 n >>= (1 << 3);
220 }
221 if (0 != (n & (kAllBits64 << (1 << 2)))) {
222 b |= (1 << 2);
223 n >>= (1 << 2);
224 }
225 if (0 != (n & (kAllBits64 << (1 << 1)))) {
226 b |= (1 << 1);
227 n >>= (1 << 1);
228 }
229 if (0 != (n & (kAllBits64 << (1 << 0)))) {
230 b |= (1 << 0);
231 }
232 return b;
233}
234
235inline int MostSignificantBitPosition64(uint64_t n) {
236#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
237 return MostSignificantBitPosition64Fast(n);
238#else
240#endif
241}
242
243#if USE_FAST_LEAST_SIGNIFICANT_BIT
244inline int MostSignificantBitPosition32Fast(uint32_t n) {
245 // The constant here depends on whether we are on a 32-bit or 64-bit machine.
246 // __builtin_clzl(1) returns 63 on a 64-bit machine and 31 on a 32-bit
247 // machine.
248 const int offset = __builtin_clzl(1);
249 return n == 0 ? 0 : (offset - __builtin_clzl(n));
250}
251#endif
252
254 int b = 0;
255 if (0 != (n & (kAllBits32 << (1 << 4)))) {
256 b |= (1 << 4);
257 n >>= (1 << 4);
258 }
259 if (0 != (n & (kAllBits32 << (1 << 3)))) {
260 b |= (1 << 3);
261 n >>= (1 << 3);
262 }
263 if (0 != (n & (kAllBits32 << (1 << 2)))) {
264 b |= (1 << 2);
265 n >>= (1 << 2);
266 }
267 if (0 != (n & (kAllBits32 << (1 << 1)))) {
268 b |= (1 << 1);
269 n >>= (1 << 1);
270 }
271 if (0 != (n & (kAllBits32 << (1 << 0)))) {
272 b |= (1 << 0);
273 }
274 return b;
275}
276
277inline int MostSignificantBitPosition32(uint32_t n) {
278#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
279 return MostSignificantBitPosition32Fast(n);
280#else
282#endif
283}
284
285#undef USE_DEBRUIJN
286#undef USE_FAST_LEAST_SIGNIFICANT_BIT
287
288// Returns a word with bits from s to e set.
289inline uint64_t OneRange64(uint64_t s, uint64_t e) {
290 DCHECK_LE(s, 63);
291 DCHECK_LE(e, 63);
292 DCHECK_LE(s, e);
293 return (kAllBits64 << s) ^ ((kAllBits64 - 1) << e);
294}
295
296inline uint32_t OneRange32(uint32_t s, uint32_t e) {
297 DCHECK_LE(s, 31);
298 DCHECK_LE(e, 31);
299 DCHECK_LE(s, e);
300 return (kAllBits32 << s) ^ ((kAllBits32 - 1) << e);
301}
302
303// Returns a word with s least significant bits unset.
304inline uint64_t IntervalUp64(uint64_t s) {
305 DCHECK_LE(s, 63);
306 return kAllBits64 << s;
307}
308
309inline uint32_t IntervalUp32(uint32_t s) {
310 DCHECK_LE(s, 31);
311 return kAllBits32 << s;
312}
313
314// Returns a word with the s most significant bits unset.
315inline uint64_t IntervalDown64(uint64_t s) {
316 DCHECK_LE(s, 63);
317 return kAllBits64 >> (63 - s);
318}
319
320inline uint32_t IntervalDown32(uint32_t s) {
321 DCHECK_LE(s, 31);
322 return kAllBits32 >> (31 - s);
323}
324
325// ----- Bitset operators -----
326// Bitset: array of uint32_t/uint64_t words
327
328// Bit operators used to manipulates bitsets.
329
330// Returns the bit number in the word computed by BitOffsetXX,
331// corresponding to the bit at position pos in the bitset.
332// Note: '& 63' is faster than '% 64'
333// TODO(user): rename BitPos and BitOffset to something more understandable.
334inline uint32_t BitPos64(uint64_t pos) { return (pos & 63); }
335inline uint32_t BitPos32(uint32_t pos) { return (pos & 31); }
336
337// Returns the word number corresponding to bit number pos.
338inline uint64_t BitOffset64(uint64_t pos) { return (pos >> 6); }
339inline uint32_t BitOffset32(uint32_t pos) { return (pos >> 5); }
340
341// Returns the number of words needed to store size bits.
342inline uint64_t BitLength64(uint64_t size) { return ((size + 63) >> 6); }
343inline uint32_t BitLength32(uint32_t size) { return ((size + 31) >> 5); }
344
345// Returns the bit number in the bitset of the first bit of word number v.
346inline uint64_t BitShift64(uint64_t v) { return v << 6; }
347inline uint32_t BitShift32(uint32_t v) { return v << 5; }
348
349// Returns true if the bit pos is set in bitset.
350inline bool IsBitSet64(const uint64_t* const bitset, uint64_t pos) {
351 return (bitset[BitOffset64(pos)] & OneBit64(BitPos64(pos)));
352}
353inline bool IsBitSet32(const uint32_t* const bitset, uint32_t pos) {
354 return (bitset[BitOffset32(pos)] & OneBit32(BitPos32(pos)));
355}
356
357// Sets the bit pos to true in bitset.
358inline void SetBit64(uint64_t* const bitset, uint64_t pos) {
359 bitset[BitOffset64(pos)] |= OneBit64(BitPos64(pos));
360}
361inline void SetBit32(uint32_t* const bitset, uint32_t pos) {
362 bitset[BitOffset32(pos)] |= OneBit32(BitPos32(pos));
363}
364
365// Sets the bit pos to false in bitset.
366inline void ClearBit64(uint64_t* const bitset, uint64_t pos) {
367 bitset[BitOffset64(pos)] &= ~OneBit64(BitPos64(pos));
368}
369inline void ClearBit32(uint32_t* const bitset, uint32_t pos) {
370 bitset[BitOffset32(pos)] &= ~OneBit32(BitPos32(pos));
371}
372
373// Returns the number of bits set in bitset between positions start and end.
374uint64_t BitCountRange64(const uint64_t* bitset, uint64_t start, uint64_t end);
375uint32_t BitCountRange32(const uint32_t* bitset, uint32_t start, uint32_t end);
376
377// Returns true if no bits are set in bitset between start and end.
378bool IsEmptyRange64(const uint64_t* bitset, uint64_t start, uint64_t end);
379bool IsEmptyRange32(const uint32_t* bitset, uint32_t start, uint32_t end);
380
381// Returns the first bit set in bitset between start and max_bit.
382int64_t LeastSignificantBitPosition64(const uint64_t* bitset, uint64_t start,
383 uint64_t end);
384int LeastSignificantBitPosition32(const uint32_t* bitset, uint32_t start,
385 uint32_t end);
386
387// Returns the last bit set in bitset between min_bit and start.
388int64_t MostSignificantBitPosition64(const uint64_t* bitset, uint64_t start,
389 uint64_t end);
390int MostSignificantBitPosition32(const uint32_t* bitset, uint32_t start,
391 uint32_t end);
392
393// Unsafe versions of the functions above where respectively end and start
394// are supposed to be set.
395int64_t UnsafeLeastSignificantBitPosition64(const uint64_t* bitset,
396 uint64_t start, uint64_t end);
397int32_t UnsafeLeastSignificantBitPosition32(const uint32_t* bitset,
398 uint32_t start, uint32_t end);
399
400int64_t UnsafeMostSignificantBitPosition64(const uint64_t* bitset,
401 uint64_t start, uint64_t end);
402int32_t UnsafeMostSignificantBitPosition32(const uint32_t* bitset,
403 uint32_t start, uint32_t end);
404
405// Returns a mask with the bits pos % 64 and (pos ^ 1) % 64 sets.
406inline uint64_t TwoBitsFromPos64(uint64_t pos) {
407 return uint64_t{3} << (pos & 62);
408}
409
410// This class is like an ITIVector<IndexType, bool> except that it provides a
411// more efficient way to iterate over the positions set to true. It achieves
412// this by caching the current uint64_t bucket in the Iterator and using
413// LeastSignificantBitPosition64() to iterate over the positions at 1 in this
414// bucket.
415template <typename IndexType = int64_t>
416class Bitset64 {
417 public:
418 using value_type = IndexType;
419
420 // When speed matter, caching the base pointer helps.
421 class ConstView {
422 public:
423 explicit ConstView(const Bitset64* bitset) : data_(bitset->data_.data()) {}
424
425 bool operator[](IndexType i) const {
426 return data_[BitOffset64(Value(i))] & OneBit64(BitPos64(Value(i)));
427 }
428
429 const uint64_t* data() const { return data_; }
430
431 private:
432 const uint64_t* const data_;
433 };
434
435 class View {
436 public:
437 explicit View(Bitset64* bitset) : data_(bitset->data_.data()) {}
438
439 bool operator[](IndexType i) const {
440 return data_[BitOffset64(Value(i))] & OneBit64(BitPos64(Value(i)));
441 }
442
443 void Clear(IndexType i) {
444 data_[BitOffset64(Value(i))] &= ~OneBit64(BitPos64(Value(i)));
445 }
446
447 void Set(IndexType i) {
448 data_[BitOffset64(Value(i))] |= OneBit64(BitPos64(Value(i)));
449 }
450
451 private:
452 uint64_t* const data_;
453 };
454
455 Bitset64() : size_(), data_() {}
456 explicit Bitset64(IndexType size)
457 : size_(Value(size) > 0 ? size : IndexType(0)),
458 data_(BitLength64(Value(size_))) {}
459
460 ConstView const_view() const { return ConstView(this); }
461 View view() { return View(this); }
462
463 // Returns how many bits this Bitset64 can hold.
464 IndexType size() const { return size_; }
465
466 // Appends value at the end of the bitset.
467 void PushBack(bool value) {
468 ++size_;
469 data_.resize(BitLength64(Value(size_)), 0);
470 Set(size_ - 1, value);
471 }
472
473 // Resizes the Bitset64 to the given number of bits. New bits are sets to 0.
474 void resize(int size) { Resize(IndexType(size)); }
475 void Resize(IndexType size) {
476 DCHECK_GE(Value(size), 0);
477 IndexType new_size = Value(size) > 0 ? size : IndexType(0);
478 if (new_size < size_ && Value(new_size) > 0) {
479 const int64_t new_data_size = BitLength64(Value(new_size));
480 const uint64_t bitmask = kAllBitsButLsb64
481 << BitPos64(Value(new_size) - 1);
482 data_[new_data_size - 1] &= ~bitmask;
483 }
484 size_ = new_size;
485 data_.resize(BitLength64(Value(size_)), 0);
486 }
487
488 // Changes the number of bits the Bitset64 can hold and set all of them to 0.
489 void ClearAndResize(IndexType size) {
490 DCHECK_GE(Value(size), 0);
491 size_ = Value(size) > 0 ? size : IndexType(0);
492
493 // Memset is 4x faster than data_.assign() as of 19/03/2014.
494 // TODO(user): Ideally if a realloc happens, we don't need to copy the old
495 // data...
496 const size_t bit_length = static_cast<size_t>(BitLength64(Value(size_)));
497 const size_t to_clear = std::min(data_.size(), bit_length);
498 data_.resize(bit_length, 0);
499 memset(data_.data(), 0, to_clear * sizeof(int64_t));
500 }
501
502 // Sets all bits to 0.
503 void ClearAll() { memset(data_.data(), 0, data_.size() * sizeof(int64_t)); }
504
505 // Sets the bit at position i to 0.
506 void Clear(IndexType i) {
507 DCHECK_GE(Value(i), 0);
508 DCHECK_LT(Value(i), Value(size_));
509 data_.data()[BitOffset64(Value(i))] &= ~OneBit64(BitPos64(Value(i)));
510 }
511
512 // Sets bucket containing bit i to 0.
513 void ClearBucket(IndexType i) {
514 DCHECK_GE(Value(i), 0);
515 DCHECK_LT(Value(i), Value(size_));
516 data_.data()[BitOffset64(Value(i))] = 0;
517 }
518
519 // Clears the bits at position i and i ^ 1.
520 void ClearTwoBits(IndexType i) {
521 DCHECK_GE(Value(i), 0);
522 DCHECK_LT(Value(i), Value(size_));
523 data_[BitOffset64(Value(i))] &= ~TwoBitsFromPos64(Value(i));
524 }
525
526 // Returns true if the bit at position i or the one at position i ^ 1 is set.
527 bool AreOneOfTwoBitsSet(IndexType i) const {
528 DCHECK_GE(Value(i), 0);
529 DCHECK_LT(Value(i), Value(size_));
530 return data_.data()[BitOffset64(Value(i))] & TwoBitsFromPos64(Value(i));
531 }
532
533 // Returns true if the bit at position i is set.
534 bool IsSet(IndexType i) const {
535 DCHECK_GE(Value(i), 0);
536 DCHECK_LT(Value(i), Value(size_));
537 return data_.data()[BitOffset64(Value(i))] & OneBit64(BitPos64(Value(i)));
538 }
539
540 // Same as IsSet().
541 bool operator[](IndexType i) const { return IsSet(i); }
542
543 // Sets the bit at position i to 1.
544 void Set(IndexType i) {
545 DCHECK_GE(Value(i), 0);
546 DCHECK_LT(Value(i), size_);
547 // The c++ hardening is costly here, so we disable it.
548 data_.data()[BitOffset64(Value(i))] |= OneBit64(BitPos64(Value(i)));
549 }
550
551 // If value is true, sets the bit at position i to 1, sets it to 0 otherwise.
552 void Set(IndexType i, bool value) {
553 if (value) {
554 Set(i);
555 } else {
556 Clear(i);
557 }
558 }
559
560 // Copies bucket containing bit i from "other" to "this".
561 void CopyBucket(const Bitset64<IndexType>& other, IndexType i) {
562 const uint64_t offset = BitOffset64(Value(i));
563 data_[offset] = other.data_[offset];
564 }
565
566 // Copies "other" to "this". The bitsets do not have to be of the same size.
567 // If "other" is smaller, high order bits are not changed. If "other" is
568 // larger, its high order bits are ignored. In any case "this" is not resized.
569 template <typename OtherIndexType>
571 const int64_t min_size = std::min(data_.size(), other.data_.size());
572 if (min_size == 0) return;
573 const uint64_t last_common_bucket = data_[min_size - 1];
574 memcpy(data_.data(), other.data_.data(), min_size * sizeof(uint64_t));
575 if (data_.size() >= other.data_.size()) {
576 const uint64_t bitmask = kAllBitsButLsb64
577 << BitPos64(other.Value(other.size() - 1));
578 data_[min_size - 1] &= ~bitmask;
579 data_[min_size - 1] |= (bitmask & last_common_bucket);
580 }
581 }
582
583 // Same as SetContentFromBitset where "this" and "other" have the same size.
584 template <typename OtherIndexType>
586 DCHECK_EQ(Value(size()), other.Value(other.size()));
587 memcpy(data_.data(), other.data_.data(), data_.size() * sizeof(uint64_t));
588 }
589
590 // Sets "this" to be the intersection of "this" and "other". The
591 // bitsets do not have to be the same size. If other is smaller, all
592 // the higher order bits are assumed to be 0.
594 const int min_size = std::min(data_.size(), other.data_.size());
595 uint64_t* const d = data_.data();
596 const uint64_t* const o = other.data_.data();
597 for (int i = 0; i < min_size; ++i) {
598 d[i] &= o[i];
599 }
600 for (int i = min_size; i < data_.size(); ++i) {
601 d[i] = 0;
602 }
603 }
604
605 // This one assume both given bitset to be of the same size.
607 const Bitset64<IndexType>& b) {
608 DCHECK_EQ(a.size(), b.size());
609 Resize(a.size());
610
611 // Copy buckets.
612 const int num_buckets = a.data_.size();
613 for (int i = 0; i < num_buckets; ++i) {
614 data_[i] = a.data_[i] & b.data_[i];
615 }
616 }
617
618 // Sets "this" to be the union of "this" and "other". The
619 // bitsets do not have to be the same size. If other is smaller, all
620 // the higher order bits are assumed to be 0.
621 void Union(const Bitset64<IndexType>& other) {
622 const int min_size = std::min(data_.size(), other.data_.size());
623 for (int i = 0; i < min_size; ++i) {
624 data_[i] |= other.data_[i];
625 }
626 }
627
628 // Class to iterate over the bit positions at 1 of a Bitset64.
629 //
630 // IMPORTANT: Because the iterator "caches" the current uint64_t bucket, this
631 // will probably not do what you want if Bitset64 is modified while iterating.
632 class Iterator {
633 public:
634 // Make this iterator a std::forward_iterator, so it works with std::sample,
635 // std::max_element, etc.
636 Iterator() : data_(nullptr), size_(0) {}
637 Iterator(Iterator&& other) = default;
638 Iterator(const Iterator& other) = default;
639 Iterator& operator=(const Iterator& other) = default;
640 using difference_type = std::ptrdiff_t;
641 using iterator_category = std::forward_iterator_tag;
642 using value_type = IndexType;
643 using size_type = std::size_t;
646
647 explicit Iterator(const Bitset64& bitset)
648 : data_(bitset.data_.data()), size_(bitset.data_.size()) {
649 if (!bitset.data_.empty()) {
650 current_ = data_[0];
651 this->operator++();
652 }
653 }
654
655 static Iterator EndIterator(const Bitset64& bitset) {
656 return Iterator(bitset.data_.data());
657 }
658
659 bool operator==(const Iterator& other) const { return !(*this != other); }
660 bool operator!=(const Iterator& other) const {
661 if (other.size_ == 0) {
662 return size_ != 0;
663 }
664 return std::tie(index_, current_) !=
665 std::tie(other.index_, other.current_);
666 }
667
668 IndexType operator*() const { return IndexType(index_); }
669
671 Iterator other = *this;
672 ++(*this);
673 return other;
674 }
675
677 int bucket = BitOffset64(index_);
678 while (current_ == 0) {
679 bucket++;
680 if (bucket == size_) {
681 size_ = 0;
682 return *this;
683 }
684 current_ = data_[bucket];
685 }
686
687 // Computes the index and clear the least significant bit of current_.
688 index_ = BitShift64(bucket) | LeastSignificantBitPosition64(current_);
689 current_ &= current_ - 1;
690 return *this;
691 }
692
693 private:
694 explicit Iterator(const uint64_t* data) : data_(data), size_(0) {}
695
696 const uint64_t* data_;
697 int size_;
698 int index_ = 0;
699 uint64_t current_ = 0;
700 };
701
702 // Allows range-based "for" loop on the non-zero positions:
703 // for (const IndexType index : bitset) {}
704 Iterator begin() const { return Iterator(*this); }
705 Iterator end() const { return Iterator::EndIterator(*this); }
706
707 // Cryptic function! This is just an optimized version of a given piece of
708 // code and has probably little general use.
709 static uint64_t ConditionalXorOfTwoBits(IndexType i, uint64_t use1,
711 uint64_t use2,
713 DCHECK(use1 == 0 || use1 == 1);
714 DCHECK(use2 == 0 || use2 == 1);
715 const int bucket = BitOffset64(Value(i));
716 const int pos = BitPos64(Value(i));
717 return ((use1 << pos) & set1.data()[bucket]) ^
718 ((use2 << pos) & set2.data()[bucket]);
719 }
720
721 // Returns a 0/1 string representing the bitset.
722 std::string DebugString() const {
723 std::string output;
724 for (IndexType i(0); i < size(); ++i) {
725 output += IsSet(i) ? "1" : "0";
726 }
727 return output;
728 }
729
730 bool IsAllFalse() const {
731 return std::all_of(data_.begin(), data_.end(),
732 [](uint64_t v) { return v == 0; });
733 }
734
735 private:
736 // Returns the value of the index type.
737 // This function is specialized below to work with IntType and int64_t.
738 static int Value(IndexType input);
739
740 IndexType size_;
741 std::vector<uint64_t> data_;
742
743 template <class OtherIndexType>
744 friend class Bitset64;
745};
746
747// Specialized version of Bitset64 that allows to query the last bit set more
748// efficiently.
750 public:
751 BitQueue64() : size_(), top_(-1), data_() {}
752 explicit BitQueue64(int size)
753 : size_(size), top_(-1), data_(BitLength64(size), 0) {}
754
755 // This type is neither copyable nor movable.
756 BitQueue64(const BitQueue64&) = delete;
757 BitQueue64& operator=(const BitQueue64&) = delete;
758
759 void IncreaseSize(int size) {
760 CHECK_GE(size, size_);
761 size_ = size;
762 data_.resize(BitLength64(size), 0);
763 }
764
765 void ClearAndResize(int size) {
766 top_ = -1;
767 size_ = size;
768 data_.assign(BitLength64(size), 0);
769 }
770
771 void Set(int i) {
772 DCHECK_GE(i, 0);
773 DCHECK_LT(i, size_);
774 top_ = std::max(top_, i);
775 data_[BitOffset64(i)] |= OneBit64(BitPos64(i));
776 }
777
778 // Sets all the bits from 0 up to i-1 to 1.
779 void SetAllBefore(int i) {
780 DCHECK_GE(i, 0);
781 DCHECK_LT(i, size_);
782 top_ = std::max(top_, i - 1);
783 int bucket_index = static_cast<int>(BitOffset64(i));
784 data_[bucket_index] |= OneBit64(BitPos64(i)) - 1;
785 for (--bucket_index; bucket_index >= 0; --bucket_index) {
786 data_[bucket_index] = kAllBits64;
787 }
788 }
789
790 // Returns the position of the highest bit set in O(1) or -1 if no bit is set.
791 int Top() const { return top_; }
792
793 // Clears the Top() bit and recomputes the position of the next Top().
794 void ClearTop() {
795 DCHECK_NE(top_, -1);
796 int bucket_index = static_cast<int>(BitOffset64(top_));
797 uint64_t bucket = data_[bucket_index] &= ~OneBit64(BitPos64(top_));
798 while (!bucket) {
799 if (bucket_index == 0) {
800 top_ = -1;
801 return;
802 }
803 bucket = data_[--bucket_index];
804 }
805
806 // Note(user): I experimented with reversing the bit order in a bucket to
807 // use LeastSignificantBitPosition64() and it is only slightly faster at the
808 // cost of a lower Set() speed. So I preferred this version.
809 top_ = static_cast<int>(BitShift64(bucket_index) +
811 }
812
813 private:
814 int size_;
815 int top_;
816 std::vector<uint64_t> data_;
817};
818
819// The specialization of Value() for IntType and int64_t.
820template <typename IntType>
821inline int Bitset64<IntType>::Value(IntType input) {
822 DCHECK_GE(input.value(), 0);
823 return input.value();
824}
825template <>
826inline int Bitset64<int>::Value(int input) {
827 DCHECK_GE(input, 0);
828 return input;
829}
830template <>
831inline int Bitset64<int64_t>::Value(int64_t input) {
832 DCHECK_GE(input, 0);
833 return input;
834}
835template <>
836inline int Bitset64<size_t>::Value(size_t input) {
837 return input;
838}
839
840// A simple utility class to set/unset integer in a range [0, size).
841// This is optimized for sparsity.
842template <typename IntegerType = int64_t>
844 public:
846 explicit SparseBitset(IntegerType size) : bitset_(size) {}
847
848 // This type is neither copyable nor movable.
849 SparseBitset(const SparseBitset&) = delete;
851 IntegerType size() const { return bitset_.size(); }
853 for (const IntegerType i : to_clear_) bitset_.ClearBucket(i);
854 to_clear_.clear();
855 }
856 void ClearAll() {
857 bitset_.ClearAll();
858 to_clear_.clear();
859 }
860 void ClearAndResize(IntegerType size) {
861 // As of 19/03/2014, experiments show that this is a reasonable threshold.
862 const int kSparseThreshold = 300;
863 if (to_clear_.size() * kSparseThreshold < size) {
865 bitset_.Resize(size);
866 } else {
867 bitset_.ClearAndResize(size);
868 to_clear_.clear();
869 }
870 }
871 void Resize(IntegerType size) {
872 if (size < bitset_.size()) {
873 int new_index = 0;
874 for (IntegerType index : to_clear_) {
875 if (index < size) {
876 to_clear_[new_index] = index;
877 ++new_index;
878 }
879 }
880 to_clear_.resize(new_index);
881 }
882 bitset_.Resize(size);
883 }
884 bool operator[](IntegerType index) const { return bitset_[index]; }
885 void Set(IntegerType index) {
886 if (!bitset_[index]) {
887 bitset_.Set(index);
888 to_clear_.push_back(index);
889 }
890 }
891
892 // A bit hacky for really hot loop.
893 typename Bitset64<IntegerType>::View BitsetView() { return bitset_.view(); }
894 void SetUnsafe(typename Bitset64<IntegerType>::View view, IntegerType index) {
895 view.Set(index);
896 to_clear_.push_back(index);
897 }
898
899 void Clear(IntegerType index) { bitset_.Clear(index); }
901 return to_clear_.size();
902 }
903 const std::vector<IntegerType>& PositionsSetAtLeastOnce() const {
904 return to_clear_;
905 }
906
907 // Tells the class that all its bits are cleared, so it can reset to_clear_
908 // to the empty vector. Note that this call is "unsafe" since the fact that
909 // the class is actually all cleared is only checked in debug mode.
910 //
911 // This is useful to iterate on the "set" positions while clearing them for
912 // instance. This way, after the loop, a client can call this for efficiency.
914 if (DEBUG_MODE) {
915 for (IntegerType index : to_clear_) CHECK(!bitset_[index]);
916 }
917 to_clear_.clear();
918 }
919
921 return bitset_.const_view();
922 }
923
924 private:
925 Bitset64<IntegerType> bitset_;
926 std::vector<IntegerType> to_clear_;
927};
928
929} // namespace operations_research
930
931#endif // OR_TOOLS_UTIL_BITSET_H_
int Top() const
Returns the position of the highest bit set in O(1) or -1 if no bit is set.
Definition bitset.h:791
void ClearAndResize(int size)
Definition bitset.h:765
void ClearTop()
Clears the Top() bit and recomputes the position of the next Top().
Definition bitset.h:794
BitQueue64(const BitQueue64 &)=delete
This type is neither copyable nor movable.
void IncreaseSize(int size)
Definition bitset.h:759
BitQueue64 & operator=(const BitQueue64 &)=delete
void SetAllBefore(int i)
Sets all the bits from 0 up to i-1 to 1.
Definition bitset.h:779
When speed matter, caching the base pointer helps.
Definition bitset.h:421
const uint64_t * data() const
Definition bitset.h:429
bool operator[](IndexType i) const
Definition bitset.h:425
ConstView(const Bitset64 *bitset)
Definition bitset.h:423
Iterator(const Iterator &other)=default
bool operator==(const Iterator &other) const
Definition bitset.h:659
bool operator!=(const Iterator &other) const
Definition bitset.h:660
std::forward_iterator_tag iterator_category
Definition bitset.h:641
Iterator(Iterator &&other)=default
Iterator & operator=(const Iterator &other)=default
static Iterator EndIterator(const Bitset64 &bitset)
Definition bitset.h:655
Iterator(const Bitset64 &bitset)
Definition bitset.h:647
bool operator[](IndexType i) const
Definition bitset.h:439
void CopyBucket(const Bitset64< IndexType > &other, IndexType i)
Copies bucket containing bit i from "other" to "this".
Definition bitset.h:561
void ClearAll()
Sets all bits to 0.
Definition bitset.h:503
void ClearBucket(IndexType i)
Sets bucket containing bit i to 0.
Definition bitset.h:513
void SetContentFromBitset(const Bitset64< OtherIndexType > &other)
Definition bitset.h:570
bool IsSet(IndexType i) const
Returns true if the bit at position i is set.
Definition bitset.h:534
void Clear(IndexType i)
Sets the bit at position i to 0.
Definition bitset.h:506
void Set(IndexType i, bool value)
If value is true, sets the bit at position i to 1, sets it to 0 otherwise.
Definition bitset.h:552
void Union(const Bitset64< IndexType > &other)
Definition bitset.h:621
void Intersection(const Bitset64< IndexType > &other)
Definition bitset.h:593
Iterator end() const
Definition bitset.h:705
Iterator begin() const
Definition bitset.h:704
void resize(int size)
Resizes the Bitset64 to the given number of bits. New bits are sets to 0.
Definition bitset.h:474
std::string DebugString() const
Returns a 0/1 string representing the bitset.
Definition bitset.h:722
static uint64_t ConditionalXorOfTwoBits(IndexType i, uint64_t use1, Bitset64< IndexType >::ConstView set1, uint64_t use2, Bitset64< IndexType >::ConstView set2)
Definition bitset.h:709
void ClearTwoBits(IndexType i)
Clears the bits at position i and i ^ 1.
Definition bitset.h:520
Bitset64(IndexType size)
Definition bitset.h:456
void Resize(IndexType size)
Definition bitset.h:475
bool AreOneOfTwoBitsSet(IndexType i) const
Returns true if the bit at position i or the one at position i ^ 1 is set.
Definition bitset.h:527
void SetToIntersectionOf(const Bitset64< IndexType > &a, const Bitset64< IndexType > &b)
This one assume both given bitset to be of the same size.
Definition bitset.h:606
void ClearAndResize(IndexType size)
Changes the number of bits the Bitset64 can hold and set all of them to 0.
Definition bitset.h:489
void PushBack(bool value)
Appends value at the end of the bitset.
Definition bitset.h:467
bool operator[](IndexType i) const
Same as IsSet().
Definition bitset.h:541
void SetContentFromBitsetOfSameSize(const Bitset64< OtherIndexType > &other)
Same as SetContentFromBitset where "this" and "other" have the same size.
Definition bitset.h:585
ConstView const_view() const
Definition bitset.h:460
void Set(IndexType i)
Sets the bit at position i to 1.
Definition bitset.h:544
void ClearAndResize(IntegerType size)
Definition bitset.h:860
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
Definition bitset.h:903
void Clear(IntegerType index)
Definition bitset.h:899
bool operator[](IntegerType index) const
Definition bitset.h:884
SparseBitset & operator=(const SparseBitset &)=delete
Bitset64< IntegerType >::ConstView const_view() const
Definition bitset.h:920
SparseBitset(IntegerType size)
Definition bitset.h:846
void Set(IntegerType index)
Definition bitset.h:885
Bitset64< IntegerType >::View BitsetView()
A bit hacky for really hot loop.
Definition bitset.h:893
int NumberOfSetCallsWithDifferentArguments() const
Definition bitset.h:900
SparseBitset(const SparseBitset &)=delete
This type is neither copyable nor movable.
IntegerType size() const
Definition bitset.h:851
void Resize(IntegerType size)
Definition bitset.h:871
void SetUnsafe(typename Bitset64< IntegerType >::View view, IntegerType index)
Definition bitset.h:894
const bool DEBUG_MODE
Definition macros.h:26
In SWIG mode, we don't want anything besides these top-level includes.
uint32_t IntervalDown32(uint32_t s)
Definition bitset.h:320
int64_t UnsafeMostSignificantBitPosition64(const uint64_t *bitset, uint64_t start, uint64_t end)
uint32_t BitCountRange32(const uint32_t *bitset, uint32_t start, uint32_t end)
int LeastSignificantBitPosition32Default(uint32_t n)
Definition bitset.h:157
void SetBit32(uint32_t *const bitset, uint32_t pos)
Definition bitset.h:361
int64_t UnsafeLeastSignificantBitPosition64(const uint64_t *bitset, uint64_t start, uint64_t end)
uint32_t BitLength32(uint32_t size)
Definition bitset.h:343
static const uint32_t kAllBits32
Definition bitset.h:39
bool IsEmptyRange32(const uint32_t *bitset, uint32_t start, uint32_t end)
uint32_t BitCount32(uint32_t n)
Definition bitset.h:57
int32_t UnsafeLeastSignificantBitPosition32(const uint32_t *bitset, uint32_t start, uint32_t end)
int LeastSignificantBitPosition64DeBruijn(uint64_t n)
Definition bitset.h:85
int MostSignificantBitPosition32Default(uint32_t n)
Definition bitset.h:253
int LeastSignificantBitPosition64Default(uint64_t n)
Definition bitset.h:97
bool IsBitSet32(const uint32_t *const bitset, uint32_t pos)
Definition bitset.h:353
uint32_t BitPos32(uint32_t pos)
Definition bitset.h:335
uint64_t BitShift64(uint64_t v)
Returns the bit number in the bitset of the first bit of word number v.
Definition bitset.h:346
uint32_t BitOffset32(uint32_t pos)
Definition bitset.h:339
uint32_t LeastSignificantBitWord32(uint32_t n)
Definition bitset.h:68
uint64_t IntervalDown64(uint64_t s)
Returns a word with the s most significant bits unset.
Definition bitset.h:315
uint32_t IntervalUp32(uint32_t s)
Definition bitset.h:309
void ClearBit32(uint32_t *const bitset, uint32_t pos)
Definition bitset.h:369
static const uint64_t kAllBits64
Basic bit operations.
Definition bitset.h:37
int LeastSignificantBitPosition32DeBruijn(uint32_t n)
Definition bitset.h:148
void ClearBit64(uint64_t *const bitset, uint64_t pos)
Sets the bit pos to false in bitset.
Definition bitset.h:366
uint32_t OneBit32(int pos)
Definition bitset.h:43
uint64_t OneRange64(uint64_t s, uint64_t e)
Returns a word with bits from s to e set.
Definition bitset.h:289
static const uint64_t kAllBitsButLsb64
Definition bitset.h:38
uint32_t BitShift32(uint32_t v)
Definition bitset.h:347
uint32_t BitPos64(uint64_t pos)
Bit operators used to manipulates bitsets.
Definition bitset.h:334
uint64_t BitCountRange64(const uint64_t *bitset, uint64_t start, uint64_t end)
Returns the number of bits set in bitset between positions start and end.
uint64_t BitCount64(uint64_t n)
Returns the number of bits set in n.
Definition bitset.h:46
int MostSignificantBitPosition32(uint32_t n)
Definition bitset.h:277
bool IsBitSet64(const uint64_t *const bitset, uint64_t pos)
Returns true if the bit pos is set in bitset.
Definition bitset.h:350
uint64_t OneBit64(int pos)
Returns a word with only bit pos set.
Definition bitset.h:42
uint32_t OneRange32(uint32_t s, uint32_t e)
Definition bitset.h:296
uint64_t BitOffset64(uint64_t pos)
Returns the word number corresponding to bit number pos.
Definition bitset.h:338
bool IsEmptyRange64(const uint64_t *bitset, uint64_t start, uint64_t end)
Returns true if no bits are set in bitset between start and end.
uint64_t BitLength64(uint64_t size)
Returns the number of words needed to store size bits.
Definition bitset.h:342
int LeastSignificantBitPosition64(uint64_t n)
Definition bitset.h:131
int32_t UnsafeMostSignificantBitPosition32(const uint32_t *bitset, uint32_t start, uint32_t end)
int MostSignificantBitPosition64Default(uint64_t n)
Returns the most significant bit position in n.
Definition bitset.h:207
int LeastSignificantBitPosition32(uint32_t n)
Definition bitset.h:186
void SetBit64(uint64_t *const bitset, uint64_t pos)
Sets the bit pos to true in bitset.
Definition bitset.h:358
uint64_t LeastSignificantBitWord64(uint64_t n)
Returns a word with only the least significant bit of n set.
Definition bitset.h:67
uint64_t TwoBitsFromPos64(uint64_t pos)
Returns a mask with the bits pos % 64 and (pos ^ 1) % 64 sets.
Definition bitset.h:406
int MostSignificantBitPosition64(uint64_t n)
Definition bitset.h:235
uint64_t IntervalUp64(uint64_t s)
Returns a word with s least significant bits unset.
Definition bitset.h:304
static int input(yyscan_t yyscanner)