#ifndef MARISA_GRIMOIRE_VECTOR_BIT_VECTOR_H_ #define MARISA_GRIMOIRE_VECTOR_BIT_VECTOR_H_ #include "marisa/grimoire/vector/rank-index.h" #include "marisa/grimoire/vector/vector.h" namespace marisa { namespace grimoire { namespace vector { class BitVector { public: #if MARISA_WORD_SIZE == 64 typedef UInt64 Unit; #else // MARISA_WORD_SIZE == 64 typedef UInt32 Unit; #endif // MARISA_WORD_SIZE == 64 BitVector() : units_(), size_(0), num_1s_(0), ranks_(), select0s_(), select1s_() {} void build(bool enables_select0, bool enables_select1) { BitVector temp; temp.build_index(*this, enables_select0, enables_select1); units_.shrink(); temp.units_.swap(units_); swap(temp); } void map(Mapper &mapper) { BitVector temp; temp.map_(mapper); swap(temp); } void read(Reader &reader) { BitVector temp; temp.read_(reader); swap(temp); } void write(Writer &writer) const { write_(writer); } void disable_select0() { select0s_.clear(); } void disable_select1() { select1s_.clear(); } void push_back(bool bit) { MARISA_THROW_IF(size_ == MARISA_UINT32_MAX, MARISA_SIZE_ERROR); if (size_ == (MARISA_WORD_SIZE * units_.size())) { units_.resize(units_.size() + (64 / MARISA_WORD_SIZE), 0); } if (bit) { units_[size_ / MARISA_WORD_SIZE] |= (Unit)1 << (size_ % MARISA_WORD_SIZE); ++num_1s_; } ++size_; } bool operator[](std::size_t i) const { MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR); return (units_[i / MARISA_WORD_SIZE] & ((Unit)1 << (i % MARISA_WORD_SIZE))) != 0; } std::size_t rank0(std::size_t i) const { MARISA_DEBUG_IF(ranks_.empty(), MARISA_STATE_ERROR); MARISA_DEBUG_IF(i > size_, MARISA_BOUND_ERROR); return i - rank1(i); } std::size_t rank1(std::size_t i) const; std::size_t select0(std::size_t i) const; std::size_t select1(std::size_t i) const; std::size_t num_0s() const { return size_ - num_1s_; } std::size_t num_1s() const { return num_1s_; } bool empty() const { return size_ == 0; } std::size_t size() const { return size_; } std::size_t total_size() const { return units_.total_size() + ranks_.total_size() + select0s_.total_size() + select1s_.total_size(); } std::size_t io_size() const { return units_.io_size() + (sizeof(UInt32) * 2) + ranks_.io_size() + select0s_.io_size() + select1s_.io_size(); } void clear() { BitVector().swap(*this); } void swap(BitVector &rhs) { units_.swap(rhs.units_); marisa::swap(size_, rhs.size_); marisa::swap(num_1s_, rhs.num_1s_); ranks_.swap(rhs.ranks_); select0s_.swap(rhs.select0s_); select1s_.swap(rhs.select1s_); } private: Vector units_; std::size_t size_; std::size_t num_1s_; Vector ranks_; Vector select0s_; Vector select1s_; void build_index(const BitVector &bv, bool enables_select0, bool enables_select1); void map_(Mapper &mapper) { units_.map(mapper); { UInt32 temp_size; mapper.map(&temp_size); size_ = temp_size; } { UInt32 temp_num_1s; mapper.map(&temp_num_1s); MARISA_THROW_IF(temp_num_1s > size_, MARISA_FORMAT_ERROR); num_1s_ = temp_num_1s; } ranks_.map(mapper); select0s_.map(mapper); select1s_.map(mapper); } void read_(Reader &reader) { units_.read(reader); { UInt32 temp_size; reader.read(&temp_size); size_ = temp_size; } { UInt32 temp_num_1s; reader.read(&temp_num_1s); MARISA_THROW_IF(temp_num_1s > size_, MARISA_FORMAT_ERROR); num_1s_ = temp_num_1s; } ranks_.read(reader); select0s_.read(reader); select1s_.read(reader); } void write_(Writer &writer) const { units_.write(writer); writer.write((UInt32)size_); writer.write((UInt32)num_1s_); ranks_.write(writer); select0s_.write(writer); select1s_.write(writer); } // Disallows copy and assignment. BitVector(const BitVector &); BitVector &operator=(const BitVector &); }; } // namespace vector } // namespace grimoire } // namespace marisa #endif // MARISA_GRIMOIRE_VECTOR_BIT_VECTOR_H_