Google OR-Tools v9.11
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-2024 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 // This type is neither copyable nor movable.
461 Bitset64(const Bitset64&) = delete;
462 Bitset64& operator=(const Bitset64&) = delete;
463
464 ConstView const_view() const { return ConstView(this); }
465 View view() { return View(this); }
466
467 // Returns how many bits this Bitset64 can hold.
468 IndexType size() const { return size_; }
469
470 // Appends value at the end of the bitset.
471 void PushBack(bool value) {
472 ++size_;
473 data_.resize(BitLength64(Value(size_)), 0);
474 Set(size_ - 1, value);
475 }
476
477 // Resizes the Bitset64 to the given number of bits. New bits are sets to 0.
478 void resize(int size) { Resize(IndexType(size)); }
479 void Resize(IndexType size) {
480 DCHECK_GE(Value(size), 0);
481 IndexType new_size = Value(size) > 0 ? size : IndexType(0);
482 if (new_size < size_ && Value(new_size) > 0) {
483 const int64_t new_data_size = BitLength64(Value(new_size));
484 const uint64_t bitmask = kAllBitsButLsb64
485 << BitPos64(Value(new_size) - 1);
486 data_[new_data_size - 1] &= ~bitmask;
487 }
488 size_ = new_size;
489 data_.resize(BitLength64(Value(size_)), 0);
490 }
491
492 // Changes the number of bits the Bitset64 can hold and set all of them to 0.
493 void ClearAndResize(IndexType size) {
494 DCHECK_GE(Value(size), 0);
495 size_ = Value(size) > 0 ? size : IndexType(0);
496
497 // Memset is 4x faster than data_.assign() as of 19/03/2014.
498 // TODO(user): Ideally if a realloc happens, we don't need to copy the old
499 // data...
500 const size_t bit_length = static_cast<size_t>(BitLength64(Value(size_)));
501 const size_t to_clear = std::min(data_.size(), bit_length);
502 data_.resize(bit_length, 0);
503 memset(data_.data(), 0, to_clear * sizeof(int64_t));
504 }
505
506 // Sets all bits to 0.
507 void ClearAll() { memset(data_.data(), 0, data_.size() * sizeof(int64_t)); }
508
509 // Sets the bit at position i to 0.
510 void Clear(IndexType i) {
511 DCHECK_GE(Value(i), 0);
512 DCHECK_LT(Value(i), Value(size_));
513 data_[BitOffset64(Value(i))] &= ~OneBit64(BitPos64(Value(i)));
514 }
515
516 // Sets bucket containing bit i to 0.
517 void ClearBucket(IndexType i) {
518 DCHECK_GE(Value(i), 0);
519 DCHECK_LT(Value(i), Value(size_));
520 data_[BitOffset64(Value(i))] = 0;
521 }
522
523 // Clears the bits at position i and i ^ 1.
524 void ClearTwoBits(IndexType i) {
525 DCHECK_GE(Value(i), 0);
526 DCHECK_LT(Value(i), Value(size_));
527 data_[BitOffset64(Value(i))] &= ~TwoBitsFromPos64(Value(i));
528 }
529
530 // Returns true if the bit at position i or the one at position i ^ 1 is set.
531 bool AreOneOfTwoBitsSet(IndexType i) const {
532 DCHECK_GE(Value(i), 0);
533 DCHECK_LT(Value(i), Value(size_));
534 return data_[BitOffset64(Value(i))] & TwoBitsFromPos64(Value(i));
535 }
536
537 // Returns true if the bit at position i is set.
538 bool IsSet(IndexType i) const {
539 DCHECK_GE(Value(i), 0);
540 DCHECK_LT(Value(i), Value(size_));
541 return data_[BitOffset64(Value(i))] & OneBit64(BitPos64(Value(i)));
542 }
543
544 // Same as IsSet().
545 bool operator[](IndexType i) const { return IsSet(i); }
546
547 // Sets the bit at position i to 1.
548 void Set(IndexType i) {
549 DCHECK_GE(Value(i), 0);
550 DCHECK_LT(Value(i), size_);
551 data_[BitOffset64(Value(i))] |= OneBit64(BitPos64(Value(i)));
552 }
553
554 // If value is true, sets the bit at position i to 1, sets it to 0 otherwise.
555 void Set(IndexType i, bool value) {
556 if (value) {
557 Set(i);
558 } else {
559 Clear(i);
560 }
561 }
562
563 // Copies bucket containing bit i from "other" to "this".
564 void CopyBucket(const Bitset64<IndexType>& other, IndexType i) {
565 const uint64_t offset = BitOffset64(Value(i));
566 data_[offset] = other.data_[offset];
567 }
568
569 // Copies "other" to "this". The bitsets do not have to be of the same size.
570 // If "other" is smaller, high order bits are not changed. If "other" is
571 // larger, its high order bits are ignored. In any case "this" is not resized.
572 template <typename OtherIndexType>
574 const int64_t min_size = std::min(data_.size(), other.data_.size());
575 if (min_size == 0) return;
576 const uint64_t last_common_bucket = data_[min_size - 1];
577 memcpy(data_.data(), other.data_.data(), min_size * sizeof(uint64_t));
578 if (data_.size() >= other.data_.size()) {
579 const uint64_t bitmask = kAllBitsButLsb64
580 << BitPos64(other.Value(other.size() - 1));
581 data_[min_size - 1] &= ~bitmask;
582 data_[min_size - 1] |= (bitmask & last_common_bucket);
583 }
584 }
585
586 // Same as SetContentFromBitset where "this" and "other" have the same size.
587 template <typename OtherIndexType>
589 DCHECK_EQ(Value(size()), other.Value(other.size()));
590 memcpy(data_.data(), other.data_.data(), data_.size() * sizeof(uint64_t));
591 }
592
593 // Sets "this" to be the intersection of "this" and "other". The
594 // bitsets do not have to be the same size. If other is smaller, all
595 // the higher order bits are assumed to be 0.
597 const int min_size = std::min(data_.size(), other.data_.size());
598 for (int i = 0; i < min_size; ++i) {
599 data_[i] &= other.data_[i];
600 }
601 for (int i = min_size; i < data_.size(); ++i) {
602 data_[i] = 0;
603 }
604 }
605
606 // Sets "this" to be the union of "this" and "other". The
607 // bitsets do not have to be the same size. If other is smaller, all
608 // the higher order bits are assumed to be 0.
609 void Union(const Bitset64<IndexType>& other) {
610 const int min_size = std::min(data_.size(), other.data_.size());
611 for (int i = 0; i < min_size; ++i) {
612 data_[i] |= other.data_[i];
613 }
614 }
615
616 // Class to iterate over the bit positions at 1 of a Bitset64.
617 //
618 // IMPORTANT: Because the iterator "caches" the current uint64_t bucket, this
619 // will probably not do what you want if Bitset64 is modified while iterating.
620 class Iterator {
621 public:
622 // Make this iterator a std::forward_iterator, so it works with std::sample,
623 // std::max_element, etc.
624 Iterator() : data_(nullptr), size_(0) {}
625 Iterator(Iterator&& other) = default;
626 Iterator(const Iterator& other) = default;
627 Iterator& operator=(const Iterator& other) = default;
628 using difference_type = std::ptrdiff_t;
629 using iterator_category = std::forward_iterator_tag;
630 using value_type = IndexType;
631 using size_type = std::size_t;
634
635 explicit Iterator(const Bitset64& bitset)
636 : data_(bitset.data_.data()), size_(bitset.data_.size()) {
637 if (!bitset.data_.empty()) {
638 current_ = data_[0];
639 this->operator++();
640 }
641 }
642
643 static Iterator EndIterator(const Bitset64& bitset) {
644 return Iterator(bitset.data_.data());
645 }
646
647 bool operator==(const Iterator& other) const { return !(*this != other); }
648 bool operator!=(const Iterator& other) const {
649 if (other.size_ == 0) {
650 return size_ != 0;
651 }
652 return std::tie(index_, current_) !=
653 std::tie(other.index_, other.current_);
654 }
655
656 IndexType operator*() const { return IndexType(index_); }
657
659 Iterator other = *this;
660 ++(*this);
661 return other;
662 }
663
665 int bucket = BitOffset64(index_);
666 while (current_ == 0) {
667 bucket++;
668 if (bucket == size_) {
669 size_ = 0;
670 return *this;
671 }
672 current_ = data_[bucket];
673 }
674
675 // Computes the index and clear the least significant bit of current_.
676 index_ = BitShift64(bucket) | LeastSignificantBitPosition64(current_);
677 current_ &= current_ - 1;
678 return *this;
679 }
680
681 private:
682 explicit Iterator(const uint64_t* data) : data_(data), size_(0) {}
683
684 const uint64_t* data_;
685 int size_;
686 int index_ = 0;
687 uint64_t current_ = 0;
688 };
689
690 // Allows range-based "for" loop on the non-zero positions:
691 // for (const IndexType index : bitset) {}
692 Iterator begin() const { return Iterator(*this); }
693 Iterator end() const { return Iterator::EndIterator(*this); }
694
695 // Cryptic function! This is just an optimized version of a given piece of
696 // code and has probably little general use.
697 static uint64_t ConditionalXorOfTwoBits(IndexType i, uint64_t use1,
699 uint64_t use2,
701 DCHECK(use1 == 0 || use1 == 1);
702 DCHECK(use2 == 0 || use2 == 1);
703 const int bucket = BitOffset64(Value(i));
704 const int pos = BitPos64(Value(i));
705 return ((use1 << pos) & set1.data()[bucket]) ^
706 ((use2 << pos) & set2.data()[bucket]);
707 }
708
709 // Returns a 0/1 string representing the bitset.
710 std::string DebugString() const {
711 std::string output;
712 for (IndexType i(0); i < size(); ++i) {
713 output += IsSet(i) ? "1" : "0";
714 }
715 return output;
716 }
717
718 private:
719 // Returns the value of the index type.
720 // This function is specialized below to work with IntType and int64_t.
721 static int Value(IndexType input);
722
723 IndexType size_;
724 std::vector<uint64_t> data_;
725
726 template <class OtherIndexType>
727 friend class Bitset64;
728};
729
730// Specialized version of Bitset64 that allows to query the last bit set more
731// efficiently.
733 public:
734 BitQueue64() : size_(), top_(-1), data_() {}
735 explicit BitQueue64(int size)
736 : size_(size), top_(-1), data_(BitLength64(size), 0) {}
737
738 // This type is neither copyable nor movable.
739 BitQueue64(const BitQueue64&) = delete;
740 BitQueue64& operator=(const BitQueue64&) = delete;
741
742 void IncreaseSize(int size) {
743 CHECK_GE(size, size_);
744 size_ = size;
745 data_.resize(BitLength64(size), 0);
746 }
747
749 top_ = -1;
750 size_ = size;
751 data_.assign(BitLength64(size), 0);
752 }
753
754 void Set(int i) {
755 DCHECK_GE(i, 0);
756 DCHECK_LT(i, size_);
757 top_ = std::max(top_, i);
758 data_[BitOffset64(i)] |= OneBit64(BitPos64(i));
759 }
760
761 // Sets all the bits from 0 up to i-1 to 1.
762 void SetAllBefore(int i) {
763 DCHECK_GE(i, 0);
764 DCHECK_LT(i, size_);
765 top_ = std::max(top_, i - 1);
766 int bucket_index = static_cast<int>(BitOffset64(i));
767 data_[bucket_index] |= OneBit64(BitPos64(i)) - 1;
768 for (--bucket_index; bucket_index >= 0; --bucket_index) {
769 data_[bucket_index] = kAllBits64;
770 }
771 }
772
773 // Returns the position of the highest bit set in O(1) or -1 if no bit is set.
774 int Top() const { return top_; }
775
776 // Clears the Top() bit and recomputes the position of the next Top().
777 void ClearTop() {
778 DCHECK_NE(top_, -1);
779 int bucket_index = static_cast<int>(BitOffset64(top_));
780 uint64_t bucket = data_[bucket_index] &= ~OneBit64(BitPos64(top_));
781 while (!bucket) {
782 if (bucket_index == 0) {
783 top_ = -1;
784 return;
785 }
786 bucket = data_[--bucket_index];
787 }
788
789 // Note(user): I experimented with reversing the bit order in a bucket to
790 // use LeastSignificantBitPosition64() and it is only slightly faster at the
791 // cost of a lower Set() speed. So I preferred this version.
792 top_ = static_cast<int>(BitShift64(bucket_index) +
794 }
795
796 private:
797 int size_;
798 int top_;
799 std::vector<uint64_t> data_;
800};
801
802// The specialization of Value() for IntType and int64_t.
803template <typename IntType>
804inline int Bitset64<IntType>::Value(IntType input) {
805 DCHECK_GE(input.value(), 0);
806 return input.value();
807}
808template <>
809inline int Bitset64<int>::Value(int input) {
810 DCHECK_GE(input, 0);
811 return input;
812}
813template <>
814inline int Bitset64<int64_t>::Value(int64_t input) {
815 DCHECK_GE(input, 0);
816 return input;
817}
818
819// A simple utility class to set/unset integer in a range [0, size).
820// This is optimized for sparsity.
821template <typename IntegerType = int64_t>
823 public:
825 explicit SparseBitset(IntegerType size) : bitset_(size) {}
826
827 // This type is neither copyable nor movable.
828 SparseBitset(const SparseBitset&) = delete;
830 IntegerType size() const { return bitset_.size(); }
832 for (const IntegerType i : to_clear_) bitset_.ClearBucket(i);
833 to_clear_.clear();
834 }
835 void ClearAll() {
836 bitset_.ClearAll();
837 to_clear_.clear();
838 }
839 void ClearAndResize(IntegerType size) {
840 // As of 19/03/2014, experiments show that this is a reasonable threshold.
841 const int kSparseThreshold = 300;
842 if (to_clear_.size() * kSparseThreshold < size) {
844 bitset_.Resize(size);
845 } else {
846 bitset_.ClearAndResize(size);
847 to_clear_.clear();
848 }
849 }
850 void Resize(IntegerType size) {
851 if (size < bitset_.size()) {
852 int new_index = 0;
853 for (IntegerType index : to_clear_) {
854 if (index < size) {
855 to_clear_[new_index] = index;
856 ++new_index;
857 }
858 }
859 to_clear_.resize(new_index);
860 }
861 bitset_.Resize(size);
862 }
863 bool operator[](IntegerType index) const { return bitset_[index]; }
864 void Set(IntegerType index) {
865 if (!bitset_[index]) {
866 bitset_.Set(index);
867 to_clear_.push_back(index);
868 }
869 }
870 void SetUnsafe(IntegerType index) {
871 bitset_.Set(index);
872 to_clear_.push_back(index);
873 }
874 void Clear(IntegerType index) { bitset_.Clear(index); }
876 return to_clear_.size();
877 }
878 const std::vector<IntegerType>& PositionsSetAtLeastOnce() const {
879 return to_clear_;
880 }
881
882 // Tells the class that all its bits are cleared, so it can reset to_clear_
883 // to the empty vector. Note that this call is "unsafe" since the fact that
884 // the class is actually all cleared is only checked in debug mode.
885 //
886 // This is useful to iterate on the "set" positions while clearing them for
887 // instance. This way, after the loop, a client can call this for efficiency.
889 if (DEBUG_MODE) {
890 for (IntegerType index : to_clear_) CHECK(!bitset_[index]);
891 }
892 to_clear_.clear();
893 }
894
896 return bitset_.const_view();
897 }
898
899 private:
900 Bitset64<IntegerType> bitset_;
901 std::vector<IntegerType> to_clear_;
902};
903
904} // namespace operations_research
905
906#endif // OR_TOOLS_UTIL_BITSET_H_
IntegerValue size
int Top() const
Returns the position of the highest bit set in O(1) or -1 if no bit is set.
Definition bitset.h:774
void ClearAndResize(int size)
Definition bitset.h:748
void ClearTop()
Clears the Top() bit and recomputes the position of the next Top().
Definition bitset.h:777
BitQueue64(const BitQueue64 &)=delete
This type is neither copyable nor movable.
void IncreaseSize(int size)
Definition bitset.h:742
BitQueue64 & operator=(const BitQueue64 &)=delete
void SetAllBefore(int i)
Sets all the bits from 0 up to i-1 to 1.
Definition bitset.h:762
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:647
bool operator!=(const Iterator &other) const
Definition bitset.h:648
std::forward_iterator_tag iterator_category
Definition bitset.h:629
Iterator(Iterator &&other)=default
Iterator & operator=(const Iterator &other)=default
static Iterator EndIterator(const Bitset64 &bitset)
Definition bitset.h:643
Iterator(const Bitset64 &bitset)
Definition bitset.h:635
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:564
void ClearAll()
Sets all bits to 0.
Definition bitset.h:507
void ClearBucket(IndexType i)
Sets bucket containing bit i to 0.
Definition bitset.h:517
void SetContentFromBitset(const Bitset64< OtherIndexType > &other)
Definition bitset.h:573
bool IsSet(IndexType i) const
Returns true if the bit at position i is set.
Definition bitset.h:538
IndexType size() const
Returns how many bits this Bitset64 can hold.
Definition bitset.h:468
void Clear(IndexType i)
Sets the bit at position i to 0.
Definition bitset.h:510
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:555
void Union(const Bitset64< IndexType > &other)
Definition bitset.h:609
void Intersection(const Bitset64< IndexType > &other)
Definition bitset.h:596
Iterator end() const
Definition bitset.h:693
Iterator begin() const
Definition bitset.h:692
Bitset64(const Bitset64 &)=delete
This type is neither copyable nor movable.
void resize(int size)
Resizes the Bitset64 to the given number of bits. New bits are sets to 0.
Definition bitset.h:478
std::string DebugString() const
Returns a 0/1 string representing the bitset.
Definition bitset.h:710
static uint64_t ConditionalXorOfTwoBits(IndexType i, uint64_t use1, Bitset64< IndexType >::ConstView set1, uint64_t use2, Bitset64< IndexType >::ConstView set2)
Definition bitset.h:697
void ClearTwoBits(IndexType i)
Clears the bits at position i and i ^ 1.
Definition bitset.h:524
Bitset64(IndexType size)
Definition bitset.h:456
void Resize(IndexType size)
Definition bitset.h:479
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:531
Bitset64 & operator=(const Bitset64 &)=delete
void ClearAndResize(IndexType size)
Changes the number of bits the Bitset64 can hold and set all of them to 0.
Definition bitset.h:493
void PushBack(bool value)
Appends value at the end of the bitset.
Definition bitset.h:471
bool operator[](IndexType i) const
Same as IsSet().
Definition bitset.h:545
void SetContentFromBitsetOfSameSize(const Bitset64< OtherIndexType > &other)
Same as SetContentFromBitset where "this" and "other" have the same size.
Definition bitset.h:588
ConstView const_view() const
Definition bitset.h:464
void Set(IndexType i)
Sets the bit at position i to 1.
Definition bitset.h:548
void ClearAndResize(IntegerType size)
Definition bitset.h:839
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
Definition bitset.h:878
void Clear(IntegerType index)
Definition bitset.h:874
bool operator[](IntegerType index) const
Definition bitset.h:863
SparseBitset & operator=(const SparseBitset &)=delete
Bitset64< IntegerType >::ConstView const_view() const
Definition bitset.h:895
SparseBitset(IntegerType size)
Definition bitset.h:825
void Set(IntegerType index)
Definition bitset.h:864
void SetUnsafe(IntegerType index)
Definition bitset.h:870
int NumberOfSetCallsWithDifferentArguments() const
Definition bitset.h:875
SparseBitset(const SparseBitset &)=delete
This type is neither copyable nor movable.
IntegerType size() const
Definition bitset.h:830
void Resize(IntegerType size)
Definition bitset.h:850
int64_t b
Definition table.cc:45
int64_t value
int index
const bool DEBUG_MODE
Definition macros.h:24
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)
std::optional< int64_t > end
int64_t start