206 lines
5.0 KiB
C++
206 lines
5.0 KiB
C++
#ifndef MARISA_GRIMOIRE_VECTOR_FLAT_VECTOR_H_
|
|
#define MARISA_GRIMOIRE_VECTOR_FLAT_VECTOR_H_
|
|
|
|
#include "marisa/grimoire/vector/vector.h"
|
|
|
|
namespace marisa {
|
|
namespace grimoire {
|
|
namespace vector {
|
|
|
|
class FlatVector {
|
|
public:
|
|
#if MARISA_WORD_SIZE == 64
|
|
typedef UInt64 Unit;
|
|
#else // MARISA_WORD_SIZE == 64
|
|
typedef UInt32 Unit;
|
|
#endif // MARISA_WORD_SIZE == 64
|
|
|
|
FlatVector() : units_(), value_size_(0), mask_(0), size_(0) {}
|
|
|
|
void build(const Vector<UInt32> &values) {
|
|
FlatVector temp;
|
|
temp.build_(values);
|
|
swap(temp);
|
|
}
|
|
|
|
void map(Mapper &mapper) {
|
|
FlatVector temp;
|
|
temp.map_(mapper);
|
|
swap(temp);
|
|
}
|
|
void read(Reader &reader) {
|
|
FlatVector temp;
|
|
temp.read_(reader);
|
|
swap(temp);
|
|
}
|
|
void write(Writer &writer) const {
|
|
write_(writer);
|
|
}
|
|
|
|
UInt32 operator[](std::size_t i) const {
|
|
MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
|
|
|
|
const std::size_t pos = i * value_size_;
|
|
const std::size_t unit_id = pos / MARISA_WORD_SIZE;
|
|
const std::size_t unit_offset = pos % MARISA_WORD_SIZE;
|
|
|
|
if ((unit_offset + value_size_) <= MARISA_WORD_SIZE) {
|
|
return (UInt32)(units_[unit_id] >> unit_offset) & mask_;
|
|
} else {
|
|
return (UInt32)((units_[unit_id] >> unit_offset)
|
|
| (units_[unit_id + 1] << (MARISA_WORD_SIZE - unit_offset))) & mask_;
|
|
}
|
|
}
|
|
|
|
std::size_t value_size() const {
|
|
return value_size_;
|
|
}
|
|
UInt32 mask() const {
|
|
return mask_;
|
|
}
|
|
|
|
bool empty() const {
|
|
return size_ == 0;
|
|
}
|
|
std::size_t size() const {
|
|
return size_;
|
|
}
|
|
std::size_t total_size() const {
|
|
return units_.total_size();
|
|
}
|
|
std::size_t io_size() const {
|
|
return units_.io_size() + (sizeof(UInt32) * 2) + sizeof(UInt64);
|
|
}
|
|
|
|
void clear() {
|
|
FlatVector().swap(*this);
|
|
}
|
|
void swap(FlatVector &rhs) {
|
|
units_.swap(rhs.units_);
|
|
marisa::swap(value_size_, rhs.value_size_);
|
|
marisa::swap(mask_, rhs.mask_);
|
|
marisa::swap(size_, rhs.size_);
|
|
}
|
|
|
|
private:
|
|
Vector<Unit> units_;
|
|
std::size_t value_size_;
|
|
UInt32 mask_;
|
|
std::size_t size_;
|
|
|
|
void build_(const Vector<UInt32> &values) {
|
|
UInt32 max_value = 0;
|
|
for (std::size_t i = 0; i < values.size(); ++i) {
|
|
if (values[i] > max_value) {
|
|
max_value = values[i];
|
|
}
|
|
}
|
|
|
|
std::size_t value_size = 0;
|
|
while (max_value != 0) {
|
|
++value_size;
|
|
max_value >>= 1;
|
|
}
|
|
|
|
std::size_t num_units = values.empty() ? 0 : (64 / MARISA_WORD_SIZE);
|
|
if (value_size != 0) {
|
|
num_units = (std::size_t)(
|
|
(((UInt64)value_size * values.size()) + (MARISA_WORD_SIZE - 1))
|
|
/ MARISA_WORD_SIZE);
|
|
num_units += num_units % (64 / MARISA_WORD_SIZE);
|
|
}
|
|
|
|
units_.resize(num_units);
|
|
if (num_units > 0) {
|
|
units_.back() = 0;
|
|
}
|
|
|
|
value_size_ = value_size;
|
|
if (value_size != 0) {
|
|
mask_ = MARISA_UINT32_MAX >> (32 - value_size);
|
|
}
|
|
size_ = values.size();
|
|
|
|
for (std::size_t i = 0; i < values.size(); ++i) {
|
|
set(i, values[i]);
|
|
}
|
|
}
|
|
|
|
void map_(Mapper &mapper) {
|
|
units_.map(mapper);
|
|
{
|
|
UInt32 temp_value_size;
|
|
mapper.map(&temp_value_size);
|
|
MARISA_THROW_IF(temp_value_size > 32, MARISA_FORMAT_ERROR);
|
|
value_size_ = temp_value_size;
|
|
}
|
|
{
|
|
UInt32 temp_mask;
|
|
mapper.map(&temp_mask);
|
|
mask_ = temp_mask;
|
|
}
|
|
{
|
|
UInt64 temp_size;
|
|
mapper.map(&temp_size);
|
|
MARISA_THROW_IF(temp_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
|
|
size_ = (std::size_t)temp_size;
|
|
}
|
|
}
|
|
|
|
void read_(Reader &reader) {
|
|
units_.read(reader);
|
|
{
|
|
UInt32 temp_value_size;
|
|
reader.read(&temp_value_size);
|
|
MARISA_THROW_IF(temp_value_size > 32, MARISA_FORMAT_ERROR);
|
|
value_size_ = temp_value_size;
|
|
}
|
|
{
|
|
UInt32 temp_mask;
|
|
reader.read(&temp_mask);
|
|
mask_ = temp_mask;
|
|
}
|
|
{
|
|
UInt64 temp_size;
|
|
reader.read(&temp_size);
|
|
MARISA_THROW_IF(temp_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
|
|
size_ = (std::size_t)temp_size;
|
|
}
|
|
}
|
|
|
|
void write_(Writer &writer) const {
|
|
units_.write(writer);
|
|
writer.write((UInt32)value_size_);
|
|
writer.write((UInt32)mask_);
|
|
writer.write((UInt64)size_);
|
|
}
|
|
|
|
void set(std::size_t i, UInt32 value) {
|
|
MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
|
|
MARISA_DEBUG_IF(value > mask_, MARISA_RANGE_ERROR);
|
|
|
|
const std::size_t pos = i * value_size_;
|
|
const std::size_t unit_id = pos / MARISA_WORD_SIZE;
|
|
const std::size_t unit_offset = pos % MARISA_WORD_SIZE;
|
|
|
|
units_[unit_id] &= ~((Unit)mask_ << unit_offset);
|
|
units_[unit_id] |= (Unit)(value & mask_) << unit_offset;
|
|
if ((unit_offset + value_size_) > MARISA_WORD_SIZE) {
|
|
units_[unit_id + 1] &=
|
|
~((Unit)mask_ >> (MARISA_WORD_SIZE - unit_offset));
|
|
units_[unit_id + 1] |=
|
|
(Unit)(value & mask_) >> (MARISA_WORD_SIZE - unit_offset);
|
|
}
|
|
}
|
|
|
|
// Disallows copy and assignment.
|
|
FlatVector(const FlatVector &);
|
|
FlatVector &operator=(const FlatVector &);
|
|
};
|
|
|
|
} // namespace vector
|
|
} // namespace grimoire
|
|
} // namespace marisa
|
|
|
|
#endif // MARISA_GRIMOIRE_VECTOR_FLAT_VECTOR_H_
|