aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/containers/bitseq/bitvector.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/containers/bitseq/bitvector.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/containers/bitseq/bitvector.h')
-rw-r--r--library/cpp/containers/bitseq/bitvector.h158
1 files changed, 158 insertions, 0 deletions
diff --git a/library/cpp/containers/bitseq/bitvector.h b/library/cpp/containers/bitseq/bitvector.h
new file mode 100644
index 0000000000..3f8fd81ee5
--- /dev/null
+++ b/library/cpp/containers/bitseq/bitvector.h
@@ -0,0 +1,158 @@
+#pragma once
+
+#include "traits.h"
+
+#include <library/cpp/pop_count/popcount.h>
+
+#include <util/generic/vector.h>
+#include <util/ysaveload.h>
+
+template <typename T>
+class TReadonlyBitVector;
+
+template <typename T>
+class TBitVector {
+public:
+ using TWord = T;
+ using TTraits = TBitSeqTraits<TWord>;
+
+private:
+ friend class TReadonlyBitVector<T>;
+ ui64 Size_;
+ TVector<TWord> Data_;
+
+public:
+ TBitVector()
+ : Size_(0)
+ , Data_(0)
+ {
+ }
+
+ TBitVector(ui64 size)
+ : Size_(size)
+ , Data_(static_cast<size_t>((Size_ + TTraits::ModMask) >> TTraits::DivShift), 0)
+ {
+ }
+
+ virtual ~TBitVector() = default;
+
+ void Clear() {
+ Size_ = 0;
+ Data_.clear();
+ }
+
+ void Resize(ui64 size) {
+ Size_ = size;
+ Data_.resize((Size_ + TTraits::ModMask) >> TTraits::DivShift);
+ }
+
+ void Swap(TBitVector& other) {
+ DoSwap(Size_, other.Size_);
+ DoSwap(Data_, other.Data_);
+ }
+
+ bool Set(ui64 pos) {
+ Y_ASSERT(pos < Size_);
+ TWord& val = Data_[pos >> TTraits::DivShift];
+ if (val & TTraits::BitMask(pos & TTraits::ModMask))
+ return false;
+ val |= TTraits::BitMask(pos & TTraits::ModMask);
+ return true;
+ }
+
+ bool Test(ui64 pos) const {
+ return TTraits::Test(Data(), pos, Size_);
+ }
+
+ void Reset(ui64 pos) {
+ Y_ASSERT(pos < Size_);
+ Data_[pos >> TTraits::DivShift] &= ~TTraits::BitMask(pos & TTraits::ModMask);
+ }
+
+ TWord Get(ui64 pos, ui8 width, TWord mask) const {
+ return TTraits::Get(Data(), pos, width, mask, Size_);
+ }
+
+ TWord Get(ui64 pos, ui8 width) const {
+ return Get(pos, width, TTraits::ElemMask(width));
+ }
+
+ void Set(ui64 pos, TWord value, ui8 width, TWord mask) {
+ if (!width)
+ return;
+ Y_ASSERT((pos + width) <= Size_);
+ size_t word = pos >> TTraits::DivShift;
+ TWord shift1 = pos & TTraits::ModMask;
+ TWord shift2 = TTraits::NumBits - shift1;
+ Data_[word] &= ~(mask << shift1);
+ Data_[word] |= (value & mask) << shift1;
+ if (shift2 < width) {
+ Data_[word + 1] &= ~(mask >> shift2);
+ Data_[word + 1] |= (value & mask) >> shift2;
+ }
+ }
+
+ void Set(ui64 pos, TWord value, ui8 width) {
+ Set(pos, value, width, TTraits::ElemMask(width));
+ }
+
+ void Append(TWord value, ui8 width, TWord mask) {
+ if (!width)
+ return;
+ if (Data_.size() * TTraits::NumBits < Size_ + width) {
+ Data_.push_back(0);
+ }
+ Size_ += width;
+ Set(Size_ - width, value, width, mask);
+ }
+
+ void Append(TWord value, ui8 width) {
+ Append(value, width, TTraits::ElemMask(width));
+ }
+
+ size_t Count() const {
+ size_t count = 0;
+ for (size_t i = 0; i < Data_.size(); ++i) {
+ count += (size_t)PopCount(Data_[i]);
+ }
+ return count;
+ }
+
+ ui64 Size() const {
+ return Size_;
+ }
+
+ size_t Words() const {
+ return Data_.size();
+ }
+
+ const TWord* Data() const {
+ return Data_.data();
+ }
+
+ void Save(IOutputStream* out) const {
+ ::Save(out, Size_);
+ ::Save(out, Data_);
+ }
+
+ void Load(IInputStream* inp) {
+ ::Load(inp, Size_);
+ ::Load(inp, Data_);
+ }
+
+ ui64 Space() const {
+ return CHAR_BIT * (sizeof(Size_) +
+ Data_.size() * sizeof(TWord));
+ }
+
+ void Print(IOutputStream& out, size_t truncate = 128) {
+ for (size_t i = 0; i < Data_.size() && i < truncate; ++i) {
+ for (int j = TTraits::NumBits - 1; j >= 0; --j) {
+ size_t pos = TTraits::NumBits * i + j;
+ out << (pos < Size_ && Test(pos) ? '1' : '0');
+ }
+ out << " ";
+ }
+ out << Endl;
+ }
+};