bitvector.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #pragma once
  2. #include "traits.h"
  3. #include <library/cpp/pop_count/popcount.h>
  4. #include <util/generic/vector.h>
  5. #include <util/ysaveload.h>
  6. template <typename T>
  7. class TReadonlyBitVector;
  8. template <typename T>
  9. class TBitVector {
  10. public:
  11. using TWord = T;
  12. using TTraits = TBitSeqTraits<TWord>;
  13. private:
  14. friend class TReadonlyBitVector<T>;
  15. ui64 Size_;
  16. TVector<TWord> Data_;
  17. public:
  18. TBitVector()
  19. : Size_(0)
  20. , Data_(0)
  21. {
  22. }
  23. TBitVector(ui64 size)
  24. : Size_(size)
  25. , Data_(static_cast<size_t>((Size_ + TTraits::ModMask) >> TTraits::DivShift), 0)
  26. {
  27. }
  28. virtual ~TBitVector() = default;
  29. void Clear() {
  30. Size_ = 0;
  31. Data_.clear();
  32. }
  33. void Resize(ui64 size) {
  34. Size_ = size;
  35. Data_.resize((Size_ + TTraits::ModMask) >> TTraits::DivShift);
  36. }
  37. void Swap(TBitVector& other) {
  38. DoSwap(Size_, other.Size_);
  39. DoSwap(Data_, other.Data_);
  40. }
  41. bool Set(ui64 pos) {
  42. Y_ASSERT(pos < Size_);
  43. TWord& val = Data_[pos >> TTraits::DivShift];
  44. if (val & TTraits::BitMask(pos & TTraits::ModMask))
  45. return false;
  46. val |= TTraits::BitMask(pos & TTraits::ModMask);
  47. return true;
  48. }
  49. bool Test(ui64 pos) const {
  50. return TTraits::Test(Data(), pos, Size_);
  51. }
  52. void Reset(ui64 pos) {
  53. Y_ASSERT(pos < Size_);
  54. Data_[pos >> TTraits::DivShift] &= ~TTraits::BitMask(pos & TTraits::ModMask);
  55. }
  56. TWord Get(ui64 pos, ui8 width, TWord mask) const {
  57. return TTraits::Get(Data(), pos, width, mask, Size_);
  58. }
  59. TWord Get(ui64 pos, ui8 width) const {
  60. return Get(pos, width, TTraits::ElemMask(width));
  61. }
  62. void Set(ui64 pos, TWord value, ui8 width, TWord mask) {
  63. if (!width)
  64. return;
  65. Y_ASSERT((pos + width) <= Size_);
  66. size_t word = pos >> TTraits::DivShift;
  67. TWord shift1 = pos & TTraits::ModMask;
  68. TWord shift2 = TTraits::NumBits - shift1;
  69. Data_[word] &= ~(mask << shift1);
  70. Data_[word] |= (value & mask) << shift1;
  71. if (shift2 < width) {
  72. Data_[word + 1] &= ~(mask >> shift2);
  73. Data_[word + 1] |= (value & mask) >> shift2;
  74. }
  75. }
  76. void Set(ui64 pos, TWord value, ui8 width) {
  77. Set(pos, value, width, TTraits::ElemMask(width));
  78. }
  79. void Append(TWord value, ui8 width, TWord mask) {
  80. if (!width)
  81. return;
  82. if (Data_.size() * TTraits::NumBits < Size_ + width) {
  83. Data_.push_back(0);
  84. }
  85. Size_ += width;
  86. Set(Size_ - width, value, width, mask);
  87. }
  88. void Append(TWord value, ui8 width) {
  89. Append(value, width, TTraits::ElemMask(width));
  90. }
  91. size_t Count() const {
  92. size_t count = 0;
  93. for (size_t i = 0; i < Data_.size(); ++i) {
  94. count += (size_t)PopCount(Data_[i]);
  95. }
  96. return count;
  97. }
  98. ui64 Size() const {
  99. return Size_;
  100. }
  101. size_t Words() const {
  102. return Data_.size();
  103. }
  104. const TWord* Data() const {
  105. return Data_.data();
  106. }
  107. void Save(IOutputStream* out) const {
  108. ::Save(out, Size_);
  109. ::Save(out, Data_);
  110. }
  111. void Load(IInputStream* inp) {
  112. ::Load(inp, Size_);
  113. ::Load(inp, Data_);
  114. }
  115. ui64 Space() const {
  116. return CHAR_BIT * (sizeof(Size_) +
  117. Data_.size() * sizeof(TWord));
  118. }
  119. void Print(IOutputStream& out, size_t truncate = 128) {
  120. for (size_t i = 0; i < Data_.size() && i < truncate; ++i) {
  121. for (int j = TTraits::NumBits - 1; j >= 0; --j) {
  122. size_t pos = TTraits::NumBits * i + j;
  123. out << (pos < Size_ && Test(pos) ? '1' : '0');
  124. }
  125. out << " ";
  126. }
  127. out << Endl;
  128. }
  129. };