16#ifndef OR_TOOLS_UTIL_BITSET_H_
17#define OR_TOOLS_UTIL_BITSET_H_
29#include "absl/log/check.h"
37static const uint64_t
kAllBits64 = uint64_t{0xFFFFFFFFFFFFFFFF};
42inline uint64_t
OneBit64(
int pos) {
return uint64_t{1} << pos; }
43inline uint32_t
OneBit32(
int pos) {
return 1U << pos; }
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};
52 n = (n & m2) + ((n >> 2) & m2);
53 n = (n + (n >> 4)) & m4;
58 n -= (n >> 1) & 0x55555555UL;
59 n = (n & 0x33333333) + ((n >> 2) & 0x33333333UL);
60 n = (n + (n >> 4)) & 0x0F0F0F0FUL;
63 return n & 0x0000003FUL;
74#define USE_DEBRUIJN true
75#if defined(__GNUC__) || defined(__llvm__)
76#define USE_FAST_LEAST_SIGNIFICANT_BIT true
79#if defined(USE_FAST_LEAST_SIGNIFICANT_BIT)
80inline int LeastSignificantBitPosition64Fast(uint64_t n) {
81 return __builtin_ctzll(n);
86 static const uint64_t kSeq = uint64_t{0x0218a392dd5fb34f};
87 static const int kTab[64] = {
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,
94 return kTab[((n & (~n + 1)) * kSeq) >> 58];
100 if (n & 0x00000000FFFFFFFFLL) {
105 if (n & 0x000000000000FFFFLL) {
110 if (n & 0x00000000000000FFLL) {
115 if (n & 0x000000000000000FLL) {
120 if (n & 0x0000000000000003LL) {
125 if (n & 0x0000000000000001LL) {
133#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
134 return LeastSignificantBitPosition64Fast(n);
135#elif defined(USE_DEBRUIJN)
142#if defined(USE_FAST_LEAST_SIGNIFICANT_BIT)
143inline int LeastSignificantBitPosition32Fast(uint32_t n) {
144 return __builtin_ctzl(n);
149 static const uint32_t kSeq = 0x077CB531U;
150 static const int kTab[32] = {
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];
160 if (n & 0x0000FFFFL) {
165 if (n & 0x000000FFL) {
170 if (n & 0x0000000FL) {
175 if (n & 0x00000003L) {
180 if (n & 0x00000001L) {
188#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
189 return LeastSignificantBitPosition32Fast(n);
190#elif defined(USE_DEBRUIJN)
198#if USE_FAST_LEAST_SIGNIFICANT_BIT
199inline int MostSignificantBitPosition64Fast(uint64_t n) {
202 const int offset = __builtin_clzll(1);
203 return n == 0 ? 0 : (offset - __builtin_clzll(n));
236#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
237 return MostSignificantBitPosition64Fast(n);
243#if USE_FAST_LEAST_SIGNIFICANT_BIT
244inline int MostSignificantBitPosition32Fast(uint32_t n) {
248 const int offset = __builtin_clzl(1);
249 return n == 0 ? 0 : (offset - __builtin_clzl(n));
278#ifdef USE_FAST_LEAST_SIGNIFICANT_BIT
279 return MostSignificantBitPosition32Fast(n);
286#undef USE_FAST_LEAST_SIGNIFICANT_BIT
334inline uint32_t
BitPos64(uint64_t pos) {
return (pos & 63); }
335inline uint32_t
BitPos32(uint32_t pos) {
return (pos & 31); }
350inline bool IsBitSet64(
const uint64_t*
const bitset, uint64_t pos) {
353inline bool IsBitSet32(
const uint32_t*
const bitset, uint32_t pos) {
358inline void SetBit64(uint64_t*
const bitset, uint64_t pos) {
361inline void SetBit32(uint32_t*
const bitset, uint32_t pos) {
366inline void ClearBit64(uint64_t*
const bitset, uint64_t pos) {
369inline void ClearBit32(uint32_t*
const bitset, uint32_t pos) {
407 return uint64_t{3} << (pos & 62);
415template <
typename IndexType =
int64_t>
429 const uint64_t*
data()
const {
return data_; }
432 const uint64_t*
const data_;
452 uint64_t*
const data_;
457 : size_(Value(
size) > 0 ?
size : IndexType(0)),
468 IndexType
size()
const {
return 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));
486 data_[new_data_size - 1] &= ~bitmask;
494 DCHECK_GE(Value(
size), 0);
495 size_ = Value(
size) > 0 ?
size : IndexType(0);
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));
507 void ClearAll() { memset(data_.data(), 0, data_.size() *
sizeof(int64_t)); }
511 DCHECK_GE(Value(i), 0);
512 DCHECK_LT(Value(i), Value(size_));
518 DCHECK_GE(Value(i), 0);
519 DCHECK_LT(Value(i), Value(size_));
525 DCHECK_GE(Value(i), 0);
526 DCHECK_LT(Value(i), Value(size_));
527 data_[
BitOffset64(Value(i))] &= ~TwoBitsFromPos64(Value(i));
532 DCHECK_GE(Value(i), 0);
533 DCHECK_LT(Value(i), Value(size_));
539 DCHECK_GE(Value(i), 0);
540 DCHECK_LT(Value(i), Value(size_));
549 DCHECK_GE(Value(i), 0);
550 DCHECK_LT(Value(i), size_);
566 data_[offset] = other.data_[offset];
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()) {
581 data_[min_size - 1] &= ~bitmask;
582 data_[min_size - 1] |= (bitmask & last_common_bucket);
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));
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];
601 for (
int i = min_size; i < data_.size(); ++i) {
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];
636 : data_(bitset.data_.data()), size_(bitset.data_.
size()) {
637 if (!bitset.data_.empty()) {
644 return Iterator(bitset.data_.data());
649 if (other.size_ == 0) {
652 return std::tie(index_, current_) !=
653 std::tie(other.index_, other.current_);
656 IndexType
operator*()
const {
return IndexType(index_); }
666 while (current_ == 0) {
668 if (bucket == size_) {
672 current_ = data_[bucket];
677 current_ &= current_ - 1;
682 explicit Iterator(
const uint64_t* data) : data_(data), size_(0) {}
684 const uint64_t* data_;
687 uint64_t current_ = 0;
701 DCHECK(use1 == 0 || use1 == 1);
702 DCHECK(use2 == 0 || use2 == 1);
705 return ((use1 << pos) & set1.
data()[bucket]) ^
706 ((use2 << pos) & set2.
data()[bucket]);
712 for (IndexType i(0); i <
size(); ++i) {
713 output +=
IsSet(i) ?
"1" :
"0";
721 static int Value(IndexType
input);
724 std::vector<uint64_t> data_;
726 template <
class OtherIndexType>
743 CHECK_GE(
size, size_);
757 top_ = std::max(top_, i);
765 top_ = std::max(top_, i - 1);
766 int bucket_index =
static_cast<int>(
BitOffset64(i));
768 for (--bucket_index; bucket_index >= 0; --bucket_index) {
774 int Top()
const {
return top_; }
779 int bucket_index =
static_cast<int>(
BitOffset64(top_));
780 uint64_t bucket = data_[bucket_index] &= ~OneBit64(
BitPos64(top_));
782 if (bucket_index == 0) {
786 bucket = data_[--bucket_index];
792 top_ =
static_cast<int>(
BitShift64(bucket_index) +
799 std::vector<uint64_t> data_;
803template <
typename IntType>
804inline int Bitset64<IntType>::Value(IntType
input) {
805 DCHECK_GE(
input.value(), 0);
806 return input.value();
809inline int Bitset64<int>::Value(
int input) {
814inline int Bitset64<int64_t>::Value(int64_t
input) {
821template <
typename IntegerType =
int64_t>
830 IntegerType
size()
const {
return bitset_.size(); }
832 for (
const IntegerType i : to_clear_) bitset_.ClearBucket(i);
841 const int kSparseThreshold = 300;
842 if (to_clear_.size() * kSparseThreshold <
size) {
844 bitset_.Resize(
size);
846 bitset_.ClearAndResize(
size);
851 if (
size < bitset_.size()) {
853 for (IntegerType
index : to_clear_) {
855 to_clear_[new_index] =
index;
859 to_clear_.resize(new_index);
861 bitset_.Resize(
size);
865 if (!bitset_[
index]) {
867 to_clear_.push_back(
index);
872 to_clear_.push_back(
index);
876 return to_clear_.size();
890 for (IntegerType
index : to_clear_) CHECK(!bitset_[
index]);
896 return bitset_.const_view();
901 std::vector<IntegerType> to_clear_;
int Top() const
Returns the position of the highest bit set in O(1) or -1 if no bit is set.
void ClearAndResize(int size)
void ClearTop()
Clears the Top() bit and recomputes the position of the next Top().
BitQueue64(const BitQueue64 &)=delete
This type is neither copyable nor movable.
void IncreaseSize(int size)
BitQueue64 & operator=(const BitQueue64 &)=delete
void SetAllBefore(int i)
Sets all the bits from 0 up to i-1 to 1.
When speed matter, caching the base pointer helps.
const uint64_t * data() const
bool operator[](IndexType i) const
ConstView(const Bitset64 *bitset)
Iterator(const Iterator &other)=default
bool operator==(const Iterator &other) const
bool operator!=(const Iterator &other) const
std::forward_iterator_tag iterator_category
Iterator(Iterator &&other)=default
Iterator & operator=(const Iterator &other)=default
std::ptrdiff_t difference_type
IndexType operator*() const
static Iterator EndIterator(const Bitset64 &bitset)
Iterator(const Bitset64 &bitset)
bool operator[](IndexType i) const
void CopyBucket(const Bitset64< IndexType > &other, IndexType i)
Copies bucket containing bit i from "other" to "this".
void ClearAll()
Sets all bits to 0.
void ClearBucket(IndexType i)
Sets bucket containing bit i to 0.
void SetContentFromBitset(const Bitset64< OtherIndexType > &other)
bool IsSet(IndexType i) const
Returns true if the bit at position i is set.
IndexType size() const
Returns how many bits this Bitset64 can hold.
void Clear(IndexType i)
Sets the bit at position i to 0.
void Set(IndexType i, bool value)
If value is true, sets the bit at position i to 1, sets it to 0 otherwise.
void Union(const Bitset64< IndexType > &other)
void Intersection(const Bitset64< IndexType > &other)
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.
std::string DebugString() const
Returns a 0/1 string representing the bitset.
static uint64_t ConditionalXorOfTwoBits(IndexType i, uint64_t use1, Bitset64< IndexType >::ConstView set1, uint64_t use2, Bitset64< IndexType >::ConstView set2)
void ClearTwoBits(IndexType i)
Clears the bits at position i and i ^ 1.
void Resize(IndexType size)
bool AreOneOfTwoBitsSet(IndexType i) const
Returns true if the bit at position i or the one at position i ^ 1 is set.
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.
void PushBack(bool value)
Appends value at the end of the bitset.
bool operator[](IndexType i) const
Same as IsSet().
void SetContentFromBitsetOfSameSize(const Bitset64< OtherIndexType > &other)
Same as SetContentFromBitset where "this" and "other" have the same size.
ConstView const_view() const
void Set(IndexType i)
Sets the bit at position i to 1.
void ClearAndResize(IntegerType size)
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
void Clear(IntegerType index)
bool operator[](IntegerType index) const
SparseBitset & operator=(const SparseBitset &)=delete
Bitset64< IntegerType >::ConstView const_view() const
SparseBitset(IntegerType size)
void Set(IntegerType index)
void SetUnsafe(IntegerType index)
int NumberOfSetCallsWithDifferentArguments() const
SparseBitset(const SparseBitset &)=delete
This type is neither copyable nor movable.
void Resize(IntegerType size)
In SWIG mode, we don't want anything besides these top-level includes.
uint32_t IntervalDown32(uint32_t s)
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)
void SetBit32(uint32_t *const bitset, uint32_t pos)
int64_t UnsafeLeastSignificantBitPosition64(const uint64_t *bitset, uint64_t start, uint64_t end)
uint32_t BitLength32(uint32_t size)
static const uint32_t kAllBits32
bool IsEmptyRange32(const uint32_t *bitset, uint32_t start, uint32_t end)
uint32_t BitCount32(uint32_t n)
int32_t UnsafeLeastSignificantBitPosition32(const uint32_t *bitset, uint32_t start, uint32_t end)
int LeastSignificantBitPosition64DeBruijn(uint64_t n)
int MostSignificantBitPosition32Default(uint32_t n)
int LeastSignificantBitPosition64Default(uint64_t n)
bool IsBitSet32(const uint32_t *const bitset, uint32_t pos)
uint32_t BitPos32(uint32_t pos)
uint64_t BitShift64(uint64_t v)
Returns the bit number in the bitset of the first bit of word number v.
uint32_t BitOffset32(uint32_t pos)
uint32_t LeastSignificantBitWord32(uint32_t n)
uint64_t IntervalDown64(uint64_t s)
Returns a word with the s most significant bits unset.
uint32_t IntervalUp32(uint32_t s)
void ClearBit32(uint32_t *const bitset, uint32_t pos)
static const uint64_t kAllBits64
Basic bit operations.
int LeastSignificantBitPosition32DeBruijn(uint32_t n)
void ClearBit64(uint64_t *const bitset, uint64_t pos)
Sets the bit pos to false in bitset.
uint32_t OneBit32(int pos)
uint64_t OneRange64(uint64_t s, uint64_t e)
Returns a word with bits from s to e set.
static const uint64_t kAllBitsButLsb64
uint32_t BitShift32(uint32_t v)
uint32_t BitPos64(uint64_t pos)
Bit operators used to manipulates bitsets.
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.
int MostSignificantBitPosition32(uint32_t n)
bool IsBitSet64(const uint64_t *const bitset, uint64_t pos)
Returns true if the bit pos is set in bitset.
uint64_t OneBit64(int pos)
Returns a word with only bit pos set.
uint32_t OneRange32(uint32_t s, uint32_t e)
uint64_t BitOffset64(uint64_t pos)
Returns the word number corresponding to bit number pos.
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.
int LeastSignificantBitPosition64(uint64_t n)
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.
int LeastSignificantBitPosition32(uint32_t n)
void SetBit64(uint64_t *const bitset, uint64_t pos)
Sets the bit pos to true in bitset.
uint64_t LeastSignificantBitWord64(uint64_t n)
Returns a word with only the least significant bit of n set.
uint64_t TwoBitsFromPos64(uint64_t pos)
Returns a mask with the bits pos % 64 and (pos ^ 1) % 64 sets.
int MostSignificantBitPosition64(uint64_t n)
uint64_t IntervalUp64(uint64_t s)
Returns a word with s least significant bits unset.
static int input(yyscan_t yyscanner)
std::optional< int64_t > end