xcdat/lib/FastDacBc.cpp

189 lines
5.3 KiB
C++
Raw Normal View History

2017-11-12 11:49:13 +00:00
#include "xcdat/FastDacBc.hpp"
2016-12-03 07:51:00 +00:00
namespace xcdat {
2017-07-12 06:48:49 +00:00
FastDacBc::FastDacBc(std::istream& is) {
values_L1_ = Vector<uint8_t>(is);
values_L2_ = Vector<uint16_t>(is);
values_L3_ = Vector<uint32_t>(is);
#ifdef XCDAT_X64
values_L4_ = Vector<uint64_t>(is);
#endif
2017-11-12 11:49:13 +00:00
for (size_t i = 0; i < LAYERS - 1; ++i) {
2017-07-12 06:48:49 +00:00
ranks_[i] = Vector<id_type>(is);
}
leaf_flags_ = BitVector(is);
links_ = FitVector(is);
num_free_nodes_ = read_value<size_t>(is);
}
2017-11-11 12:01:10 +00:00
FastDacBc::FastDacBc(const std::vector<BcPair>& bc,
BitVectorBuilder& leaf_flags) {
2016-12-03 07:51:00 +00:00
if (bc.empty()) {
return;
}
2017-03-29 06:01:06 +00:00
std::vector<uint8_t> values_L1;
std::vector<uint16_t> values_L2;
std::vector<uint32_t> values_L3;
2017-07-12 06:48:49 +00:00
#ifdef XCDAT_X64
2017-03-29 06:01:06 +00:00
std::vector<uint64_t> values_L4;
#endif
2017-11-12 11:49:13 +00:00
std::vector<id_type> ranks[LAYERS - 1];
2017-03-29 06:01:06 +00:00
std::vector<id_type> links;
2017-07-12 06:48:49 +00:00
leaf_flags_ = BitVector(leaf_flags, true, false);
2016-12-03 07:51:00 +00:00
2017-03-29 06:01:06 +00:00
ranks[0].reserve((bc.size() * 2) / 128);
2016-12-03 07:51:00 +00:00
2017-03-29 06:01:06 +00:00
auto append = [&](id_type value) {
2017-11-12 11:49:13 +00:00
if ((values_L1.size() % BLOCK_SIZE_L1) == 0) {
2017-03-29 06:01:06 +00:00
ranks[0].push_back(static_cast<id_type>(values_L2.size()));
}
2017-11-12 11:49:13 +00:00
if ((value / BLOCK_SIZE_L1) == 0) {
2017-03-29 06:01:06 +00:00
values_L1.push_back(static_cast<uint8_t>(0 | (value << 1)));
2016-12-03 07:51:00 +00:00
return;
2017-03-29 06:01:06 +00:00
} else {
auto pos = values_L2.size() - ranks[0].back();
values_L1.push_back(static_cast<uint8_t>(1 | (pos << 1)));
2016-12-03 07:51:00 +00:00
}
2017-11-12 11:49:13 +00:00
if ((values_L2.size() % BLOCK_SIZE_L2) == 0) {
2017-03-29 06:01:06 +00:00
ranks[1].push_back(static_cast<id_type>(values_L3.size()));
}
2017-11-12 11:49:13 +00:00
if ((value / BLOCK_SIZE_L2) == 0) {
2017-03-29 06:01:06 +00:00
values_L2.push_back(static_cast<uint16_t>(0 | (value << 1)));
2016-12-03 07:51:00 +00:00
return;
} else {
2017-03-29 06:01:06 +00:00
auto pos = values_L3.size() - ranks[1].back();
values_L2.push_back(static_cast<uint16_t>(1 | (pos << 1)));
2016-12-03 07:51:00 +00:00
}
2017-07-12 06:48:49 +00:00
#ifdef XCDAT_X64
2017-11-12 11:49:13 +00:00
if ((values_L3.size() % BLOCK_SIZE_L3) == 0) {
2017-03-29 06:01:06 +00:00
ranks[1].push_back(static_cast<id_type>(values_L4.size()));
2016-12-03 07:51:00 +00:00
}
2017-11-12 11:49:13 +00:00
if ((value / BLOCK_SIZE_L3) == 0) {
2017-03-29 06:01:06 +00:00
values_L3.push_back(static_cast<uint32_t>(0 | (value << 1)));
2016-12-03 07:51:00 +00:00
return;
} else {
2017-03-29 06:01:06 +00:00
auto pos = values_L4.size() - ranks[1].back();
values_L3.push_back(static_cast<uint32_t>(1 | (pos << 1)));
2016-12-03 07:51:00 +00:00
}
2017-03-29 06:01:06 +00:00
values_L4.push_back(value);
#else
values_L3.push_back(value);
#endif
};
2016-12-03 07:51:00 +00:00
2017-03-29 06:01:06 +00:00
auto append_leaf = [&](id_type value) {
2017-11-12 11:49:13 +00:00
if ((values_L1.size() % BLOCK_SIZE_L1) == 0) {
2017-03-29 06:01:06 +00:00
ranks[0].push_back(static_cast<id_type>(values_L2.size()));
}
values_L1.push_back(static_cast<uint8_t>(value & 0xFF));
links.push_back(value >> 8);
2016-12-03 07:51:00 +00:00
};
2017-03-29 06:01:06 +00:00
for (id_type i = 0; i < bc.size(); ++i) {
if (leaf_flags_[i]) {
append_leaf(bc[i].base);
2016-12-03 07:51:00 +00:00
} else {
2017-03-29 06:01:06 +00:00
append(bc[i].base ^ i);
}
append(bc[i].check ^ i);
if (bc[i].check == i) {
++num_free_nodes_;
2016-12-03 07:51:00 +00:00
}
}
// release
2017-07-12 06:48:49 +00:00
values_L1_ = Vector<uint8_t>(values_L1);
values_L2_ = Vector<uint16_t>(values_L2);
values_L3_ = Vector<uint32_t>(values_L3);
#ifdef XCDAT_X64
values_L4_ = Vector<uint64_t>(values_L4);
2017-03-29 06:01:06 +00:00
#endif
2017-11-12 11:49:13 +00:00
for (uint8_t j = 0; j < LAYERS - 1; ++j) {
2017-07-12 06:48:49 +00:00
ranks_[j] = Vector<id_type>(ranks[j]);
2017-03-29 06:01:06 +00:00
}
2017-07-12 06:48:49 +00:00
links_ = FitVector(links);
2016-12-03 07:51:00 +00:00
}
size_t FastDacBc::size_in_bytes() const {
size_t ret = 0;
2017-03-29 06:01:06 +00:00
ret += values_L1_.size_in_bytes();
ret += values_L2_.size_in_bytes();
ret += values_L3_.size_in_bytes();
2017-07-12 06:48:49 +00:00
#ifdef XCDAT_X64
2017-03-29 06:01:06 +00:00
ret += values_L4_.size_in_bytes();
#endif
2016-12-03 07:51:00 +00:00
for (auto& ranks : ranks_) {
2017-03-29 06:01:06 +00:00
ret += ranks.size_in_bytes();
2016-12-03 07:51:00 +00:00
}
2017-03-29 06:01:06 +00:00
ret += leaf_flags_.size_in_bytes();
2016-12-03 07:51:00 +00:00
ret += links_.size_in_bytes();
ret += sizeof(num_free_nodes_);
return ret;
}
void FastDacBc::show_stat(std::ostream& os) const {
const auto total_size = size_in_bytes();
os << "basic statistics of xcdat::FastDacBc" << std::endl;
2016-12-04 06:53:02 +00:00
show_size("\tnum links: ", links_.size(), os);
show_size("\tbytes per node:", double(total_size) / num_nodes(), os);
2016-12-03 07:51:00 +00:00
os << "member size statistics of xcdat::FastDacBc" << std::endl;
2017-03-29 06:01:06 +00:00
show_size_ratio("\tvalues_L1:", values_L1_.size_in_bytes(), total_size, os);
show_size_ratio("\tvalues_L2:", values_L2_.size_in_bytes(), total_size, os);
show_size_ratio("\tvalues_L3:", values_L3_.size_in_bytes(), total_size, os);
2017-07-12 06:48:49 +00:00
#ifdef XCDAT_X64
2017-03-29 06:01:06 +00:00
show_size_ratio("\tvalues_L4:", values_L4_.size_in_bytes(), total_size, os);
#endif
show_size_ratio("\tranks_L1: ", ranks_[0].size_in_bytes(), total_size, os);
show_size_ratio("\tranks_L2: ", ranks_[1].size_in_bytes(), total_size, os);
2017-07-12 06:48:49 +00:00
#ifdef XCDAT_X64
2017-03-29 06:01:06 +00:00
show_size_ratio("\tranks_L3: ", ranks_[2].size_in_bytes(), total_size, os);
#endif
show_size_ratio("\tleaves: ", leaf_flags_.size_in_bytes(), total_size, os);
show_size_ratio("\tlinks: ", links_.size_in_bytes(), total_size, os);
2016-12-03 07:51:00 +00:00
}
void FastDacBc::write(std::ostream& os) const {
2017-03-29 06:01:06 +00:00
values_L1_.write(os);
values_L2_.write(os);
values_L3_.write(os);
2017-07-12 06:48:49 +00:00
#ifdef XCDAT_X64
2017-03-29 06:01:06 +00:00
values_L4_.write(os);
#endif
2016-12-03 07:51:00 +00:00
for (auto& ranks : ranks_) {
2017-03-29 06:01:06 +00:00
ranks.write(os);
2016-12-03 07:51:00 +00:00
}
2017-03-29 06:01:06 +00:00
leaf_flags_.write(os);
2016-12-03 07:51:00 +00:00
links_.write(os);
2016-12-04 06:53:02 +00:00
write_value(num_free_nodes_, os);
2016-12-03 07:51:00 +00:00
}
2017-03-29 06:01:06 +00:00
id_type FastDacBc::access_(id_type i) const {
uint32_t value = values_L1_[i] >> 1;
if ((values_L1_[i] & 1U) == 0) {
return value;
}
2017-11-12 11:49:13 +00:00
i = ranks_[0][i / BLOCK_SIZE_L1] + value;
2017-03-29 06:01:06 +00:00
value = values_L2_[i] >> 1;
if ((values_L2_[i] & 1U) == 0) {
2016-12-03 07:51:00 +00:00
return value;
}
2017-11-12 11:49:13 +00:00
i = ranks_[1][i / BLOCK_SIZE_L2] + value;
2017-07-12 06:48:49 +00:00
#ifdef XCDAT_X64
2017-03-29 06:01:06 +00:00
value = values_L3_[i] >> 1;
if ((values_L3_[i] & 1U) == 0) {
2016-12-03 07:51:00 +00:00
return value;
}
2017-11-12 11:49:13 +00:00
i = ranks_[2][i / BLOCK_SIZE_L3] + value;
2017-03-29 06:01:06 +00:00
return values_L4_[i];
#else
return values_L3_[i];
#endif
2016-12-03 07:51:00 +00:00
}
} //namespace - xcdat