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