blob: e9499994f6cc56b1adfc6ba43260d98ce7e3c6a5 [file] [log] [blame]
#include "bitvector.h"
#include "popcount.h"
namespace marisa_alpha {
namespace {
const UInt8 SelectTable[8][256] = {
{
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
},
{
7, 7, 7, 1, 7, 2, 2, 1, 7, 3, 3, 1, 3, 2, 2, 1,
7, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
7, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
7, 6, 6, 1, 6, 2, 2, 1, 6, 3, 3, 1, 3, 2, 2, 1,
6, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
6, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
7, 7, 7, 1, 7, 2, 2, 1, 7, 3, 3, 1, 3, 2, 2, 1,
7, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
7, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
7, 6, 6, 1, 6, 2, 2, 1, 6, 3, 3, 1, 3, 2, 2, 1,
6, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
6, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1
},
{
7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 3, 7, 3, 3, 2,
7, 7, 7, 4, 7, 4, 4, 2, 7, 4, 4, 3, 4, 3, 3, 2,
7, 7, 7, 5, 7, 5, 5, 2, 7, 5, 5, 3, 5, 3, 3, 2,
7, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2,
7, 7, 7, 6, 7, 6, 6, 2, 7, 6, 6, 3, 6, 3, 3, 2,
7, 6, 6, 4, 6, 4, 4, 2, 6, 4, 4, 3, 4, 3, 3, 2,
7, 6, 6, 5, 6, 5, 5, 2, 6, 5, 5, 3, 5, 3, 3, 2,
6, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2,
7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 3, 7, 3, 3, 2,
7, 7, 7, 4, 7, 4, 4, 2, 7, 4, 4, 3, 4, 3, 3, 2,
7, 7, 7, 5, 7, 5, 5, 2, 7, 5, 5, 3, 5, 3, 3, 2,
7, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2,
7, 7, 7, 6, 7, 6, 6, 2, 7, 6, 6, 3, 6, 3, 3, 2,
7, 6, 6, 4, 6, 4, 4, 2, 6, 4, 4, 3, 4, 3, 3, 2,
7, 6, 6, 5, 6, 5, 5, 2, 6, 5, 5, 3, 5, 3, 3, 2,
6, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2
},
{
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3,
7, 7, 7, 7, 7, 7, 7, 4, 7, 7, 7, 4, 7, 4, 4, 3,
7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 3,
7, 7, 7, 5, 7, 5, 5, 4, 7, 5, 5, 4, 5, 4, 4, 3,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 3,
7, 7, 7, 6, 7, 6, 6, 4, 7, 6, 6, 4, 6, 4, 4, 3,
7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 3,
7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3,
7, 7, 7, 7, 7, 7, 7, 4, 7, 7, 7, 4, 7, 4, 4, 3,
7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 3,
7, 7, 7, 5, 7, 5, 5, 4, 7, 5, 5, 4, 5, 4, 4, 3,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 3,
7, 7, 7, 6, 7, 6, 6, 4, 7, 6, 6, 4, 6, 4, 4, 3,
7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 3,
7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3
},
{
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 4,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 4,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5,
7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 4,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 4,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5,
7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4
},
{
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5
},
{
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6
},
{
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
}
};
} // namespace
BitVector::BitVector()
: blocks_(), size_(0), ranks_(), select0s_(), select1s_() {}
void BitVector::build() {
Vector<Rank> ranks;
const UInt32 num_blocks = (size_ / 512) + (((size_ % 512) != 0) ? 1 : 0);
ranks.resize(num_blocks + 1);
Vector<UInt32> select0s;
Vector<UInt32> select1s;
UInt32 num_0s = 0;
UInt32 num_1s = 0;
for (UInt32 i = 0; i < size_; ++i) {
if ((i % 64) == 0) {
UInt32 rank_id = i / 512;
switch ((i / 64) % 8) {
case 0: {
ranks[rank_id].set_abs(num_1s);
break;
}
case 1: {
ranks[rank_id].set_rel1(num_1s - ranks[rank_id].abs());
break;
}
case 2: {
ranks[rank_id].set_rel2(num_1s - ranks[rank_id].abs());
break;
}
case 3: {
ranks[rank_id].set_rel3(num_1s - ranks[rank_id].abs());
break;
}
case 4: {
ranks[rank_id].set_rel4(num_1s - ranks[rank_id].abs());
break;
}
case 5: {
ranks[rank_id].set_rel5(num_1s - ranks[rank_id].abs());
break;
}
case 6: {
ranks[rank_id].set_rel6(num_1s - ranks[rank_id].abs());
break;
}
case 7: {
ranks[rank_id].set_rel7(num_1s - ranks[rank_id].abs());
break;
}
}
}
if ((*this)[i]) {
if ((num_1s % 512) == 0) {
select1s.push_back(i);
}
++num_1s;
} else {
if ((num_0s % 512) == 0) {
select0s.push_back(i);
}
++num_0s;
}
}
if ((size_ % 512) != 0) {
UInt32 rank_id = (size_ - 1) / 512;
switch (((size_ - 1) / 64) % 8) {
case 0: {
ranks[rank_id].set_rel1(num_1s - ranks[rank_id].abs());
}
case 1: {
ranks[rank_id].set_rel2(num_1s - ranks[rank_id].abs());
}
case 2: {
ranks[rank_id].set_rel3(num_1s - ranks[rank_id].abs());
}
case 3: {
ranks[rank_id].set_rel4(num_1s - ranks[rank_id].abs());
}
case 4: {
ranks[rank_id].set_rel5(num_1s - ranks[rank_id].abs());
}
case 5: {
ranks[rank_id].set_rel6(num_1s - ranks[rank_id].abs());
}
case 6: {
ranks[rank_id].set_rel7(num_1s - ranks[rank_id].abs());
break;
}
}
}
ranks.back().set_abs(num_1s);
select0s.push_back(size_);
select1s.push_back(size_);
select0s.shrink();
select1s.shrink();
blocks_.shrink();
ranks_.swap(&ranks);
select0s_.swap(&select0s);
select1s_.swap(&select1s);
}
void BitVector::mmap(Mapper *mapper, const char *filename,
long offset, int whence) {
MARISA_ALPHA_THROW_IF(mapper == NULL, MARISA_ALPHA_PARAM_ERROR);
Mapper temp_mapper;
temp_mapper.open(filename, offset, whence);
map(temp_mapper);
temp_mapper.swap(mapper);
}
void BitVector::map(const void *ptr, std::size_t size) {
Mapper mapper(ptr, size);
map(mapper);
}
void BitVector::map(Mapper &mapper) {
BitVector temp;
temp.blocks_.map(mapper);
mapper.map(&temp.size_);
temp.ranks_.map(mapper);
temp.select0s_.map(mapper);
temp.select1s_.map(mapper);
temp.swap(this);
}
void BitVector::load(const char *filename,
long offset, int whence) {
Reader reader;
reader.open(filename, offset, whence);
read(reader);
}
void BitVector::fread(std::FILE *file) {
Reader reader(file);
read(reader);
}
void BitVector::read(int fd) {
Reader reader(fd);
read(reader);
}
void BitVector::read(std::istream &stream) {
Reader reader(&stream);
read(reader);
}
void BitVector::read(Reader &reader) {
BitVector temp;
temp.blocks_.read(reader);
reader.read(&temp.size_);
temp.ranks_.read(reader);
temp.select0s_.read(reader);
temp.select1s_.read(reader);
temp.swap(this);
}
void BitVector::save(const char *filename, bool trunc_flag,
long offset, int whence) const {
Writer writer;
writer.open(filename, trunc_flag, offset, whence);
write(writer);
}
void BitVector::fwrite(std::FILE *file) const {
Writer writer(file);
write(writer);
}
void BitVector::write(int fd) const {
Writer writer(fd);
write(writer);
}
void BitVector::write(std::ostream &stream) const {
Writer writer(&stream);
write(writer);
}
void BitVector::write(Writer &writer) const {
blocks_.write(writer);
writer.write(size_);
ranks_.write(writer);
select0s_.write(writer);
select1s_.write(writer);
}
UInt32 BitVector::rank1(UInt32 i) const {
MARISA_ALPHA_DEBUG_IF(i > size_, MARISA_ALPHA_PARAM_ERROR);
const Rank &rank = ranks_[i / 512];
UInt32 offset = rank.abs();
switch ((i / 64) % 8) {
case 1: {
offset += rank.rel1();
break;
}
case 2: {
offset += rank.rel2();
break;
}
case 3: {
offset += rank.rel3();
break;
}
case 4: {
offset += rank.rel4();
break;
}
case 5: {
offset += rank.rel5();
break;
}
case 6: {
offset += rank.rel6();
break;
}
case 7: {
offset += rank.rel7();
break;
}
}
switch ((i / 32) % 2) {
case 1: {
offset += PopCount(blocks_[(i / 32) - 1]).lo32();
}
case 0: {
offset += PopCount(blocks_[i / 32] & ((1U << (i % 32)) - 1)).lo32();
break;
}
}
return offset;
}
UInt32 BitVector::select0(UInt32 i) const {
UInt32 select_id = i / 512;
MARISA_ALPHA_DEBUG_IF((select_id + 1) >= select0s_.size(),
MARISA_ALPHA_PARAM_ERROR);
if ((i % 512) == 0) {
return select0s_[select_id];
}
UInt32 begin = select0s_[select_id] / 512;
UInt32 end = (select0s_[select_id + 1] + 511) / 512;
if (begin + 10 >= end) {
while (i >= ((begin + 1) * 512) - ranks_[begin + 1].abs()) {
++begin;
}
} else {
while (begin + 1 < end) {
UInt32 middle = (begin + end) / 2;
if (i < (middle * 512) - ranks_[middle].abs()) {
end = middle;
} else {
begin = middle;
}
}
}
const UInt32 rank_id = begin;
i -= (rank_id * 512) - ranks_[rank_id].abs();
const Rank &rank = ranks_[rank_id];
UInt32 block_id = rank_id * 16;
if (i < (256U - rank.rel4())) {
if (i < (128U - rank.rel2())) {
if (i >= (64U - rank.rel1())) {
block_id += 2;
i -= 64 - rank.rel1();
}
} else if (i < (192U - rank.rel3())) {
block_id += 4;
i -= 128 - rank.rel2();
} else {
block_id += 6;
i -= 192 - rank.rel3();
}
} else if (i < (384U - rank.rel6())) {
if (i < (320U - rank.rel5())) {
block_id += 8;
i -= 256 - rank.rel4();
} else {
block_id += 10;
i -= 320 - rank.rel5();
}
} else if (i < (448U - rank.rel7())) {
block_id += 12;
i -= 384 - rank.rel6();
} else {
block_id += 14;
i -= 448 - rank.rel7();
}
UInt32 block = ~blocks_[block_id];
PopCount count(block);
if (i >= count.lo32()) {
++block_id;
i -= count.lo32();
block = ~blocks_[block_id];
count = PopCount(block);
}
UInt32 bit_id = block_id * 32;
if (i < count.lo16()) {
if (i >= count.lo8()) {
bit_id += 8;
block >>= 8;
i -= count.lo8();
}
} else if (i < count.lo24()) {
bit_id += 16;
block >>= 16;
i -= count.lo16();
} else {
bit_id += 24;
block >>= 24;
i -= count.lo24();
}
return bit_id + SelectTable[i][block & 0xFF];
}
UInt32 BitVector::select1(UInt32 i) const {
UInt32 select_id = i / 512;
MARISA_ALPHA_DEBUG_IF((select_id + 1) >= select1s_.size(),
MARISA_ALPHA_PARAM_ERROR);
if ((i % 512) == 0) {
return select1s_[select_id];
}
UInt32 begin = select1s_[select_id] / 512;
UInt32 end = (select1s_[select_id + 1] + 511) / 512;
if (begin + 10 >= end) {
while (i >= ranks_[begin + 1].abs()) {
++begin;
}
} else {
while (begin + 1 < end) {
UInt32 middle = (begin + end) / 2;
if (i < ranks_[middle].abs()) {
end = middle;
} else {
begin = middle;
}
}
}
const UInt32 rank_id = begin;
i -= ranks_[rank_id].abs();
const Rank &rank = ranks_[rank_id];
UInt32 block_id = rank_id * 16;
if (i < rank.rel4()) {
if (i < rank.rel2()) {
if (i >= rank.rel1()) {
block_id += 2;
i -= rank.rel1();
}
} else if (i < rank.rel3()) {
block_id += 4;
i -= rank.rel2();
} else {
block_id += 6;
i -= rank.rel3();
}
} else if (i < rank.rel6()) {
if (i < rank.rel5()) {
block_id += 8;
i -= rank.rel4();
} else {
block_id += 10;
i -= rank.rel5();
}
} else if (i < rank.rel7()) {
block_id += 12;
i -= rank.rel6();
} else {
block_id += 14;
i -= rank.rel7();
}
UInt32 block = blocks_[block_id];
PopCount count(block);
if (i >= count.lo32()) {
++block_id;
i -= count.lo32();
block = blocks_[block_id];
count = PopCount(block);
}
UInt32 bit_id = block_id * 32;
if (i < count.lo16()) {
if (i >= count.lo8()) {
bit_id += 8;
block >>= 8;
i -= count.lo8();
}
} else if (i < count.lo24()) {
bit_id += 16;
block >>= 16;
i -= count.lo16();
} else {
bit_id += 24;
block >>= 24;
i -= count.lo24();
}
return bit_id + SelectTable[i][block & 0xFF];
}
void BitVector::clear() {
BitVector().swap(this);
}
void BitVector::swap(BitVector *rhs) {
MARISA_ALPHA_THROW_IF(rhs == NULL, MARISA_ALPHA_PARAM_ERROR);
blocks_.swap(&rhs->blocks_);
Swap(&size_, &rhs->size_);
ranks_.swap(&rhs->ranks_);
select0s_.swap(&rhs->select0s_);
select1s_.swap(&rhs->select1s_);
}
} // namespace marisa_alpha