* speed up hop-to-hop calculations
* better and faster trip clustering: trip tries * add --write-colors to extract line colors from OSM data * refactor config parameter names, update default pfaedle.cfg * add --stats for writing a stats.json file * add --no-fast-hops, --no-a-star, --no-trie for debugging * general refactoring
This commit is contained in:
parent
f1822868c5
commit
4c29892658
126 changed files with 14576 additions and 12196 deletions
226
src/util/graph/radix_heap.h
Normal file
226
src/util/graph/radix_heap.h
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
// based on https://github.com/iwiwi/radix-heap
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace radix_heap {
|
||||
namespace internal {
|
||||
template <bool Is64bit>
|
||||
class find_bucket_impl;
|
||||
|
||||
template <>
|
||||
class find_bucket_impl<false> {
|
||||
public:
|
||||
static inline constexpr size_t find_bucket(uint32_t x, uint32_t last) {
|
||||
return x == last ? 0 : 32 - __builtin_clz(x ^ last);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class find_bucket_impl<true> {
|
||||
public:
|
||||
static inline constexpr size_t find_bucket(uint64_t x, uint64_t last) {
|
||||
return x == last ? 0 : 64 - __builtin_clzll(x ^ last);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr size_t find_bucket(T x, T last) {
|
||||
return find_bucket_impl<sizeof(T) == 8>::find_bucket(x, last);
|
||||
}
|
||||
|
||||
template <typename KeyType, bool IsSigned>
|
||||
class encoder_impl_integer;
|
||||
|
||||
template <typename KeyType>
|
||||
class encoder_impl_integer<KeyType, false> {
|
||||
public:
|
||||
typedef KeyType key_type;
|
||||
typedef KeyType unsigned_key_type;
|
||||
|
||||
inline static constexpr unsigned_key_type encode(key_type x) { return x; }
|
||||
|
||||
inline static constexpr key_type decode(unsigned_key_type x) { return x; }
|
||||
};
|
||||
|
||||
template <typename KeyType>
|
||||
class encoder_impl_integer<KeyType, true> {
|
||||
public:
|
||||
typedef KeyType key_type;
|
||||
typedef typename std::make_unsigned<KeyType>::type unsigned_key_type;
|
||||
|
||||
inline static constexpr unsigned_key_type encode(key_type x) {
|
||||
return static_cast<unsigned_key_type>(x) ^
|
||||
(unsigned_key_type(1) << unsigned_key_type(
|
||||
std::numeric_limits<unsigned_key_type>::digits - 1));
|
||||
}
|
||||
|
||||
inline static constexpr key_type decode(unsigned_key_type x) {
|
||||
return static_cast<key_type>(
|
||||
x ^ (unsigned_key_type(1)
|
||||
<< (std::numeric_limits<unsigned_key_type>::digits - 1)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename KeyType, typename UnsignedKeyType>
|
||||
class encoder_impl_decimal {
|
||||
public:
|
||||
typedef KeyType key_type;
|
||||
typedef UnsignedKeyType unsigned_key_type;
|
||||
|
||||
inline static constexpr unsigned_key_type encode(key_type x) {
|
||||
return raw_cast<key_type, unsigned_key_type>(x) ^
|
||||
((-(raw_cast<key_type, unsigned_key_type>(x) >>
|
||||
(std::numeric_limits<unsigned_key_type>::digits - 1))) |
|
||||
(unsigned_key_type(1)
|
||||
<< (std::numeric_limits<unsigned_key_type>::digits - 1)));
|
||||
}
|
||||
|
||||
inline static constexpr key_type decode(unsigned_key_type x) {
|
||||
return raw_cast<unsigned_key_type, key_type>(
|
||||
x ^ (((x >> (std::numeric_limits<unsigned_key_type>::digits - 1)) - 1) |
|
||||
(unsigned_key_type(1)
|
||||
<< (std::numeric_limits<unsigned_key_type>::digits - 1))));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T, typename U>
|
||||
union raw_cast {
|
||||
public:
|
||||
constexpr raw_cast(T t) : t_(t) {}
|
||||
operator U() const { return u_; }
|
||||
|
||||
private:
|
||||
T t_;
|
||||
U u_;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename KeyType>
|
||||
class encoder
|
||||
: public encoder_impl_integer<KeyType, std::is_signed<KeyType>::value> {};
|
||||
template <>
|
||||
class encoder<float> : public encoder_impl_decimal<float, uint32_t> {};
|
||||
template <>
|
||||
class encoder<double> : public encoder_impl_decimal<double, uint64_t> {};
|
||||
} // namespace internal
|
||||
|
||||
template <typename KeyType, typename ValueType,
|
||||
typename EncoderType = internal::encoder<KeyType>>
|
||||
class pair_radix_heap {
|
||||
public:
|
||||
typedef KeyType key_type;
|
||||
typedef ValueType value_type;
|
||||
typedef EncoderType encoder_type;
|
||||
typedef typename encoder_type::unsigned_key_type unsigned_key_type;
|
||||
|
||||
pair_radix_heap() : size_(0), last_(), buckets_() {
|
||||
buckets_min_.fill(std::numeric_limits<unsigned_key_type>::max());
|
||||
}
|
||||
|
||||
void push(key_type key, const value_type &value) {
|
||||
unsigned_key_type x = encoder_type::encode(key);
|
||||
if (last_ > x) {
|
||||
std::cerr << "Not monotone: " << last_ << " vs " << x << std::endl;
|
||||
x = last_;
|
||||
}
|
||||
++size_;
|
||||
const size_t k = internal::find_bucket(x, last_);
|
||||
buckets_[k].emplace_back(x, value);
|
||||
buckets_min_[k] = std::min(buckets_min_[k], x);
|
||||
}
|
||||
|
||||
void push(key_type key, value_type &&value) {
|
||||
unsigned_key_type x = encoder_type::encode(key);
|
||||
if (last_ > x) {
|
||||
std::cerr << "Not monotone: " << last_ << " vs " << x << std::endl;
|
||||
x = last_;
|
||||
}
|
||||
++size_;
|
||||
const size_t k = internal::find_bucket(x, last_);
|
||||
buckets_[k].emplace_back(x, std::move(value));
|
||||
buckets_min_[k] = std::min(buckets_min_[k], x);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void emplace(key_type key, Args &&... args) {
|
||||
unsigned_key_type x = encoder_type::encode(key);
|
||||
if (last_ > x) x = last_;
|
||||
++size_;
|
||||
const size_t k = internal::find_bucket(x, last_);
|
||||
buckets_[k].emplace_back(std::piecewise_construct, std::forward_as_tuple(x),
|
||||
std::forward_as_tuple(args...));
|
||||
buckets_min_[k] = std::min(buckets_min_[k], x);
|
||||
}
|
||||
|
||||
key_type topKey() {
|
||||
pull();
|
||||
return encoder_type::decode(last_);
|
||||
}
|
||||
|
||||
value_type &topVal() {
|
||||
pull();
|
||||
return buckets_[0].back().second;
|
||||
}
|
||||
|
||||
void pop() {
|
||||
pull();
|
||||
buckets_[0].pop_back();
|
||||
--size_;
|
||||
}
|
||||
|
||||
size_t size() const { return size_; }
|
||||
|
||||
bool empty() const { return size_ == 0; }
|
||||
|
||||
void clear() {
|
||||
size_ = 0;
|
||||
last_ = key_type();
|
||||
for (auto &b : buckets_) b.clear();
|
||||
buckets_min_.fill(std::numeric_limits<unsigned_key_type>::max());
|
||||
}
|
||||
|
||||
void swap(pair_radix_heap<KeyType, ValueType, EncoderType> &a) {
|
||||
std::swap(size_, a.size_);
|
||||
std::swap(last_, a.last_);
|
||||
buckets_.swap(a.buckets_);
|
||||
buckets_min_.swap(a.buckets_min_);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
unsigned_key_type last_;
|
||||
std::array<std::vector<std::pair<unsigned_key_type, value_type>>,
|
||||
std::numeric_limits<unsigned_key_type>::digits + 1>
|
||||
buckets_;
|
||||
std::array<unsigned_key_type,
|
||||
std::numeric_limits<unsigned_key_type>::digits + 1>
|
||||
buckets_min_;
|
||||
|
||||
void pull() {
|
||||
assert(size_ > 0);
|
||||
if (!buckets_[0].empty()) return;
|
||||
|
||||
size_t i;
|
||||
for (i = 1; buckets_[i].empty(); ++i)
|
||||
;
|
||||
last_ = buckets_min_[i];
|
||||
|
||||
for (size_t j = 0; j < buckets_[i].size(); ++j) {
|
||||
const unsigned_key_type x = buckets_[i][j].first;
|
||||
const size_t k = internal::find_bucket(x, last_);
|
||||
buckets_[k].emplace_back(std::move(buckets_[i][j]));
|
||||
buckets_min_[k] = std::min(buckets_min_[k], x);
|
||||
}
|
||||
buckets_[i].clear();
|
||||
buckets_min_[i] = std::numeric_limits<unsigned_key_type>::max();
|
||||
}
|
||||
};
|
||||
} // namespace radix_heap
|
||||
Loading…
Add table
Add a link
Reference in a new issue