Make PackedVector generic
This commit is contained in:
committed by
Patrick Niklaus
parent
e85c4f87e9
commit
a66918a303
@@ -5,6 +5,7 @@
|
||||
#include "extractor/node_based_edge.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "storage/io.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
@@ -59,7 +60,7 @@ NodeID loadNodesFromFile(storage::io::FileReader &file_reader,
|
||||
BarrierOutIter barriers,
|
||||
TrafficSignalsOutIter traffic_signals,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids)
|
||||
extractor::PackedOSMIDs &osm_node_ids)
|
||||
{
|
||||
auto number_of_nodes = file_reader.ReadElementCount64();
|
||||
Log() << "Importing number_of_nodes new = " << number_of_nodes << " nodes ";
|
||||
|
||||
@@ -16,33 +16,28 @@ namespace util
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership> class PackedVector;
|
||||
template <typename T, std::size_t Bits, storage::Ownership Ownership> class PackedVector;
|
||||
}
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Ownership> &vec);
|
||||
template <typename T, std::size_t Bits, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Bits, Ownership> &vec);
|
||||
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer, const detail::PackedVector<T, Ownership> &vec);
|
||||
template <typename T, std::size_t Bits, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::PackedVector<T, Bits, Ownership> &vec);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Since OSM node IDs are (at the time of writing) not quite yet overflowing 32 bits, and
|
||||
* will predictably be containable within 33 bits for a long time, the following packs
|
||||
* 64-bit OSM IDs as 33-bit numbers within a 64-bit vector.
|
||||
*
|
||||
* NOTE: this type is templated for future use, but will require a slight refactor to
|
||||
* configure BITSIZE and ELEMSIZE
|
||||
*/
|
||||
template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
template <typename T, std::size_t Bits, storage::Ownership Ownership> class PackedVector
|
||||
{
|
||||
static const constexpr std::size_t BITSIZE = 33;
|
||||
static const constexpr std::size_t ELEMSIZE = 64;
|
||||
static const constexpr std::size_t PACKSIZE = BITSIZE * ELEMSIZE;
|
||||
static_assert(sizeof(T) <= sizeof(std::uint64_t), "Maximum size of type T is 8 bytes");
|
||||
static_assert(Bits <= sizeof(std::uint64_t)*CHAR_BIT, "Maximum number of bits it 64.");
|
||||
|
||||
static const constexpr std::size_t ELEMSIZE = sizeof(std::uint64_t)*CHAR_BIT;
|
||||
static const constexpr std::size_t PACKSIZE = Bits * ELEMSIZE;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
@@ -54,31 +49,31 @@ template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
*/
|
||||
inline static std::size_t elements_to_blocks(std::size_t elements)
|
||||
{
|
||||
return std::ceil(static_cast<double>(elements) * BITSIZE / ELEMSIZE);
|
||||
return std::ceil(static_cast<double>(elements) * Bits / ELEMSIZE);
|
||||
}
|
||||
|
||||
void push_back(T incoming_node_id)
|
||||
void push_back(T data)
|
||||
{
|
||||
std::uint64_t node_id = static_cast<std::uint64_t>(incoming_node_id);
|
||||
std::uint64_t node_id = static_cast<std::uint64_t>(data);
|
||||
|
||||
// mask incoming values, just in case they are > bitsize
|
||||
const std::uint64_t incoming_mask = static_cast<std::uint64_t>(pow(2, BITSIZE)) - 1;
|
||||
const std::uint64_t incoming_mask = static_cast<std::uint64_t>(pow(2, Bits)) - 1;
|
||||
node_id = node_id & incoming_mask;
|
||||
|
||||
const std::size_t available = (PACKSIZE - BITSIZE * num_elements) % ELEMSIZE;
|
||||
const std::size_t available = (PACKSIZE - Bits * num_elements) % ELEMSIZE;
|
||||
|
||||
if (available == 0)
|
||||
{
|
||||
// insert ID at the left side of this element
|
||||
std::uint64_t at_left = node_id << (ELEMSIZE - BITSIZE);
|
||||
std::uint64_t at_left = node_id << (ELEMSIZE - Bits);
|
||||
|
||||
add_last_elem(at_left);
|
||||
}
|
||||
else if (available >= BITSIZE)
|
||||
else if (available >= Bits)
|
||||
{
|
||||
// insert ID somewhere in the middle of this element; ID can be contained
|
||||
// entirely within one element
|
||||
const std::uint64_t shifted = node_id << (available - BITSIZE);
|
||||
const std::uint64_t shifted = node_id << (available - Bits);
|
||||
|
||||
replace_last_elem(vec_back() | shifted);
|
||||
}
|
||||
@@ -86,9 +81,9 @@ template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
{
|
||||
// ID will be split between the end of this element and the beginning
|
||||
// of the next element
|
||||
const std::uint64_t left = node_id >> (BITSIZE - available);
|
||||
const std::uint64_t left = node_id >> (Bits - available);
|
||||
|
||||
std::uint64_t right = node_id << (ELEMSIZE - (BITSIZE - available));
|
||||
std::uint64_t right = node_id << (ELEMSIZE - (Bits - available));
|
||||
|
||||
replace_last_elem(vec_back() | left);
|
||||
add_last_elem(right);
|
||||
@@ -105,11 +100,11 @@ template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
|
||||
const std::size_t pack_group = trunc(a_index / ELEMSIZE);
|
||||
const std::size_t pack_index = (a_index + ELEMSIZE) % ELEMSIZE;
|
||||
const std::size_t left_index = (PACKSIZE - BITSIZE * pack_index) % ELEMSIZE;
|
||||
const std::size_t left_index = (PACKSIZE - Bits * pack_index) % ELEMSIZE;
|
||||
|
||||
const bool back_half = pack_index >= BITSIZE;
|
||||
const std::size_t index = pack_group * BITSIZE + trunc(pack_index / BITSIZE) +
|
||||
trunc((pack_index - back_half) / 2);
|
||||
const bool back_half = pack_index >= Bits;
|
||||
const std::size_t index =
|
||||
pack_group * Bits + trunc(pack_index / Bits) + trunc((pack_index - back_half) / 2);
|
||||
|
||||
BOOST_ASSERT(index < vec.size());
|
||||
const std::uint64_t elem = static_cast<std::uint64_t>(vec.at(index));
|
||||
@@ -117,25 +112,25 @@ template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
if (left_index == 0)
|
||||
{
|
||||
// ID is at the far left side of this element
|
||||
return T{elem >> (ELEMSIZE - BITSIZE)};
|
||||
return T{elem >> (ELEMSIZE - Bits)};
|
||||
}
|
||||
else if (left_index >= BITSIZE)
|
||||
else if (left_index >= Bits)
|
||||
{
|
||||
// ID is entirely contained within this element
|
||||
const std::uint64_t at_right = elem >> (left_index - BITSIZE);
|
||||
const std::uint64_t left_mask = static_cast<std::uint64_t>(pow(2, BITSIZE)) - 1;
|
||||
const std::uint64_t at_right = elem >> (left_index - Bits);
|
||||
const std::uint64_t left_mask = static_cast<std::uint64_t>(pow(2, Bits)) - 1;
|
||||
return T{at_right & left_mask};
|
||||
}
|
||||
else
|
||||
{
|
||||
// ID is split between this and the next element
|
||||
const std::uint64_t left_mask = static_cast<std::uint64_t>(pow(2, left_index)) - 1;
|
||||
const std::uint64_t left_side = (elem & left_mask) << (BITSIZE - left_index);
|
||||
const std::uint64_t left_side = (elem & left_mask) << (Bits - left_index);
|
||||
|
||||
BOOST_ASSERT(index < vec.size() - 1);
|
||||
const std::uint64_t next_elem = static_cast<std::uint64_t>(vec.at(index + 1));
|
||||
|
||||
const std::uint64_t right_side = next_elem >> (ELEMSIZE - (BITSIZE - left_index));
|
||||
const std::uint64_t right_side = next_elem >> (ELEMSIZE - (Bits - left_index));
|
||||
return T{left_side | right_side};
|
||||
}
|
||||
}
|
||||
@@ -163,14 +158,14 @@ template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
|
||||
std::size_t capacity() const
|
||||
{
|
||||
return std::floor(static_cast<double>(vec.capacity()) * ELEMSIZE / BITSIZE);
|
||||
return std::floor(static_cast<double>(vec.capacity()) * ELEMSIZE / Bits);
|
||||
}
|
||||
|
||||
friend void serialization::read<T, Ownership>(storage::io::FileReader &reader,
|
||||
detail::PackedVector<T, Ownership> &vec);
|
||||
friend void serialization::read<T, Bits, Ownership>(storage::io::FileReader &reader,
|
||||
PackedVector &vec);
|
||||
|
||||
friend void serialization::write<T, Ownership>(storage::io::FileWriter &writer,
|
||||
const detail::PackedVector<T, Ownership> &vec);
|
||||
friend void serialization::write<T, Bits, Ownership>(storage::io::FileWriter &writer,
|
||||
const PackedVector &vec);
|
||||
|
||||
private:
|
||||
util::ViewOrVector<std::uint64_t, Ownership> vec;
|
||||
@@ -218,8 +213,8 @@ template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T> using PackedVector = detail::PackedVector<T, storage::Ownership::Container>;
|
||||
template <typename T> using PackedVectorView = detail::PackedVector<T, storage::Ownership::View>;
|
||||
template <typename T, std::size_t Bits> using PackedVector = detail::PackedVector<T, Bits, storage::Ownership::Container>;
|
||||
template <typename T, std::size_t Bits> using PackedVectorView = detail::PackedVector<T, Bits, storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@ namespace util
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Ownership> &vec)
|
||||
template <typename T, std::size_t Bits, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Bits, Ownership> &vec)
|
||||
{
|
||||
vec.num_elements = reader.ReadOne<std::uint64_t>();
|
||||
storage::serialization::read(reader, vec.vec);
|
||||
}
|
||||
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer, const detail::PackedVector<T, Ownership> &vec)
|
||||
template <typename T, std::size_t Bits, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer, const detail::PackedVector<T, Bits, Ownership> &vec)
|
||||
{
|
||||
writer.WriteOne(vec.num_elements);
|
||||
storage::serialization::write(writer, vec.vec);
|
||||
|
||||
Reference in New Issue
Block a user