16 #ifndef OR_TOOLS_UTIL_BITSET_H_ 17 #define OR_TOOLS_UTIL_BITSET_H_ 33 static const uint64_t
kAllBits64 = uint64_t{0xFFFFFFFFFFFFFFFF};
38 inline uint64_t
OneBit64(
int pos) {
return uint64_t{1} << pos; }
39 inline uint32_t
OneBit32(
int pos) {
return 1U << pos; }
43 const uint64_t m1 = uint64_t{0x5555555555555555};
44 const uint64_t m2 = uint64_t{0x3333333333333333};
45 const uint64_t m4 = uint64_t{0x0F0F0F0F0F0F0F0F};
46 const uint64_t h01 = uint64_t{0x0101010101010101};
48 n = (n & m2) + ((n >> 2) & m2);
49 n = (n + (n >> 4)) & m4;
54 n -= (n >> 1) & 0x55555555UL;
55 n = (n & 0x33333333) + ((n >> 2) & 0x33333333UL);
56 n = (n + (n >> 4)) & 0x0F0F0F0FUL;
59 return n & 0x0000003FUL;
70 #define USE_DEBRUIJN true // if true, use de Bruijn bit forward scanner. 71 #if defined(__GNUC__) || defined(__llvm__) 72 #define USE_FAST_LEAST_SIGNIFICANT_BIT true // if true, use fast lsb. 75 #if defined(USE_FAST_LEAST_SIGNIFICANT_BIT) 76 inline int LeastSignificantBitPosition64Fast(uint64_t n) {
77 return n == 0 ? 0 : __builtin_ctzll(n);
82 static const uint64_t kSeq = uint64_t{0x0218a392dd5fb34f};
83 static const int kTab[64] = {
85 0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 52, 20, 58,
86 5, 17, 26, 56, 15, 38, 29, 40, 10, 49, 53, 31, 21, 34, 59, 42,
87 63, 6, 12, 18, 24, 27, 51, 57, 16, 55, 37, 39, 48, 30, 33, 41,
88 62, 11, 23, 50, 54, 36, 47, 32, 61, 22, 35, 46, 60, 45, 44, 43,
90 return kTab[((n & (~n + 1)) * kSeq) >> 58];
96 if (n & 0x00000000FFFFFFFFLL) {
101 if (n & 0x000000000000FFFFLL) {
106 if (n & 0x00000000000000FFLL) {
111 if (n & 0x000000000000000FLL) {
116 if (n & 0x0000000000000003LL) {
121 if (n & 0x0000000000000001LL) {
129 #ifdef USE_FAST_LEAST_SIGNIFICANT_BIT 130 return LeastSignificantBitPosition64Fast(n);
131 #elif defined(USE_DEBRUIJN) 138 #if defined(USE_FAST_LEAST_SIGNIFICANT_BIT) 139 inline int LeastSignificantBitPosition32Fast(uint32_t n) {
140 return n == 0 ? 0 : __builtin_ctzl(n);
145 static const uint32_t kSeq = 0x077CB531U;
146 static const int kTab[32] = {
147 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20,
148 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19,
149 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
150 return kTab[((n & (~n + 1)) * kSeq) >> 27];
154 if (n == 0)
return 0;
156 if (n & 0x0000FFFFL) {
161 if (n & 0x000000FFL) {
166 if (n & 0x0000000FL) {
171 if (n & 0x00000003L) {
176 if (n & 0x00000001L) {
184 #ifdef USE_FAST_LEAST_SIGNIFICANT_BIT 185 return LeastSignificantBitPosition32Fast(n);
186 #elif defined(USE_DEBRUIJN) 194 #if USE_FAST_LEAST_SIGNIFICANT_BIT 195 inline int MostSignificantBitPosition64Fast(uint64_t n) {
198 const int offset = __builtin_clzll(1);
199 return n == 0 ? 0 : (offset - __builtin_clzll(n));
232 #ifdef USE_FAST_LEAST_SIGNIFICANT_BIT 233 return MostSignificantBitPosition64Fast(n);
239 #if USE_FAST_LEAST_SIGNIFICANT_BIT 240 inline int MostSignificantBitPosition32Fast(uint32_t n) {
244 const int offset = __builtin_clzl(1);
245 return n == 0 ? 0 : (offset - __builtin_clzl(n));
274 #ifdef USE_FAST_LEAST_SIGNIFICANT_BIT 275 return MostSignificantBitPosition32Fast(n);
282 #undef USE_FAST_LEAST_SIGNIFICANT_BIT 330 inline uint32_t
BitPos64(uint64_t pos) {
return (pos & 63); }
331 inline uint32_t
BitPos32(uint32_t pos) {
return (pos & 31); }
338 inline uint64_t
BitLength64(uint64_t size) {
return ((size + 63) >> 6); }
339 inline uint32_t
BitLength32(uint32_t size) {
return ((size + 31) >> 5); }
346 inline bool IsBitSet64(
const uint64_t*
const bitset, uint64_t pos) {
349 inline bool IsBitSet32(
const uint32_t*
const bitset, uint32_t pos) {
354 inline void SetBit64(uint64_t*
const bitset, uint64_t pos) {
357 inline void SetBit32(uint32_t*
const bitset, uint32_t pos) {
362 inline void ClearBit64(uint64_t*
const bitset, uint64_t pos) {
365 inline void ClearBit32(uint32_t*
const bitset, uint32_t pos) {
376 bool IsEmptyRange64(
const uint64_t*
const bitset, uint64_t start, uint64_t end);
377 bool IsEmptyRange32(
const uint32_t*
const bitset, uint32_t start, uint32_t end);
381 uint64_t start, uint64_t end);
387 uint64_t start, uint64_t end);
394 uint64_t start, uint64_t end);
396 uint32_t start, uint32_t end);
399 uint64_t start, uint64_t end);
401 uint32_t start, uint32_t end);
405 return uint64_t{3} << (pos & 62);
413 template <
typename IndexType =
int64_t>
416 Bitset64() : size_(), data_(), end_(*this, true) {}
418 : size_(Value(
size) > 0 ?
size : IndexType(0)),
423 IndexType
size()
const {
return size_; }
435 size_ = Value(
size) > 0 ?
size : IndexType(0);
442 size_ = Value(
size) > 0 ?
size : IndexType(0);
447 const size_t bit_length = static_cast<size_t>(
BitLength64(Value(size_)));
448 const size_t to_clear =
std::min(data_.size(), bit_length);
449 data_.resize(bit_length, 0);
450 memset(data_.data(), 0, to_clear *
sizeof(int64_t));
454 void ClearAll() { memset(data_.data(), 0, data_.size() *
sizeof(int64_t)); }
513 data_[offset] = other.data_[offset];
519 template <
typename OtherIndexType>
521 const int64_t min_size =
std::min(data_.size(), other.data_.size());
522 if (min_size == 0)
return;
523 const uint64_t last_common_bucket = data_[min_size - 1];
524 memcpy(data_.data(), other.data_.data(), min_size *
sizeof(uint64_t));
525 if (data_.size() >= other.data_.size()) {
528 data_[min_size - 1] &= ~bitmask;
529 data_[min_size - 1] |= (bitmask & last_common_bucket);
534 template <
typename OtherIndexType>
537 memcpy(data_.data(), other.data_.data(), data_.size() *
sizeof(uint64_t));
544 const int min_size =
std::min(data_.size(), other.data_.size());
545 for (
int i = 0; i < min_size; ++i) {
546 data_[i] &= other.data_[i];
548 for (
int i = min_size; i < data_.size(); ++i) {
557 const int min_size =
std::min(data_.size(), other.data_.size());
558 for (
int i = 0; i < min_size; ++i) {
559 data_[i] |= other.data_[i];
570 : bitset_(data_), index_(0), base_index_(0), current_(0) {
571 if (bitset_.data_.empty()) {
574 current_ = bitset_.data_[0];
580 bool Ok()
const {
return index_ != -1; }
585 return IndexType(index_);
593 const int size = bitset_.data_.size();
596 }
while (bucket <
size && bitset_.data_[bucket] == 0);
597 if (bucket ==
size) {
601 current_ = bitset_.data_[bucket];
607 current_ &= current_ - 1;
612 : bitset_(data_), index_(0), base_index_(0), current_(0) {
613 if (at_end || bitset_.data_.empty()) {
616 current_ = bitset_.data_[0];
621 return index_ != other.index_;
623 IndexType
operator*()
const {
return IndexType(index_); }
638 Iterator
begin()
const {
return Iterator(*
this); }
639 Iterator
end()
const {
return end_; }
647 DCHECK_EQ(set1.data_.size(), set1.data_.size());
648 DCHECK(use1 == 0 || use1 == 1);
649 DCHECK(use2 == 0 || use2 == 1);
652 return ((use1 << pos) & set1.data_[bucket]) ^
653 ((use2 << pos) & set2.data_[bucket]);
659 for (IndexType i(0); i <
size(); ++i) {
660 output +=
IsSet(i) ?
"1" :
"0";
668 static int64_t Value(IndexType
input);
671 std::vector<uint64_t> data_;
677 template <
class OtherIndexType>
688 : size_(size), top_(-1), data_(
BitLength64(size), 0) {}
714 int bucket_index = static_cast<int>(
BitOffset64(i));
716 for (--bucket_index; bucket_index >= 0; --bucket_index) {
722 int Top()
const {
return top_; }
727 int bucket_index = static_cast<int>(
BitOffset64(top_));
730 if (bucket_index == 0) {
734 bucket = data_[--bucket_index];
740 top_ = static_cast<int>(
BitShift64(bucket_index) +
747 std::vector<uint64_t> data_;
752 template <
typename IntType>
753 inline int64_t Bitset64<IntType>::Value(IntType
input) {
755 return input.value();
758 inline int64_t Bitset64<int64_t>::Value(int64_t
input) {
765 template <
typename IntegerType =
int64_t>
770 IntegerType
size()
const {
return bitset_.size(); }
772 for (
const IntegerType i : to_clear_) bitset_.ClearBucket(i);
781 const int kSparseThreshold = 300;
782 if (to_clear_.size() * kSparseThreshold < size) {
784 bitset_.Resize(size);
786 bitset_.ClearAndResize(size);
791 if (size < bitset_.size()) {
793 for (IntegerType
index : to_clear_) {
795 to_clear_[new_index] =
index;
799 to_clear_.resize(new_index);
801 bitset_.Resize(size);
805 if (!bitset_[
index]) {
807 to_clear_.push_back(
index);
812 return to_clear_.size();
833 std::vector<IntegerType> to_clear_;
839 #endif // OR_TOOLS_UTIL_BITSET_H_
int64_t UnsafeLeastSignificantBitPosition64(const uint64_t *const bitset, uint64_t start, uint64_t end)
void SetContentFromBitsetOfSameSize(const Bitset64< OtherIndexType > &other)
void Set(IntegerType index)
int32_t UnsafeMostSignificantBitPosition32(const uint32_t *const bitset, uint32_t start, uint32_t end)
int MostSignificantBitPosition32Default(uint32_t n)
IndexType operator *() const
#define CHECK_GE(val1, val2)
uint64_t BitLength64(uint64_t size)
uint64_t BitShift64(uint64_t v)
bool IsEmptyRange32(const uint32_t *const bitset, uint32_t start, uint32_t end)
uint32_t BitShift32(uint32_t v)
uint32_t LeastSignificantBitWord32(uint32_t n)
static const uint64_t kAllBits64
void Intersection(const Bitset64< IndexType > &other)
void ClearBit32(uint32_t *const bitset, uint32_t pos)
uint32_t IntervalUp32(uint32_t s)
static uint64_t ConditionalXorOfTwoBits(IndexType i, uint64_t use1, const Bitset64< IndexType > &set1, uint64_t use2, const Bitset64< IndexType > &set2)
uint64_t LeastSignificantBitWord64(uint64_t n)
int LeastSignificantBitPosition32Default(uint32_t n)
void Resize(IntegerType size)
void Clear(IntegerType index)
uint32_t BitOffset32(uint32_t pos)
uint64_t OneRange64(uint64_t s, uint64_t e)
uint32_t BitPos32(uint32_t pos)
void SetBit32(uint32_t *const bitset, uint32_t pos)
uint32_t OneBit32(int pos)
int64_t UnsafeMostSignificantBitPosition64(const uint64_t *const bitset, uint64_t start, uint64_t end)
bool IsBitSet32(const uint32_t *const bitset, uint32_t pos)
uint32_t BitLength32(uint32_t size)
void ClearAndResize(int size)
uint32_t BitCount32(uint32_t n)
void Set(IndexType i, bool value)
std::string DebugString() const
void ClearBit64(uint64_t *const bitset, uint64_t pos)
int MostSignificantBitPosition32(uint32_t n)
void ClearAndResize(IndexType size)
void ClearTwoBits(IndexType i)
int MostSignificantBitPosition64(uint64_t n)
void CopyBucket(const Bitset64< IndexType > &other, IndexType i)
uint64_t IntervalUp64(uint64_t s)
uint64_t TwoBitsFromPos64(uint64_t pos)
#define DCHECK_NE(val1, val2)
uint32_t IntervalDown32(uint32_t s)
int LeastSignificantBitPosition32DeBruijn(uint32_t n)
uint64_t BitOffset64(uint64_t pos)
Iterator(const Bitset64 &data_, bool at_end)
uint32_t BitCountRange32(const uint32_t *const bitset, uint32_t start, uint32_t end)
static int input(yyscan_t yyscanner)
uint64_t IntervalDown64(uint64_t s)
void ClearBucket(IndexType i)
int NumberOfSetCallsWithDifferentArguments() const
#define DCHECK_GE(val1, val2)
static const uint32_t kAllBits32
void SetBit64(uint64_t *const bitset, uint64_t pos)
int32_t UnsafeLeastSignificantBitPosition32(const uint32_t *const bitset, uint32_t start, uint32_t end)
#define DCHECK(condition)
bool operator[](IntegerType index) const
#define DCHECK_EQ(val1, val2)
void ClearAndResize(IntegerType size)
uint64_t BitCountRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
void SetContentFromBitset(const Bitset64< OtherIndexType > &other)
bool IsSet(IndexType i) const
int LeastSignificantBitPosition64(uint64_t n)
uint64_t BitCount64(uint64_t n)
#define DCHECK_LE(val1, val2)
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
SparseBitset(IntegerType size)
bool operator[](IndexType i) const
uint32_t BitPos64(uint64_t pos)
Collection of objects used to extend the Constraint Solver library.
bool IsBitSet64(const uint64_t *const bitset, uint64_t pos)
int MostSignificantBitPosition64Default(uint64_t n)
void IncreaseSize(int size)
void Union(const Bitset64< IndexType > &other)
int LeastSignificantBitPosition32(uint32_t n)
void PushBack(bool value)
bool IsEmptyRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
static const uint64_t kAllBitsButLsb64
int LeastSignificantBitPosition64Default(uint64_t n)
void Resize(IndexType size)
Iterator(const Bitset64 &data_)
bool AreOneOfTwoBitsSet(IndexType i) const
uint32_t OneRange32(uint32_t s, uint32_t e)
bool operator!=(const Iterator &other) const
uint64_t OneBit64(int pos)
#define DCHECK_LT(val1, val2)
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
int LeastSignificantBitPosition64DeBruijn(uint64_t n)