mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-23 22:53:43 +00:00
[core] Replace SmallMap
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
This commit is contained in:
committed by
Konstantin Pastbin
parent
969e1ef2da
commit
882dccb87d
@@ -421,9 +421,7 @@ public:
|
|||||||
auto const s = m_avgSpeeds[ind][type].m_speed;
|
auto const s = m_avgSpeeds[ind][type].m_speed;
|
||||||
if (s > 0)
|
if (s > 0)
|
||||||
return s;
|
return s;
|
||||||
auto const * p = kHighwayBasedSpeeds.Find(type);
|
return kHighwayBasedSpeeds.at(type).GetSpeed(inCity).m_weight;
|
||||||
CHECK(p, ());
|
|
||||||
return p->GetSpeed(inCity).m_weight;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// These speeds: Primary, Secondary, Tertiary, Residential have the biggest routing quality impact.
|
// These speeds: Primary, Secondary, Tertiary, Residential have the biggest routing quality impact.
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ set(SRC
|
|||||||
set_operations.hpp
|
set_operations.hpp
|
||||||
shared_buffer_manager.cpp
|
shared_buffer_manager.cpp
|
||||||
shared_buffer_manager.hpp
|
shared_buffer_manager.hpp
|
||||||
small_map.hpp
|
|
||||||
small_set.hpp
|
|
||||||
src_point.cpp
|
src_point.cpp
|
||||||
src_point.hpp
|
src_point.hpp
|
||||||
stats.hpp
|
stats.hpp
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ set(SRC
|
|||||||
regexp_test.cpp
|
regexp_test.cpp
|
||||||
rolling_hash_test.cpp
|
rolling_hash_test.cpp
|
||||||
scope_guard_test.cpp
|
scope_guard_test.cpp
|
||||||
small_set_test.cpp
|
|
||||||
stl_helpers_tests.cpp
|
stl_helpers_tests.cpp
|
||||||
string_utils_test.cpp
|
string_utils_test.cpp
|
||||||
suffix_array_tests.cpp
|
suffix_array_tests.cpp
|
||||||
|
|||||||
@@ -1,270 +0,0 @@
|
|||||||
#include "testing/testing.hpp"
|
|
||||||
|
|
||||||
#include "base/small_map.hpp"
|
|
||||||
#include "base/small_set.hpp"
|
|
||||||
#include "base/timer.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <random>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "3party/ankerl/unordered_dense.h"
|
|
||||||
|
|
||||||
namespace small_set_test
|
|
||||||
{
|
|
||||||
using namespace base;
|
|
||||||
|
|
||||||
UNIT_TEST(SmallSet_Smoke)
|
|
||||||
{
|
|
||||||
SmallSet<300> set;
|
|
||||||
TEST_EQUAL(set.Size(), 0, ());
|
|
||||||
for (uint64_t i = 0; i < 300; ++i)
|
|
||||||
TEST(!set.Contains(i), ());
|
|
||||||
|
|
||||||
set.Insert(0);
|
|
||||||
TEST_EQUAL(set.Size(), 1, ());
|
|
||||||
TEST(set.Contains(0), ());
|
|
||||||
|
|
||||||
set.Insert(0);
|
|
||||||
TEST_EQUAL(set.Size(), 1, ());
|
|
||||||
TEST(set.Contains(0), ());
|
|
||||||
|
|
||||||
set.Insert(5);
|
|
||||||
TEST_EQUAL(set.Size(), 2, ());
|
|
||||||
TEST(set.Contains(0), ());
|
|
||||||
TEST(set.Contains(5), ());
|
|
||||||
|
|
||||||
set.Insert(64);
|
|
||||||
TEST_EQUAL(set.Size(), 3, ());
|
|
||||||
TEST(set.Contains(0), ());
|
|
||||||
TEST(set.Contains(5), ());
|
|
||||||
TEST(set.Contains(64), ());
|
|
||||||
|
|
||||||
{
|
|
||||||
auto cur = set.begin();
|
|
||||||
auto end = set.end();
|
|
||||||
for (uint64_t i : {0, 5, 64})
|
|
||||||
{
|
|
||||||
TEST(cur != end, ());
|
|
||||||
TEST_EQUAL(*cur, i, ());
|
|
||||||
++cur;
|
|
||||||
}
|
|
||||||
TEST(cur == end, ());
|
|
||||||
}
|
|
||||||
|
|
||||||
set.Remove(5);
|
|
||||||
TEST_EQUAL(set.Size(), 2, ());
|
|
||||||
TEST(set.Contains(0), ());
|
|
||||||
TEST(!set.Contains(5), ());
|
|
||||||
TEST(set.Contains(64), ());
|
|
||||||
|
|
||||||
set.Insert(297);
|
|
||||||
set.Insert(298);
|
|
||||||
set.Insert(299);
|
|
||||||
TEST_EQUAL(set.Size(), 5, ());
|
|
||||||
|
|
||||||
{
|
|
||||||
std::vector<uint64_t> const actual(set.begin(), set.end());
|
|
||||||
std::vector<uint64_t> const expected = {0, 64, 297, 298, 299};
|
|
||||||
TEST_EQUAL(actual, expected, ());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_EQUAL(set.Size(), std::distance(set.begin(), set.end()), ());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BenchmarkTimeLessOrNear(uint64_t l, uint64_t r, double relativeTolerance)
|
|
||||||
{
|
|
||||||
return (l < r) || ((l - r) / static_cast<double>(l) < relativeTolerance);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
std::vector<uint32_t> GenerateIndices(uint32_t min, uint32_t max)
|
|
||||||
{
|
|
||||||
std::vector<uint32_t> res;
|
|
||||||
|
|
||||||
std::uniform_int_distribution<uint64_t> randDist(min, max);
|
|
||||||
std::random_device randDevice;
|
|
||||||
std::mt19937 randEngine(randDevice());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 10000000; ++i)
|
|
||||||
res.push_back(randDist(randEngine));
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIT_TEST(SmallMap_Benchmark1)
|
|
||||||
{
|
|
||||||
// 1. Init maps.
|
|
||||||
// Dataset is similar to routing::VehicleModel.
|
|
||||||
ankerl::unordered_dense::map<uint32_t, bool> uMap = {
|
|
||||||
{1, true}, {2, false}, {4, false}, {6, true}, {7, true}, {8, true}, {12, false},
|
|
||||||
{15, false}, {26, true}, {30, false}, {36, false}, {43, false}, {54, false}, {57, true},
|
|
||||||
{58, true}, {65, true}, {69, true}, {90, true}, {95, false}, {119, false}, {167, true},
|
|
||||||
{176, false}, {259, true}, {272, false}, {994, true}, {1054, false}};
|
|
||||||
|
|
||||||
base::SmallMap<uint32_t, bool> sMap(uMap.begin(), uMap.end());
|
|
||||||
|
|
||||||
// 2. Generate indices.
|
|
||||||
std::vector<uint32_t> indices = GenerateIndices(1, 1054);
|
|
||||||
|
|
||||||
uint64_t t1, t2;
|
|
||||||
uint32_t sum1 = 0, sum2 = 0;
|
|
||||||
|
|
||||||
// 3. Run unordered_map.
|
|
||||||
{
|
|
||||||
base::HighResTimer timer;
|
|
||||||
for (auto i : indices)
|
|
||||||
sum1 += (uMap.find(i) != uMap.end() ? 1 : 0);
|
|
||||||
t1 = timer.ElapsedMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Run SmallMap.
|
|
||||||
{
|
|
||||||
base::HighResTimer timer;
|
|
||||||
for (auto i : indices)
|
|
||||||
sum2 += (sMap.Find(i) ? 1 : 0);
|
|
||||||
t2 = timer.ElapsedMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_EQUAL(sum1, sum2, ());
|
|
||||||
// At this moment, we have rare t2 > t1 on Linux CI.
|
|
||||||
TEST(BenchmarkTimeLessOrNear(t2, t1, 0.3), (t2, t1));
|
|
||||||
LOG(LINFO, ("unordered_map time =", t1, "SmallMap time =", t2));
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIT_TEST(SmallMap_Benchmark2)
|
|
||||||
{
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
uint32_t i = 0;
|
|
||||||
// Dataset is similar to routing::VehicleModelFactory.
|
|
||||||
ankerl::unordered_dense::map<string, shared_ptr<int>> uMap = {
|
|
||||||
{"", make_shared<int>(i++)},
|
|
||||||
{"Australia", make_shared<int>(i++)},
|
|
||||||
{"Austria", make_shared<int>(i++)},
|
|
||||||
{"Belarus", make_shared<int>(i++)},
|
|
||||||
{"Belgium", make_shared<int>(i++)},
|
|
||||||
{"Brazil", make_shared<int>(i++)},
|
|
||||||
{"Denmark", make_shared<int>(i++)},
|
|
||||||
{"France", make_shared<int>(i++)},
|
|
||||||
{"Finland", make_shared<int>(i++)},
|
|
||||||
{"Germany", make_shared<int>(i++)},
|
|
||||||
{"Hungary", make_shared<int>(i++)},
|
|
||||||
{"Iceland", make_shared<int>(i++)},
|
|
||||||
{"Netherlands", make_shared<int>(i++)},
|
|
||||||
{"Norway", make_shared<int>(i++)},
|
|
||||||
{"Oman", make_shared<int>(i++)},
|
|
||||||
{"Poland", make_shared<int>(i++)},
|
|
||||||
{"Romania", make_shared<int>(i++)},
|
|
||||||
{"Russian Federation", make_shared<int>(i++)},
|
|
||||||
{"Slovakia", make_shared<int>(i++)},
|
|
||||||
{"Spain", make_shared<int>(i++)},
|
|
||||||
{"Switzerland", make_shared<int>(i++)},
|
|
||||||
{"Turkey", make_shared<int>(i++)},
|
|
||||||
{"Ukraine", make_shared<int>(i++)},
|
|
||||||
{"United Kingdom", make_shared<int>(i++)},
|
|
||||||
{"United States of America", make_shared<int>(i++)},
|
|
||||||
};
|
|
||||||
|
|
||||||
base::SmallMap<std::string, std::shared_ptr<int>> sMap(uMap.begin(), uMap.end());
|
|
||||||
|
|
||||||
// 2. Generate indices.
|
|
||||||
std::vector<std::string> keys;
|
|
||||||
for (auto const & e : uMap)
|
|
||||||
{
|
|
||||||
keys.push_back(e.first);
|
|
||||||
keys.push_back(e.first + "_Foo");
|
|
||||||
keys.push_back(e.first + "_Bar");
|
|
||||||
keys.push_back(e.first + "_Bazz");
|
|
||||||
}
|
|
||||||
std::vector<uint32_t> indices = GenerateIndices(0, keys.size() - 1);
|
|
||||||
|
|
||||||
uint64_t t1, t2;
|
|
||||||
uint32_t sum1 = 0, sum2 = 0;
|
|
||||||
|
|
||||||
// 3. Run unordered_map.
|
|
||||||
{
|
|
||||||
base::HighResTimer timer;
|
|
||||||
for (auto i : indices)
|
|
||||||
{
|
|
||||||
auto const it = uMap.find(keys[i]);
|
|
||||||
if (it != uMap.end())
|
|
||||||
sum1 += *it->second;
|
|
||||||
}
|
|
||||||
t1 = timer.ElapsedMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Run SmallMap.
|
|
||||||
{
|
|
||||||
base::HighResTimer timer;
|
|
||||||
for (auto i : indices)
|
|
||||||
{
|
|
||||||
auto const * p = sMap.Find(keys[i]);
|
|
||||||
if (p)
|
|
||||||
sum2 += **p;
|
|
||||||
}
|
|
||||||
t2 = timer.ElapsedMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_EQUAL(sum1, sum2, ());
|
|
||||||
// std::hash(std::string) is better than std::less(std::string)
|
|
||||||
TEST_LESS(t1, t2, ());
|
|
||||||
LOG(LINFO, ("unordered_map time =", t1, "SmallMap time =", t2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Small 4 elements sample doesn't work for new (gcc11+, clang14+) toolchain.
|
|
||||||
/*
|
|
||||||
UNIT_TEST(SmallMap_Benchmark3)
|
|
||||||
{
|
|
||||||
// Dataset is similar to routing::VehicleModel.m_surfaceFactors.
|
|
||||||
ankerl::unordered_dense::map<int, int> uMap = {
|
|
||||||
{1, 0}, {10, 1}, {100, 2}, {1000, 3},
|
|
||||||
};
|
|
||||||
|
|
||||||
base::SmallMap<int, int> sMap(uMap.begin(), uMap.end());
|
|
||||||
base::SmallMapBase<int, int> sbMap(uMap.begin(), uMap.end());
|
|
||||||
|
|
||||||
std::vector<uint32_t> indices = GenerateIndices(0, 3);
|
|
||||||
// Missing key queries are even worse for the std map.
|
|
||||||
std::vector<int> keys;
|
|
||||||
for (auto const & e : uMap)
|
|
||||||
keys.push_back(e.first);
|
|
||||||
|
|
||||||
uint64_t t1, t2, t3;
|
|
||||||
uint32_t sum1 = 0, sum2 = 0, sum3 = 0;
|
|
||||||
|
|
||||||
// 3. Run unordered_map.
|
|
||||||
{
|
|
||||||
base::HighResTimer timer;
|
|
||||||
for (auto i : indices)
|
|
||||||
sum1 += uMap.find(keys[i])->second;
|
|
||||||
t1 = timer.ElapsedMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Run SmallMap.
|
|
||||||
{
|
|
||||||
base::HighResTimer timer;
|
|
||||||
for (auto i : indices)
|
|
||||||
sum2 += *sMap.Find(keys[i]);
|
|
||||||
t2 = timer.ElapsedMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Run SmallMapBase.
|
|
||||||
{
|
|
||||||
base::HighResTimer timer;
|
|
||||||
for (auto i : indices)
|
|
||||||
sum3 += *sbMap.Find(keys[i]);
|
|
||||||
t3 = timer.ElapsedMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_EQUAL(sum1, sum2, ());
|
|
||||||
TEST_EQUAL(sum1, sum3, ());
|
|
||||||
TEST_LESS(t2, t1, ());
|
|
||||||
TEST(BenchmarkTimeLessOrNear(t3, t2, 0.05), (t3, t2));
|
|
||||||
LOG(LINFO, ("unordered_map time =", t1, "SmallMap time =", t2, "SmallMapBase time =", t3));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace small_set_test
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "assert.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace base
|
|
||||||
{
|
|
||||||
|
|
||||||
/// Consider using as a replacement of unordered_map (map) when:
|
|
||||||
/// - very small amount of elements (<8)
|
|
||||||
template <class Key, class Value>
|
|
||||||
class SmallMapBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using ValueType = std::pair<Key, Value>;
|
|
||||||
|
|
||||||
SmallMapBase() = default;
|
|
||||||
SmallMapBase(std::initializer_list<ValueType> init) : m_map(std::move(init)) {}
|
|
||||||
template <class Iter>
|
|
||||||
SmallMapBase(Iter beg, Iter end) : m_map(beg, end)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool operator==(SmallMapBase const & rhs) const { return m_map == rhs.m_map; }
|
|
||||||
|
|
||||||
void Reserve(size_t count) { m_map.reserve(count); }
|
|
||||||
void Insert(Key k, Value v) { m_map.emplace_back(std::move(k), std::move(v)); }
|
|
||||||
|
|
||||||
Value const * Find(Key const & k) const
|
|
||||||
{
|
|
||||||
for (auto const & e : m_map)
|
|
||||||
if (e.first == k)
|
|
||||||
return &e.second;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const { return m_map.size(); }
|
|
||||||
auto begin() const { return m_map.begin(); }
|
|
||||||
auto end() const { return m_map.end(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/// @todo buffer_vector is not suitable now, because Key/Value is not default constructible.
|
|
||||||
std::vector<ValueType> m_map;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Consider using as a replacement of unordered_map (map) when:
|
|
||||||
/// - initialize and don't modify
|
|
||||||
/// - relatively small amount of elements (8-128)
|
|
||||||
template <class Key, class Value>
|
|
||||||
class SmallMap : public SmallMapBase<Key, Value>
|
|
||||||
{
|
|
||||||
using BaseT = SmallMapBase<Key, Value>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using ValueType = typename BaseT::ValueType;
|
|
||||||
|
|
||||||
SmallMap() = default;
|
|
||||||
SmallMap(std::initializer_list<ValueType> init) : BaseT(std::move(init)) { FinishBuilding(); }
|
|
||||||
template <class Iter>
|
|
||||||
SmallMap(Iter beg, Iter end) : BaseT(beg, end)
|
|
||||||
{
|
|
||||||
FinishBuilding();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FinishBuilding()
|
|
||||||
{
|
|
||||||
auto & theMap = this->m_map;
|
|
||||||
std::sort(theMap.begin(), theMap.end(), [](ValueType const & l, ValueType const & r) { return l.first < r.first; });
|
|
||||||
}
|
|
||||||
|
|
||||||
Value const * Find(Key const & k) const
|
|
||||||
{
|
|
||||||
auto const & theMap = this->m_map;
|
|
||||||
auto const it = std::lower_bound(theMap.cbegin(), theMap.cend(), k,
|
|
||||||
[](ValueType const & l, Key const & r) { return l.first < r; });
|
|
||||||
|
|
||||||
if (it != theMap.cend() && it->first == k)
|
|
||||||
return &(it->second);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Replace(Key const & k, Value v)
|
|
||||||
{
|
|
||||||
auto & theMap = this->m_map;
|
|
||||||
auto it = std::lower_bound(theMap.begin(), theMap.end(), k,
|
|
||||||
[](ValueType const & l, Key const & r) { return l.first < r; });
|
|
||||||
|
|
||||||
ASSERT(it != theMap.end() && it->first == k, ());
|
|
||||||
it->second = std::move(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value const & Get(Key const & k) const
|
|
||||||
{
|
|
||||||
Value const * v = Find(k);
|
|
||||||
ASSERT(v, ());
|
|
||||||
return *v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace base
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "base/assert.hpp"
|
|
||||||
#include "base/bits.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iterator>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace base
|
|
||||||
{
|
|
||||||
// A set of nonnegative integers less than |UpperBound|.
|
|
||||||
//
|
|
||||||
// Requires UpperBound + O(1) bits of memory. All operations except
|
|
||||||
// Clear() and iteration are O(1). Clear() and iteration require
|
|
||||||
// O(UpperBound) steps.
|
|
||||||
//
|
|
||||||
// *NOTE* This class *IS NOT* thread safe.
|
|
||||||
template <uint64_t UpperBound>
|
|
||||||
class SmallSet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static uint64_t constexpr kNumBlocks = (UpperBound + 63) / 64;
|
|
||||||
static_assert(kNumBlocks > 0);
|
|
||||||
|
|
||||||
class Iterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using difference_type = uint64_t;
|
|
||||||
using value_type = uint64_t;
|
|
||||||
using pointer = void;
|
|
||||||
using reference = uint64_t;
|
|
||||||
using iterator_category = std::forward_iterator_tag;
|
|
||||||
|
|
||||||
Iterator(uint64_t const * blocks, uint64_t current_block_index)
|
|
||||||
: m_blocks(blocks)
|
|
||||||
, m_current_block_index(current_block_index)
|
|
||||||
, m_current_block(0)
|
|
||||||
{
|
|
||||||
ASSERT_LESS_OR_EQUAL(current_block_index, kNumBlocks, ());
|
|
||||||
if (current_block_index < kNumBlocks)
|
|
||||||
m_current_block = m_blocks[current_block_index];
|
|
||||||
SkipZeroes();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(Iterator const & rhs) const
|
|
||||||
{
|
|
||||||
return m_blocks == rhs.m_blocks && m_current_block_index == rhs.m_current_block_index &&
|
|
||||||
m_current_block == rhs.m_current_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(Iterator const & rhs) const { return !(*this == rhs); }
|
|
||||||
|
|
||||||
uint64_t operator*() const
|
|
||||||
{
|
|
||||||
ASSERT_NOT_EQUAL(m_current_block, 0, ());
|
|
||||||
auto const bit = m_current_block & -m_current_block;
|
|
||||||
return bits::FloorLog(bit) + m_current_block_index * 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator const & operator++()
|
|
||||||
{
|
|
||||||
ASSERT(m_current_block_index < kNumBlocks, ());
|
|
||||||
ASSERT_NOT_EQUAL(m_current_block, 0, ());
|
|
||||||
m_current_block = m_current_block & (m_current_block - 1);
|
|
||||||
SkipZeroes();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SkipZeroes()
|
|
||||||
{
|
|
||||||
ASSERT_LESS_OR_EQUAL(m_current_block_index, kNumBlocks, ());
|
|
||||||
|
|
||||||
if (m_current_block != 0 || m_current_block_index == kNumBlocks)
|
|
||||||
return;
|
|
||||||
|
|
||||||
do
|
|
||||||
++m_current_block_index;
|
|
||||||
while (m_current_block_index < kNumBlocks && m_blocks[m_current_block_index] == 0);
|
|
||||||
if (m_current_block_index < kNumBlocks)
|
|
||||||
m_current_block = m_blocks[m_current_block_index];
|
|
||||||
else
|
|
||||||
m_current_block = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t const * m_blocks;
|
|
||||||
uint64_t m_current_block_index;
|
|
||||||
uint64_t m_current_block;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEFINE_BLOCK_OFFSET(value) \
|
|
||||||
uint64_t const block = value / 64; \
|
|
||||||
uint64_t const offset = value % 64
|
|
||||||
|
|
||||||
// This invalidates all iterators except end().
|
|
||||||
void Insert(uint64_t value)
|
|
||||||
{
|
|
||||||
ASSERT_LESS(value, UpperBound, ());
|
|
||||||
|
|
||||||
DEFINE_BLOCK_OFFSET(value);
|
|
||||||
auto const bit = kOne << offset;
|
|
||||||
m_size += (m_blocks[block] & bit) == 0;
|
|
||||||
m_blocks[block] |= bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This invalidates all iterators except end().
|
|
||||||
void Remove(uint64_t value)
|
|
||||||
{
|
|
||||||
ASSERT_LESS(value, UpperBound, ());
|
|
||||||
|
|
||||||
DEFINE_BLOCK_OFFSET(value);
|
|
||||||
auto const bit = kOne << offset;
|
|
||||||
m_size -= (m_blocks[block] & bit) != 0;
|
|
||||||
m_blocks[block] &= ~bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Contains(uint64_t value) const
|
|
||||||
{
|
|
||||||
ASSERT_LESS(value, UpperBound, ());
|
|
||||||
|
|
||||||
DEFINE_BLOCK_OFFSET(value);
|
|
||||||
return m_blocks[block] & (kOne << offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef DEFINE_BLOCK_OFFSET
|
|
||||||
|
|
||||||
uint64_t Size() const { return m_size; }
|
|
||||||
|
|
||||||
// This invalidates all iterators except end().
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
std::fill(std::begin(m_blocks), std::end(m_blocks), static_cast<uint64_t>(0));
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator begin() const { return Iterator(m_blocks, 0); }
|
|
||||||
Iterator cbegin() const { return Iterator(m_blocks, 0); }
|
|
||||||
|
|
||||||
Iterator end() const { return Iterator(m_blocks, kNumBlocks); }
|
|
||||||
Iterator cend() const { return Iterator(m_blocks, kNumBlocks); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
static uint64_t constexpr kOne = 1;
|
|
||||||
|
|
||||||
uint64_t m_blocks[kNumBlocks] = {};
|
|
||||||
uint64_t m_size = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// static
|
|
||||||
template <uint64_t UpperBound>
|
|
||||||
uint64_t constexpr SmallSet<UpperBound>::kNumBlocks;
|
|
||||||
|
|
||||||
// static
|
|
||||||
template <uint64_t UpperBound>
|
|
||||||
uint64_t constexpr SmallSet<UpperBound>::kOne;
|
|
||||||
|
|
||||||
template <uint64_t UpperBound>
|
|
||||||
std::string DebugPrint(SmallSet<UpperBound> const & set)
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os << "SmallSet<" << UpperBound << "> [" << set.Size() << ": ";
|
|
||||||
for (auto const & v : set)
|
|
||||||
os << v << " ";
|
|
||||||
os << "]";
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a delegate for SmallSet<>, that checks the validity of
|
|
||||||
// argument in Insert(), Remove() and Contains() methods and does
|
|
||||||
// nothing when the argument is not valid.
|
|
||||||
template <uint64_t UpperBound>
|
|
||||||
class SafeSmallSet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Set = SmallSet<UpperBound>;
|
|
||||||
using Iterator = typename Set::Iterator;
|
|
||||||
|
|
||||||
void Insert(uint64_t value)
|
|
||||||
{
|
|
||||||
if (IsValid(value))
|
|
||||||
m_set.Insert(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Remove(uint64_t value)
|
|
||||||
{
|
|
||||||
if (IsValid(value))
|
|
||||||
m_set.Remove(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Contains(uint64_t value) const { return IsValid(value) && m_set.Contains(value); }
|
|
||||||
|
|
||||||
uint64_t Size() const { return m_set.Size(); }
|
|
||||||
|
|
||||||
void Clear() { m_set.Clear(); }
|
|
||||||
|
|
||||||
Iterator begin() const { return m_set.begin(); }
|
|
||||||
Iterator cbegin() const { return m_set.cbegin(); }
|
|
||||||
|
|
||||||
Iterator end() const { return m_set.end(); }
|
|
||||||
Iterator cend() const { return m_set.cend(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool IsValid(uint64_t value) const { return value < UpperBound; }
|
|
||||||
|
|
||||||
Set m_set;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <uint64_t UpperBound>
|
|
||||||
std::string DebugPrint(SafeSmallSet<UpperBound> const & set)
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os << "SafeSmallSet<" << UpperBound << "> [" << set.Size() << ": ";
|
|
||||||
for (auto const v : set)
|
|
||||||
os << v << " ";
|
|
||||||
os << "]";
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
} // namespace base
|
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
#include "drape/utils/projection.hpp"
|
#include "drape/utils/projection.hpp"
|
||||||
|
|
||||||
#include "base/logging.hpp"
|
#include "base/logging.hpp"
|
||||||
#include "base/small_map.hpp"
|
|
||||||
#include "base/stl_helpers.hpp"
|
#include "base/stl_helpers.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -37,6 +36,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "3party/skarupke/flat_hash_map.hpp"
|
||||||
|
|
||||||
namespace df
|
namespace df
|
||||||
{
|
{
|
||||||
dp::Color ToDrapeColor(uint32_t src)
|
dp::Color ToDrapeColor(uint32_t src)
|
||||||
@@ -271,7 +272,7 @@ dp::Color GetRoadShieldColor(dp::Color const & baseColor, ftypes::RoadShield con
|
|||||||
{
|
{
|
||||||
using ftypes::RoadShieldType;
|
using ftypes::RoadShieldType;
|
||||||
|
|
||||||
static base::SmallMapBase<ftypes::RoadShieldType, df::ColorConstant> kColors = {
|
static ska::flat_hash_map<RoadShieldType, df::ColorConstant> const kColors = {
|
||||||
{RoadShieldType::Generic_White, kRoadShieldWhiteBackgroundColor},
|
{RoadShieldType::Generic_White, kRoadShieldWhiteBackgroundColor},
|
||||||
{RoadShieldType::Generic_Green, kRoadShieldGreenBackgroundColor},
|
{RoadShieldType::Generic_Green, kRoadShieldGreenBackgroundColor},
|
||||||
{RoadShieldType::Generic_Blue, kRoadShieldBlueBackgroundColor},
|
{RoadShieldType::Generic_Blue, kRoadShieldBlueBackgroundColor},
|
||||||
@@ -294,8 +295,9 @@ dp::Color GetRoadShieldColor(dp::Color const & baseColor, ftypes::RoadShield con
|
|||||||
{RoadShieldType::Generic_Pill_Orange_Bordered, kRoadShieldOrangeBackgroundColor},
|
{RoadShieldType::Generic_Pill_Orange_Bordered, kRoadShieldOrangeBackgroundColor},
|
||||||
{RoadShieldType::UK_Highway, kRoadShieldGreenBackgroundColor}};
|
{RoadShieldType::UK_Highway, kRoadShieldGreenBackgroundColor}};
|
||||||
|
|
||||||
if (auto const * cl = kColors.Find(shield.m_type); cl)
|
auto const it = kColors.find(shield.m_type);
|
||||||
return df::GetColorConstant(*cl);
|
if (it != kColors.cend())
|
||||||
|
return df::GetColorConstant(it->second);
|
||||||
|
|
||||||
return baseColor;
|
return baseColor;
|
||||||
}
|
}
|
||||||
@@ -304,7 +306,7 @@ dp::Color GetRoadShieldTextColor(dp::Color const & baseColor, ftypes::RoadShield
|
|||||||
{
|
{
|
||||||
using ftypes::RoadShieldType;
|
using ftypes::RoadShieldType;
|
||||||
|
|
||||||
static base::SmallMapBase<ftypes::RoadShieldType, df::ColorConstant> kColors = {
|
static ska::flat_hash_map<RoadShieldType, df::ColorConstant> const kColors = {
|
||||||
{RoadShieldType::Generic_White, kRoadShieldBlackTextColor},
|
{RoadShieldType::Generic_White, kRoadShieldBlackTextColor},
|
||||||
{RoadShieldType::Generic_Green, kRoadShieldWhiteTextColor},
|
{RoadShieldType::Generic_Green, kRoadShieldWhiteTextColor},
|
||||||
{RoadShieldType::Generic_Blue, kRoadShieldWhiteTextColor},
|
{RoadShieldType::Generic_Blue, kRoadShieldWhiteTextColor},
|
||||||
@@ -336,8 +338,9 @@ dp::Color GetRoadShieldTextColor(dp::Color const & baseColor, ftypes::RoadShield
|
|||||||
{RoadShieldType::Hungary_Green, kRoadShieldWhiteTextColor},
|
{RoadShieldType::Hungary_Green, kRoadShieldWhiteTextColor},
|
||||||
{RoadShieldType::Hungary_Blue, kRoadShieldWhiteTextColor}};
|
{RoadShieldType::Hungary_Blue, kRoadShieldWhiteTextColor}};
|
||||||
|
|
||||||
if (auto const * cl = kColors.Find(shield.m_type); cl)
|
auto const it = kColors.find(shield.m_type);
|
||||||
return df::GetColorConstant(*cl);
|
if (it != kColors.cend())
|
||||||
|
return df::GetColorConstant(it->second);
|
||||||
|
|
||||||
return baseColor;
|
return baseColor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ NewFeatureCategories::NewFeatureCategories(editor::EditorConfig const & config)
|
|||||||
}
|
}
|
||||||
m_types.emplace_back(clType);
|
m_types.emplace_back(clType);
|
||||||
}
|
}
|
||||||
|
m_addedLangs.reserve(CategoriesHolder::kLocaleMapping.size() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewFeatureCategories::NewFeatureCategories(NewFeatureCategories && other) noexcept
|
NewFeatureCategories::NewFeatureCategories(NewFeatureCategories && other) noexcept
|
||||||
@@ -37,14 +38,14 @@ void NewFeatureCategories::AddLanguage(std::string lang)
|
|||||||
lang = "en";
|
lang = "en";
|
||||||
langCode = CategoriesHolder::kEnglishCode;
|
langCode = CategoriesHolder::kEnglishCode;
|
||||||
}
|
}
|
||||||
if (m_addedLangs.Contains(langCode))
|
if (m_addedLangs.contains(langCode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto const & c = classif();
|
auto const & c = classif();
|
||||||
for (auto const & type : m_types)
|
for (auto const & type : m_types)
|
||||||
m_index.AddCategoryByTypeAndLang(c.GetTypeByReadableObjectName(type), langCode);
|
m_index.AddCategoryByTypeAndLang(c.GetTypeByReadableObjectName(type), langCode);
|
||||||
|
|
||||||
m_addedLangs.Insert(langCode);
|
m_addedLangs.insert(langCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewFeatureCategories::TypeNames NewFeatureCategories::Search(std::string const & query) const
|
NewFeatureCategories::TypeNames NewFeatureCategories::Search(std::string const & query) const
|
||||||
|
|||||||
@@ -6,11 +6,12 @@
|
|||||||
#include "indexer/categories_index.hpp"
|
#include "indexer/categories_index.hpp"
|
||||||
|
|
||||||
#include "base/macros.hpp"
|
#include "base/macros.hpp"
|
||||||
#include "base/small_set.hpp"
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "3party/ankerl/unordered_dense.h"
|
||||||
|
|
||||||
namespace osm
|
namespace osm
|
||||||
{
|
{
|
||||||
// This class holds an index of categories that can be set for a newly added feature.
|
// This class holds an index of categories that can be set for a newly added feature.
|
||||||
@@ -43,7 +44,7 @@ public:
|
|||||||
TypeNames const & GetAllCreatableTypeNames() const { return m_types; }
|
TypeNames const & GetAllCreatableTypeNames() const { return m_types; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Langs = base::SmallSet<CategoriesHolder::kLocaleMapping.size() + 1>;
|
using Langs = ankerl::unordered_dense::set<int8_t>;
|
||||||
|
|
||||||
indexer::CategoriesIndex m_index;
|
indexer::CategoriesIndex m_index;
|
||||||
Langs m_addedLangs;
|
Langs m_addedLangs;
|
||||||
|
|||||||
@@ -339,20 +339,21 @@ IsWayChecker::IsWayChecker()
|
|||||||
{"unclassified", Minors},
|
{"unclassified", Minors},
|
||||||
};
|
};
|
||||||
|
|
||||||
m_ranks.Reserve(std::size(types));
|
m_ranks.reserve(std::size(types));
|
||||||
for (auto const & e : types)
|
for (auto const & e : types)
|
||||||
{
|
{
|
||||||
uint32_t const type = c.GetTypeByPath({"highway", e.first});
|
uint32_t const type = c.GetTypeByPath({"highway", e.first});
|
||||||
m_types.push_back(type);
|
m_types.push_back(type);
|
||||||
m_ranks.Insert(type, e.second);
|
m_ranks.insert({type, e.second});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IsWayChecker::SearchRank IsWayChecker::GetSearchRank(uint32_t type) const
|
IsWayChecker::SearchRank IsWayChecker::GetSearchRank(uint32_t type) const
|
||||||
{
|
{
|
||||||
ftype::TruncValue(type, 2);
|
ftype::TruncValue(type, 2);
|
||||||
if (auto const * res = m_ranks.Find(type))
|
auto const it = m_ranks.find(type);
|
||||||
return *res;
|
if (it != m_ranks.cend())
|
||||||
|
return it->second;
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,16 @@
|
|||||||
#include "indexer/feature_data.hpp"
|
#include "indexer/feature_data.hpp"
|
||||||
#include "indexer/feature_utils.hpp"
|
#include "indexer/feature_utils.hpp"
|
||||||
|
|
||||||
#include "base/small_map.hpp"
|
|
||||||
#include "base/stl_helpers.hpp"
|
#include "base/stl_helpers.hpp"
|
||||||
|
|
||||||
|
#include <boost/container_hash/hash.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "3party/skarupke/flat_hash_map.hpp"
|
||||||
|
|
||||||
#define DECLARE_CHECKER_INSTANCE(CheckerType) \
|
#define DECLARE_CHECKER_INSTANCE(CheckerType) \
|
||||||
static CheckerType const & Instance() \
|
static CheckerType const & Instance() \
|
||||||
{ \
|
{ \
|
||||||
@@ -193,7 +196,7 @@ public:
|
|||||||
SearchRank GetSearchRank(uint32_t type) const;
|
SearchRank GetSearchRank(uint32_t type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
base::SmallMap<uint32_t, SearchRank> m_ranks;
|
ska::flat_hash_map<uint32_t, SearchRank, boost::hash<uint32_t>> m_ranks;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IsStreetOrSquareChecker : public BaseChecker
|
class IsStreetOrSquareChecker : public BaseChecker
|
||||||
|
|||||||
@@ -75,19 +75,18 @@ RoutingOptionsClassifier::RoutingOptionsClassifier()
|
|||||||
{{"psurface", "paved_good"}, RoutingOptions::Road::Paved},
|
{{"psurface", "paved_good"}, RoutingOptions::Road::Paved},
|
||||||
{{"psurface", "paved_bad"}, RoutingOptions::Road::Paved}};
|
{{"psurface", "paved_bad"}, RoutingOptions::Road::Paved}};
|
||||||
|
|
||||||
m_data.Reserve(std::size(types));
|
m_data.reserve(std::size(types));
|
||||||
for (auto const & data : types)
|
for (auto const & data : types)
|
||||||
m_data.Insert(c.GetTypeByPath(data.first), data.second);
|
m_data.insert({c.GetTypeByPath(data.first), data.second});
|
||||||
m_data.FinishBuilding();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<RoutingOptions::Road> RoutingOptionsClassifier::Get(uint32_t type) const
|
optional<RoutingOptions::Road> RoutingOptionsClassifier::Get(uint32_t type) const
|
||||||
{
|
{
|
||||||
ftype::TruncValue(type, 2); // in case of highway-motorway-bridge
|
ftype::TruncValue(type, 2); // in case of highway-motorway-bridge
|
||||||
|
|
||||||
auto const * res = m_data.Find(type);
|
auto const it = m_data.find(type);
|
||||||
if (res)
|
if (it != m_data.cend())
|
||||||
return *res;
|
return it->second;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/small_map.hpp"
|
#include <boost/container_hash/hash.hpp>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "3party/skarupke/flat_hash_map.hpp"
|
||||||
|
|
||||||
namespace routing
|
namespace routing
|
||||||
{
|
{
|
||||||
class RoutingOptions
|
class RoutingOptions
|
||||||
@@ -51,7 +53,7 @@ public:
|
|||||||
static RoutingOptionsClassifier const & Instance();
|
static RoutingOptionsClassifier const & Instance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
base::SmallMap<uint32_t, RoutingOptions::Road> m_data;
|
ska::flat_hash_map<uint32_t, RoutingOptions::Road, boost::hash<uint32_t>> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
RoutingOptions::Road ChooseMainRoutingOptionRoad(RoutingOptions options, bool isCarRouter);
|
RoutingOptions::Road ChooseMainRoutingOptionRoad(RoutingOptions options, bool isCarRouter);
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ VehicleModel::LimitsInitList NoTrunk()
|
|||||||
HighwayBasedSpeeds NormalPedestrianSpeed()
|
HighwayBasedSpeeds NormalPedestrianSpeed()
|
||||||
{
|
{
|
||||||
HighwayBasedSpeeds res = kDefaultSpeeds;
|
HighwayBasedSpeeds res = kDefaultSpeeds;
|
||||||
res.Replace(HighwayType::HighwayPedestrian, InOutCitySpeedKMpH(kSpeedOnFootwayKMpH));
|
res[HighwayType::HighwayPedestrian] = InOutCitySpeedKMpH(kSpeedOnFootwayKMpH);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,15 +125,15 @@ HighwayBasedSpeeds NormalPedestrianAndFootwaySpeed()
|
|||||||
{
|
{
|
||||||
HighwayBasedSpeeds res = kDefaultSpeeds;
|
HighwayBasedSpeeds res = kDefaultSpeeds;
|
||||||
InOutCitySpeedKMpH const footSpeed(kSpeedOnFootwayKMpH);
|
InOutCitySpeedKMpH const footSpeed(kSpeedOnFootwayKMpH);
|
||||||
res.Replace(HighwayType::HighwayPedestrian, footSpeed);
|
res[HighwayType::HighwayPedestrian] = footSpeed;
|
||||||
res.Replace(HighwayType::HighwayFootway, footSpeed);
|
res[HighwayType::HighwayFootway] = footSpeed;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
HighwayBasedSpeeds DismountPathSpeed()
|
HighwayBasedSpeeds DismountPathSpeed()
|
||||||
{
|
{
|
||||||
HighwayBasedSpeeds res = kDefaultSpeeds;
|
HighwayBasedSpeeds res = kDefaultSpeeds;
|
||||||
res.Replace(HighwayType::HighwayPath, InOutCitySpeedKMpH(kSpeedDismountKMpH));
|
res[HighwayType::HighwayPath] = InOutCitySpeedKMpH(kSpeedDismountKMpH);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,15 +143,15 @@ HighwayBasedSpeeds PreferFootwaysToRoads()
|
|||||||
|
|
||||||
// Decrease secondary/tertiary weight speed (-20% from default).
|
// Decrease secondary/tertiary weight speed (-20% from default).
|
||||||
InOutCitySpeedKMpH roadSpeed = InOutCitySpeedKMpH(SpeedKMpH(11.0, 17.0), SpeedKMpH(16.0, 19.0));
|
InOutCitySpeedKMpH roadSpeed = InOutCitySpeedKMpH(SpeedKMpH(11.0, 17.0), SpeedKMpH(16.0, 19.0));
|
||||||
res.Replace(HighwayType::HighwaySecondary, roadSpeed);
|
res[HighwayType::HighwaySecondary] = roadSpeed;
|
||||||
res.Replace(HighwayType::HighwaySecondaryLink, roadSpeed);
|
res[HighwayType::HighwaySecondaryLink] = roadSpeed;
|
||||||
res.Replace(HighwayType::HighwayTertiary, roadSpeed);
|
res[HighwayType::HighwayTertiary] = roadSpeed;
|
||||||
res.Replace(HighwayType::HighwayTertiaryLink, roadSpeed);
|
res[HighwayType::HighwayTertiaryLink] = roadSpeed;
|
||||||
|
|
||||||
// Increase footway speed to make bigger than other roads (+20% from default roads).
|
// Increase footway speed to make bigger than other roads (+20% from default roads).
|
||||||
InOutCitySpeedKMpH footSpeed = InOutCitySpeedKMpH(SpeedKMpH(17.0, 12.0), SpeedKMpH(20.0, 15.0));
|
InOutCitySpeedKMpH footSpeed = InOutCitySpeedKMpH(SpeedKMpH(17.0, 12.0), SpeedKMpH(20.0, 15.0));
|
||||||
res.Replace(HighwayType::HighwayPedestrian, footSpeed);
|
res[HighwayType::HighwayPedestrian] = footSpeed;
|
||||||
res.Replace(HighwayType::HighwayFootway, footSpeed);
|
res[HighwayType::HighwayFootway] = footSpeed;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -205,7 +205,7 @@ BicycleModel::BicycleModel(VehicleModel::LimitsInitList const & limits, HighwayB
|
|||||||
m_onedirBicycleType = cl.GetTypeByPath({"hwtag", "onedir_bicycle"});
|
m_onedirBicycleType = cl.GetTypeByPath({"hwtag", "onedir_bicycle"});
|
||||||
|
|
||||||
// Assign 90% of max cycleway speed for bicycle=yes to keep choosing most preferred cycleway.
|
// Assign 90% of max cycleway speed for bicycle=yes to keep choosing most preferred cycleway.
|
||||||
auto const yesSpeed = kDefaultSpeeds.Get(HighwayType::HighwayCycleway).m_inCity * 0.9;
|
auto const yesSpeed = kDefaultSpeeds.at(HighwayType::HighwayCycleway).m_inCity * 0.9;
|
||||||
AddAdditionalRoadTypes(cl, {{std::move(hwtagYesBicycle), InOutCitySpeedKMpH(yesSpeed)}});
|
AddAdditionalRoadTypes(cl, {{std::move(hwtagYesBicycle), InOutCitySpeedKMpH(yesSpeed)}});
|
||||||
|
|
||||||
// Update max speed with possible ferry transfer and bicycle speed downhill.
|
// Update max speed with possible ferry transfer and bicycle speed downhill.
|
||||||
@@ -265,40 +265,39 @@ BicycleModelFactory::BicycleModelFactory(CountryParentNameGetterFn const & count
|
|||||||
: VehicleModelFactory(countryParentNameGetterFn)
|
: VehicleModelFactory(countryParentNameGetterFn)
|
||||||
{
|
{
|
||||||
using namespace bicycle_model;
|
using namespace bicycle_model;
|
||||||
using std::make_shared;
|
|
||||||
|
|
||||||
// Names must be the same with country names from countries.txt
|
// Names must be the same with country names from countries.txt
|
||||||
m_models[""] = make_shared<BicycleModel>(kDefaultOptions);
|
m_models[""] = std::make_shared<BicycleModel>(kDefaultOptions);
|
||||||
|
|
||||||
m_models["Australia"] = make_shared<BicycleModel>(AllAllowed(), NormalPedestrianAndFootwaySpeed());
|
m_models["Australia"] = std::make_shared<BicycleModel>(AllAllowed(), NormalPedestrianAndFootwaySpeed());
|
||||||
m_models["Austria"] = make_shared<BicycleModel>(NoTrunk(), DismountPathSpeed());
|
m_models["Austria"] = std::make_shared<BicycleModel>(NoTrunk(), DismountPathSpeed());
|
||||||
// Belarus law demands to use footways for bicycles where possible.
|
// Belarus law demands to use footways for bicycles where possible.
|
||||||
m_models["Belarus"] = make_shared<BicycleModel>(kDefaultOptions, PreferFootwaysToRoads());
|
m_models["Belarus"] = std::make_shared<BicycleModel>(kDefaultOptions, PreferFootwaysToRoads());
|
||||||
m_models["Belgium"] = make_shared<BicycleModel>(NoTrunk(), NormalPedestrianSpeed());
|
m_models["Belgium"] = std::make_shared<BicycleModel>(NoTrunk(), NormalPedestrianSpeed());
|
||||||
m_models["Brazil"] = make_shared<BicycleModel>(AllAllowed());
|
m_models["Brazil"] = std::make_shared<BicycleModel>(AllAllowed());
|
||||||
m_models["Denmark"] = make_shared<BicycleModel>(NoTrunk());
|
m_models["Denmark"] = std::make_shared<BicycleModel>(NoTrunk());
|
||||||
m_models["France"] = make_shared<BicycleModel>(NoTrunk(), NormalPedestrianSpeed());
|
m_models["France"] = std::make_shared<BicycleModel>(NoTrunk(), NormalPedestrianSpeed());
|
||||||
m_models["Finland"] = make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianSpeed());
|
m_models["Finland"] = std::make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianSpeed());
|
||||||
m_models["Hungary"] = make_shared<BicycleModel>(NoTrunk());
|
m_models["Hungary"] = std::make_shared<BicycleModel>(NoTrunk());
|
||||||
m_models["Iceland"] = make_shared<BicycleModel>(AllAllowed(), NormalPedestrianAndFootwaySpeed());
|
m_models["Iceland"] = std::make_shared<BicycleModel>(AllAllowed(), NormalPedestrianAndFootwaySpeed());
|
||||||
m_models["Ireland"] = make_shared<BicycleModel>(AllAllowed());
|
m_models["Ireland"] = std::make_shared<BicycleModel>(AllAllowed());
|
||||||
m_models["Italy"] = make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianSpeed());
|
m_models["Italy"] = std::make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianSpeed());
|
||||||
m_models["Netherlands"] = make_shared<BicycleModel>(NoTrunk());
|
m_models["Netherlands"] = std::make_shared<BicycleModel>(NoTrunk());
|
||||||
m_models["Norway"] = make_shared<BicycleModel>(AllAllowed(), NormalPedestrianAndFootwaySpeed());
|
m_models["Norway"] = std::make_shared<BicycleModel>(AllAllowed(), NormalPedestrianAndFootwaySpeed());
|
||||||
m_models["Oman"] = make_shared<BicycleModel>(AllAllowed());
|
m_models["Oman"] = std::make_shared<BicycleModel>(AllAllowed());
|
||||||
m_models["Philippines"] = make_shared<BicycleModel>(AllAllowed(), NormalPedestrianSpeed());
|
m_models["Philippines"] = std::make_shared<BicycleModel>(AllAllowed(), NormalPedestrianSpeed());
|
||||||
m_models["Poland"] = make_shared<BicycleModel>(NoTrunk());
|
m_models["Poland"] = std::make_shared<BicycleModel>(NoTrunk());
|
||||||
m_models["Romania"] = make_shared<BicycleModel>(AllAllowed());
|
m_models["Romania"] = std::make_shared<BicycleModel>(AllAllowed());
|
||||||
// Note. Despite the fact that according to
|
// Note. Despite the fact that according to
|
||||||
// https://wiki.openstreetmap.org/wiki/OSM_tags_for_routing/Access-Restrictions passing through service and
|
// https://wiki.openstreetmap.org/wiki/OSM_tags_for_routing/Access-Restrictions passing through service and
|
||||||
// living_street with a bicycle is prohibited it's allowed according to Russian traffic rules.
|
// living_street with a bicycle is prohibited it's allowed according to Russian traffic rules.
|
||||||
m_models["Russian Federation"] = make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianAndFootwaySpeed());
|
m_models["Russian Federation"] = std::make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianAndFootwaySpeed());
|
||||||
m_models["Slovakia"] = make_shared<BicycleModel>(NoTrunk());
|
m_models["Slovakia"] = std::make_shared<BicycleModel>(NoTrunk());
|
||||||
m_models["Spain"] = make_shared<BicycleModel>(NoTrunk(), NormalPedestrianSpeed());
|
m_models["Spain"] = std::make_shared<BicycleModel>(NoTrunk(), NormalPedestrianSpeed());
|
||||||
m_models["Sweden"] = make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianSpeed());
|
m_models["Sweden"] = std::make_shared<BicycleModel>(kDefaultOptions, NormalPedestrianSpeed());
|
||||||
m_models["Switzerland"] = make_shared<BicycleModel>(NoTrunk(), NormalPedestrianAndFootwaySpeed());
|
m_models["Switzerland"] = std::make_shared<BicycleModel>(NoTrunk(), NormalPedestrianAndFootwaySpeed());
|
||||||
m_models["Ukraine"] = make_shared<BicycleModel>(UkraineOptions());
|
m_models["Ukraine"] = std::make_shared<BicycleModel>(UkraineOptions());
|
||||||
m_models["United Kingdom"] = make_shared<BicycleModel>(AllAllowed());
|
m_models["United Kingdom"] = std::make_shared<BicycleModel>(AllAllowed());
|
||||||
m_models["United States of America"] = make_shared<BicycleModel>(AllAllowed(), NormalPedestrianSpeed());
|
m_models["United States of America"] = std::make_shared<BicycleModel>(AllAllowed(), NormalPedestrianSpeed());
|
||||||
}
|
}
|
||||||
} // namespace routing
|
} // namespace routing
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ CarModel::CarModel(VehicleModel::LimitsInitList const & roadLimits)
|
|||||||
m_yesType = cl.GetTypeByPath(hwtagYesCar);
|
m_yesType = cl.GetTypeByPath(hwtagYesCar);
|
||||||
|
|
||||||
// Set small track speed if highway is not in kHighwayBasedSpeeds (path, pedestrian), but marked as yescar.
|
// Set small track speed if highway is not in kHighwayBasedSpeeds (path, pedestrian), but marked as yescar.
|
||||||
AddAdditionalRoadTypes(cl, {{std::move(hwtagYesCar), kHighwayBasedSpeeds.Get(HighwayType::HighwayTrack)}});
|
AddAdditionalRoadTypes(cl, {{std::move(hwtagYesCar), kHighwayBasedSpeeds.at(HighwayType::HighwayTrack)}});
|
||||||
|
|
||||||
// Set max possible (reasonable) car speed. See EdgeEstimator::CalcHeuristic.
|
// Set max possible (reasonable) car speed. See EdgeEstimator::CalcHeuristic.
|
||||||
SpeedKMpH constexpr kMaxCarSpeedKMpH(200.0);
|
SpeedKMpH constexpr kMaxCarSpeedKMpH(200.0);
|
||||||
|
|||||||
@@ -125,8 +125,8 @@ HighwayBasedSpeeds IncreasePrimary()
|
|||||||
{
|
{
|
||||||
/// @todo Probably, should make Primary = Secondary = 4.
|
/// @todo Probably, should make Primary = Secondary = 4.
|
||||||
HighwayBasedSpeeds res = pedestrian_model::kDefaultSpeeds;
|
HighwayBasedSpeeds res = pedestrian_model::kDefaultSpeeds;
|
||||||
res.Replace(HighwayType::HighwayPrimary, InOutCitySpeedKMpH(SpeedKMpH(3.0, 5.0)));
|
res[HighwayType::HighwayPrimary] = InOutCitySpeedKMpH(SpeedKMpH(3.0, 5.0));
|
||||||
res.Replace(HighwayType::HighwayPrimaryLink, InOutCitySpeedKMpH(SpeedKMpH(3.0, 5.0)));
|
res[HighwayType::HighwayPrimaryLink] = InOutCitySpeedKMpH(SpeedKMpH(3.0, 5.0));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ PedestrianModel::PedestrianModel(VehicleModel::LimitsInitList const & limits, Hi
|
|||||||
m_noType = cl.GetTypeByPath({"hwtag", "nofoot"});
|
m_noType = cl.GetTypeByPath({"hwtag", "nofoot"});
|
||||||
m_yesType = cl.GetTypeByPath(hwtagYesFoot);
|
m_yesType = cl.GetTypeByPath(hwtagYesFoot);
|
||||||
|
|
||||||
AddAdditionalRoadTypes(cl, {{std::move(hwtagYesFoot), kDefaultSpeeds.Get(HighwayType::HighwayLivingStreet)}});
|
AddAdditionalRoadTypes(cl, {{std::move(hwtagYesFoot), kDefaultSpeeds.at(HighwayType::HighwayLivingStreet)}});
|
||||||
|
|
||||||
// Update max pedestrian speed with possible ferry transfer. See EdgeEstimator::CalcHeuristic.
|
// Update max pedestrian speed with possible ferry transfer. See EdgeEstimator::CalcHeuristic.
|
||||||
SpeedKMpH constexpr kMaxPedestrianSpeedKMpH(60.0);
|
SpeedKMpH constexpr kMaxPedestrianSpeedKMpH(60.0);
|
||||||
@@ -194,38 +194,37 @@ PedestrianModelFactory::PedestrianModelFactory(CountryParentNameGetterFn const &
|
|||||||
: VehicleModelFactory(countryParentNameGetterFn)
|
: VehicleModelFactory(countryParentNameGetterFn)
|
||||||
{
|
{
|
||||||
using namespace pedestrian_model;
|
using namespace pedestrian_model;
|
||||||
using std::make_shared;
|
|
||||||
|
|
||||||
// Names must be the same with country names from countries.txt
|
// Names must be the same with country names from countries.txt
|
||||||
m_models[""] = make_shared<PedestrianModel>(kDefaultOptions);
|
m_models[""] = std::make_shared<PedestrianModel>(kDefaultOptions);
|
||||||
|
|
||||||
m_models["Australia"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["Australia"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["Austria"] = make_shared<PedestrianModel>(NoTrunk());
|
m_models["Austria"] = std::make_shared<PedestrianModel>(NoTrunk());
|
||||||
m_models["Belarus"] = make_shared<PedestrianModel>(YesCycleway());
|
m_models["Belarus"] = std::make_shared<PedestrianModel>(YesCycleway());
|
||||||
m_models["Belgium"] = make_shared<PedestrianModel>(YesCycleway(YesBridleway(NoTrunk())));
|
m_models["Belgium"] = std::make_shared<PedestrianModel>(YesCycleway(YesBridleway(NoTrunk())));
|
||||||
m_models["Brazil"] = make_shared<PedestrianModel>(YesBridleway());
|
m_models["Brazil"] = std::make_shared<PedestrianModel>(YesBridleway());
|
||||||
m_models["Denmark"] = make_shared<PedestrianModel>(YesCycleway(NoTrunk()));
|
m_models["Denmark"] = std::make_shared<PedestrianModel>(YesCycleway(NoTrunk()));
|
||||||
m_models["France"] = make_shared<PedestrianModel>(NoTrunk());
|
m_models["France"] = std::make_shared<PedestrianModel>(NoTrunk());
|
||||||
m_models["Finland"] = make_shared<PedestrianModel>(YesCycleway());
|
m_models["Finland"] = std::make_shared<PedestrianModel>(YesCycleway());
|
||||||
m_models["Georgia"] = make_shared<PedestrianModel>(AllAllowed(), IncreasePrimary());
|
m_models["Georgia"] = std::make_shared<PedestrianModel>(AllAllowed(), IncreasePrimary());
|
||||||
m_models["Greece"] = make_shared<PedestrianModel>(YesCycleway(YesBridleway(NoTrunk())));
|
m_models["Greece"] = std::make_shared<PedestrianModel>(YesCycleway(YesBridleway(NoTrunk())));
|
||||||
m_models["Hungary"] = make_shared<PedestrianModel>(NoTrunk());
|
m_models["Hungary"] = std::make_shared<PedestrianModel>(NoTrunk());
|
||||||
m_models["Iceland"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["Iceland"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["Ireland"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["Ireland"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["Netherlands"] = make_shared<PedestrianModel>(YesCycleway(NoTrunk()));
|
m_models["Netherlands"] = std::make_shared<PedestrianModel>(YesCycleway(NoTrunk()));
|
||||||
m_models["Norway"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["Norway"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["Oman"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["Oman"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["Philippines"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["Philippines"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["Poland"] = make_shared<PedestrianModel>(YesBridleway(NoTrunk()));
|
m_models["Poland"] = std::make_shared<PedestrianModel>(YesBridleway(NoTrunk()));
|
||||||
m_models["Romania"] = make_shared<PedestrianModel>(YesBridleway());
|
m_models["Romania"] = std::make_shared<PedestrianModel>(YesBridleway());
|
||||||
m_models["Russian Federation"] = make_shared<PedestrianModel>(YesCycleway());
|
m_models["Russian Federation"] = std::make_shared<PedestrianModel>(YesCycleway());
|
||||||
m_models["Slovakia"] = make_shared<PedestrianModel>(NoTrunk());
|
m_models["Slovakia"] = std::make_shared<PedestrianModel>(NoTrunk());
|
||||||
m_models["Spain"] = make_shared<PedestrianModel>(NoTrunk());
|
m_models["Spain"] = std::make_shared<PedestrianModel>(NoTrunk());
|
||||||
m_models["Sweden"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["Sweden"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["Switzerland"] = make_shared<PedestrianModel>(NoTrunk());
|
m_models["Switzerland"] = std::make_shared<PedestrianModel>(NoTrunk());
|
||||||
m_models["Turkey"] = make_shared<PedestrianModel>(AllAllowed(), IncreasePrimary());
|
m_models["Turkey"] = std::make_shared<PedestrianModel>(AllAllowed(), IncreasePrimary());
|
||||||
m_models["Ukraine"] = make_shared<PedestrianModel>(NoTrunk());
|
m_models["Ukraine"] = std::make_shared<PedestrianModel>(NoTrunk());
|
||||||
m_models["United Kingdom"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["United Kingdom"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
m_models["United States of America"] = make_shared<PedestrianModel>(AllAllowed());
|
m_models["United States of America"] = std::make_shared<PedestrianModel>(AllAllowed());
|
||||||
}
|
}
|
||||||
} // namespace routing
|
} // namespace routing
|
||||||
|
|||||||
@@ -33,19 +33,18 @@ VehicleModel::VehicleModel(Classificator const & classif, LimitsInitList const &
|
|||||||
: m_highwayBasedInfo(info)
|
: m_highwayBasedInfo(info)
|
||||||
, m_onewayType(ftypes::IsOneWayChecker::Instance().GetType())
|
, m_onewayType(ftypes::IsOneWayChecker::Instance().GetType())
|
||||||
{
|
{
|
||||||
m_roadTypes.Reserve(featureTypeLimits.size());
|
m_roadTypes.reserve(featureTypeLimits.size());
|
||||||
for (auto const & v : featureTypeLimits)
|
for (auto const & v : featureTypeLimits)
|
||||||
{
|
{
|
||||||
auto const * speed = info.m_speeds.Find(v.m_type);
|
auto const it = info.m_speeds.find(v.m_type);
|
||||||
ASSERT(speed, ("Can't found speed for", v.m_type));
|
ASSERT_EQUAL(it, info.m_speeds.cend(), ("Can't found speed for", v.m_type));
|
||||||
|
|
||||||
m_maxModelSpeed = Max(m_maxModelSpeed, *speed);
|
m_maxModelSpeed = Max(m_maxModelSpeed, it->second);
|
||||||
|
|
||||||
m_roadTypes.Insert(classif.GetTypeForIndex(static_cast<uint32_t>(v.m_type)), v.m_isPassThroughAllowed);
|
m_roadTypes.insert({classif.GetTypeForIndex(static_cast<uint32_t>(v.m_type)), v.m_isPassThroughAllowed});
|
||||||
}
|
}
|
||||||
m_roadTypes.FinishBuilding();
|
|
||||||
|
|
||||||
m_surfaceFactors.Reserve(featureTypeSurface.size());
|
m_surfaceFactors.reserve(featureTypeSurface.size());
|
||||||
for (auto const & v : featureTypeSurface)
|
for (auto const & v : featureTypeSurface)
|
||||||
{
|
{
|
||||||
auto const & speedFactor = v.m_factor;
|
auto const & speedFactor = v.m_factor;
|
||||||
@@ -53,7 +52,7 @@ VehicleModel::VehicleModel(Classificator const & classif, LimitsInitList const &
|
|||||||
ASSERT_LESS_OR_EQUAL(speedFactor.m_eta, 1.0, ());
|
ASSERT_LESS_OR_EQUAL(speedFactor.m_eta, 1.0, ());
|
||||||
ASSERT_GREATER(speedFactor.m_weight, 0.0, ());
|
ASSERT_GREATER(speedFactor.m_weight, 0.0, ());
|
||||||
ASSERT_GREATER(speedFactor.m_eta, 0.0, ());
|
ASSERT_GREATER(speedFactor.m_eta, 0.0, ());
|
||||||
m_surfaceFactors.Insert(classif.GetTypeByPath(v.m_type), speedFactor);
|
m_surfaceFactors.insert({classif.GetTypeByPath(v.m_type), speedFactor});
|
||||||
|
|
||||||
if (v.m_type[1] == "paved_bad")
|
if (v.m_type[1] == "paved_bad")
|
||||||
m_minSurfaceFactorForMaxspeed = speedFactor;
|
m_minSurfaceFactorForMaxspeed = speedFactor;
|
||||||
@@ -65,9 +64,9 @@ void VehicleModel::AddAdditionalRoadTypes(Classificator const & classif, Additio
|
|||||||
for (auto const & r : roads)
|
for (auto const & r : roads)
|
||||||
{
|
{
|
||||||
uint32_t const type = classif.GetTypeByPath(r.m_type);
|
uint32_t const type = classif.GetTypeByPath(r.m_type);
|
||||||
if (m_roadTypes.Find(type) == nullptr)
|
if (m_roadTypes.find(type) == m_roadTypes.cend())
|
||||||
{
|
{
|
||||||
m_addRoadTypes.Insert(type, r.m_speed);
|
m_addRoadTypes.insert({type, r.m_speed});
|
||||||
m_maxModelSpeed = Max(m_maxModelSpeed, r.m_speed);
|
m_maxModelSpeed = Max(m_maxModelSpeed, r.m_speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,17 +94,16 @@ double VehicleModel::GetMaxWeightSpeed() const
|
|||||||
|
|
||||||
optional<HighwayType> VehicleModel::GetHighwayType(uint32_t type) const
|
optional<HighwayType> VehicleModel::GetHighwayType(uint32_t type) const
|
||||||
{
|
{
|
||||||
auto const * value = m_roadTypes.Find(type);
|
if (m_roadTypes.find(type) != m_roadTypes.cend())
|
||||||
if (value)
|
|
||||||
return static_cast<HighwayType>(classif().GetIndexForType(type));
|
return static_cast<HighwayType>(classif().GetIndexForType(type));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehicleModel::GetSurfaceFactor(uint32_t type, SpeedFactor & factor) const
|
void VehicleModel::GetSurfaceFactor(uint32_t type, SpeedFactor & factor) const
|
||||||
{
|
{
|
||||||
auto const * surface = m_surfaceFactors.Find(type);
|
auto const it = m_surfaceFactors.find(type);
|
||||||
if (surface)
|
if (it != m_surfaceFactors.cend())
|
||||||
factor = Pick<min>(factor, *surface);
|
factor = Pick<min>(factor, it->second);
|
||||||
|
|
||||||
ASSERT_LESS_OR_EQUAL(factor.m_weight, 1.0, ());
|
ASSERT_LESS_OR_EQUAL(factor.m_weight, 1.0, ());
|
||||||
ASSERT_LESS_OR_EQUAL(factor.m_eta, 1.0, ());
|
ASSERT_LESS_OR_EQUAL(factor.m_eta, 1.0, ());
|
||||||
@@ -115,12 +113,12 @@ void VehicleModel::GetSurfaceFactor(uint32_t type, SpeedFactor & factor) const
|
|||||||
|
|
||||||
void VehicleModel::GetAdditionalRoadSpeed(uint32_t type, bool isCityRoad, optional<SpeedKMpH> & speed) const
|
void VehicleModel::GetAdditionalRoadSpeed(uint32_t type, bool isCityRoad, optional<SpeedKMpH> & speed) const
|
||||||
{
|
{
|
||||||
auto const * s = m_addRoadTypes.Find(type);
|
auto const it = m_addRoadTypes.find(type);
|
||||||
if (s)
|
if (it != m_addRoadTypes.cend())
|
||||||
{
|
{
|
||||||
// Now we have only 1 additional type "yes" for all models.
|
// Now we have only 1 additional type "yes" for all models.
|
||||||
ASSERT(!speed, ());
|
ASSERT(!speed, ());
|
||||||
speed = isCityRoad ? s->m_inCity : s->m_outCity;
|
speed = isCityRoad ? it->second.m_inCity : it->second.m_outCity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,9 +155,9 @@ SpeedKMpH VehicleModel::GetTypeSpeedImpl(FeatureTypes const & types, SpeedParams
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto const * s = m_highwayBasedInfo.m_speeds.Find(*hwType);
|
auto const it = m_highwayBasedInfo.m_speeds.find(*hwType);
|
||||||
ASSERT(s, ("Key:", *hwType, "is not found."));
|
ASSERT_EQUAL(it, m_highwayBasedInfo.m_speeds.cend(), ("Key:", *hwType, "is not found."));
|
||||||
speed = s->GetSpeed(isCityRoad);
|
speed = it->second.GetSpeed(isCityRoad);
|
||||||
|
|
||||||
if (isCar)
|
if (isCar)
|
||||||
{
|
{
|
||||||
@@ -183,9 +181,9 @@ SpeedKMpH VehicleModel::GetTypeSpeedImpl(FeatureTypes const & types, SpeedParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto const typeKey = *hwType;
|
auto const typeKey = *hwType;
|
||||||
auto const * factor = m_highwayBasedInfo.m_factors.Find(typeKey);
|
auto const it = m_highwayBasedInfo.m_factors.find(typeKey);
|
||||||
ASSERT(factor, ("Key:", typeKey, "is not found."));
|
ASSERT_EQUAL(it, m_highwayBasedInfo.m_factors.cend(), ("Key:", typeKey, "is not found."));
|
||||||
auto const & f = factor->GetFactor(isCityRoad);
|
auto const & f = it->second.GetFactor(isCityRoad);
|
||||||
speed.m_weight *= f.m_weight;
|
speed.m_weight *= f.m_weight;
|
||||||
speed.m_eta *= f.m_eta;
|
speed.m_eta *= f.m_eta;
|
||||||
}
|
}
|
||||||
@@ -218,12 +216,12 @@ bool VehicleModel::IsPassThroughAllowed(FeatureTypes const & types) const
|
|||||||
ftype::TruncValue(t, 2);
|
ftype::TruncValue(t, 2);
|
||||||
|
|
||||||
// Additional types (like ferry) are always pass-through now.
|
// Additional types (like ferry) are always pass-through now.
|
||||||
if (m_addRoadTypes.Find(t))
|
if (m_addRoadTypes.find(t) != m_addRoadTypes.cend())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool const * allow = m_roadTypes.Find(t);
|
auto const it = m_roadTypes.find(t);
|
||||||
if (allow && *allow)
|
if (it != m_roadTypes.cend())
|
||||||
return true;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -232,7 +230,7 @@ bool VehicleModel::IsPassThroughAllowed(FeatureTypes const & types) const
|
|||||||
bool VehicleModel::IsRoadType(uint32_t type) const
|
bool VehicleModel::IsRoadType(uint32_t type) const
|
||||||
{
|
{
|
||||||
ftype::TruncValue(type, 2);
|
ftype::TruncValue(type, 2);
|
||||||
return m_addRoadTypes.Find(type) || m_roadTypes.Find(type);
|
return m_addRoadTypes.find(type) != m_addRoadTypes.cend() || m_roadTypes.find(type) != m_roadTypes.cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VehicleModel::IsRoadImpl(FeatureTypes const & types) const
|
bool VehicleModel::IsRoadImpl(FeatureTypes const & types) const
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "indexer/feature_data.hpp"
|
#include "indexer/feature_data.hpp"
|
||||||
|
|
||||||
#include "base/small_map.hpp"
|
#include <boost/container_hash/hash.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "3party/ankerl/unordered_dense.h"
|
#include "3party/ankerl/unordered_dense.h"
|
||||||
|
#include "3party/skarupke/flat_hash_map.hpp"
|
||||||
|
|
||||||
class Classificator;
|
class Classificator;
|
||||||
class FeatureType;
|
class FeatureType;
|
||||||
@@ -60,8 +61,8 @@ enum class HighwayType : uint16_t
|
|||||||
RouteShuttleTrain = 1054,
|
RouteShuttleTrain = 1054,
|
||||||
};
|
};
|
||||||
|
|
||||||
using HighwayBasedFactors = base::SmallMap<HighwayType, InOutCityFactor>;
|
using HighwayBasedFactors = ska::flat_hash_map<HighwayType, InOutCityFactor, boost::hash<HighwayType>>;
|
||||||
using HighwayBasedSpeeds = base::SmallMap<HighwayType, InOutCitySpeedKMpH>;
|
using HighwayBasedSpeeds = ska::flat_hash_map<HighwayType, InOutCitySpeedKMpH, boost::hash<HighwayType>>;
|
||||||
|
|
||||||
/// \brief Params for calculation of an approximate speed on a feature.
|
/// \brief Params for calculation of an approximate speed on a feature.
|
||||||
struct SpeedParams
|
struct SpeedParams
|
||||||
@@ -330,13 +331,13 @@ private:
|
|||||||
uint32_t m_onewayType;
|
uint32_t m_onewayType;
|
||||||
|
|
||||||
// HW type -> allow pass through.
|
// HW type -> allow pass through.
|
||||||
base::SmallMap<uint32_t, bool> m_roadTypes;
|
ska::flat_hash_map<uint32_t, bool, boost::hash<uint32_t>> m_roadTypes;
|
||||||
// Mapping surface types psurface={paved_good/paved_bad/unpaved_good/unpaved_bad} to surface speed factors.
|
// Mapping surface types psurface={paved_good/paved_bad/unpaved_good/unpaved_bad} to surface speed factors.
|
||||||
base::SmallMapBase<uint32_t, SpeedFactor> m_surfaceFactors;
|
ska::flat_hash_map<uint32_t, SpeedFactor, boost::hash<uint32_t>> m_surfaceFactors;
|
||||||
SpeedFactor m_minSurfaceFactorForMaxspeed;
|
SpeedFactor m_minSurfaceFactorForMaxspeed;
|
||||||
|
|
||||||
/// @todo Do we really need a separate map here or can merge with the m_roadTypes map?
|
/// @todo Do we really need a separate map here or can merge with the m_roadTypes map?
|
||||||
base::SmallMapBase<uint32_t, InOutCitySpeedKMpH> m_addRoadTypes;
|
ska::flat_hash_map<uint32_t, InOutCitySpeedKMpH, boost::hash<uint32_t>> m_addRoadTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VehicleModelFactory : public VehicleModelFactoryInterface
|
class VehicleModelFactory : public VehicleModelFactoryInterface
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
#include "indexer/categories_holder.hpp"
|
#include "indexer/categories_holder.hpp"
|
||||||
|
|
||||||
#include "base/buffer_vector.hpp"
|
#include "base/buffer_vector.hpp"
|
||||||
#include "base/small_set.hpp"
|
|
||||||
#include "base/string_utils.hpp"
|
#include "base/string_utils.hpp"
|
||||||
|
|
||||||
|
#include "3party/ankerl/unordered_dense.h"
|
||||||
|
|
||||||
namespace search
|
namespace search
|
||||||
{
|
{
|
||||||
// The prefix is stored separately.
|
// The prefix is stored separately.
|
||||||
@@ -13,7 +14,7 @@ namespace search
|
|||||||
// the prefix and non-prefix tokens.
|
// the prefix and non-prefix tokens.
|
||||||
using QueryTokens = buffer_vector<strings::UniString, 32>;
|
using QueryTokens = buffer_vector<strings::UniString, 32>;
|
||||||
|
|
||||||
using Locales = base::SafeSmallSet<CategoriesHolder::kLocaleMapping.size() + 1>;
|
using Locales = ankerl::unordered_dense::set<uint64_t>;
|
||||||
|
|
||||||
/// Upper bound for max count of tokens for indexing and scoring.
|
/// Upper bound for max count of tokens for indexing and scoring.
|
||||||
size_t constexpr kMaxNumTokens = 32;
|
size_t constexpr kMaxNumTokens = 32;
|
||||||
|
|||||||
@@ -495,11 +495,11 @@ Locales Processor::GetCategoryLocales() const
|
|||||||
Locales result;
|
Locales result;
|
||||||
|
|
||||||
// Prepare array of processing locales. English locale is always present for category matching.
|
// Prepare array of processing locales. English locale is always present for category matching.
|
||||||
result.Insert(static_cast<uint64_t>(enLocaleCode));
|
result.insert(static_cast<uint64_t>(enLocaleCode));
|
||||||
if (m_currentLocaleCode != -1)
|
if (m_currentLocaleCode != -1)
|
||||||
result.Insert(static_cast<uint64_t>(m_currentLocaleCode));
|
result.insert(static_cast<uint64_t>(m_currentLocaleCode));
|
||||||
if (m_inputLocaleCode != -1)
|
if (m_inputLocaleCode != -1)
|
||||||
result.Insert(static_cast<uint64_t>(m_inputLocaleCode));
|
result.insert(static_cast<uint64_t>(m_inputLocaleCode));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -829,7 +829,7 @@ void Processor::InitParams(QueryParams & params) const
|
|||||||
for (size_t i = 0; i < params.GetNumTokens(); ++i)
|
for (size_t i = 0; i < params.GetNumTokens(); ++i)
|
||||||
base::SortUnique(params.GetTypeIndices(i));
|
base::SortUnique(params.GetTypeIndices(i));
|
||||||
|
|
||||||
m_keywordsScorer.ForEachLanguage([¶ms](int8_t lang) { params.GetLangs().Insert(static_cast<uint64_t>(lang)); });
|
m_keywordsScorer.ForEachLanguage([¶ms](int8_t lang) { params.GetLangs().insert(static_cast<uint64_t>(lang)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Processor::InitGeocoder(Geocoder::Params & geocoderParams, SearchParams const & searchParams)
|
void Processor::InitGeocoder(Geocoder::Params & geocoderParams, SearchParams const & searchParams)
|
||||||
|
|||||||
@@ -1542,7 +1542,7 @@ void QueryParams::Clear()
|
|||||||
m_hasPrefix = false;
|
m_hasPrefix = false;
|
||||||
m_isCommonToken.clear();
|
m_isCommonToken.clear();
|
||||||
m_typeIndices.clear();
|
m_typeIndices.clear();
|
||||||
m_langs.Clear();
|
m_langs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueryParams::IsCategorySynonym(size_t i) const
|
bool QueryParams::IsCategorySynonym(size_t i) const
|
||||||
@@ -1637,7 +1637,7 @@ string DebugPrint(QueryParams const & params)
|
|||||||
ostringstream os;
|
ostringstream os;
|
||||||
os << boolalpha << "QueryParams "
|
os << boolalpha << "QueryParams "
|
||||||
<< "{ m_tokens: " << ::DebugPrint(params.m_tokens) << ", m_prefixToken: " << DebugPrint(params.m_prefixToken)
|
<< "{ m_tokens: " << ::DebugPrint(params.m_tokens) << ", m_prefixToken: " << DebugPrint(params.m_prefixToken)
|
||||||
<< ", m_typeIndices: " << ::DebugPrint(params.m_typeIndices) << ", m_langs: " << DebugPrint(params.m_langs)
|
<< ", m_typeIndices: " << ::DebugPrint(params.m_typeIndices) << ", m_langs: " << ::DebugPrint(params.m_langs)
|
||||||
<< ", m_isCommonToken: " << ::DebugPrint(params.m_isCommonToken) << " }";
|
<< ", m_isCommonToken: " << ::DebugPrint(params.m_isCommonToken) << " }";
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
#include "coding/string_utf8_multilang.hpp"
|
#include "coding/string_utf8_multilang.hpp"
|
||||||
|
|
||||||
#include "base/assert.hpp"
|
#include "base/assert.hpp"
|
||||||
#include "base/small_set.hpp"
|
|
||||||
#include "base/string_utils.hpp"
|
#include "base/string_utils.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "3party/ankerl/unordered_dense.h"
|
||||||
|
|
||||||
namespace search
|
namespace search
|
||||||
{
|
{
|
||||||
class TokenRange;
|
class TokenRange;
|
||||||
@@ -19,7 +20,7 @@ class QueryParams
|
|||||||
public:
|
public:
|
||||||
using String = strings::UniString;
|
using String = strings::UniString;
|
||||||
using TypeIndices = std::vector<uint32_t>;
|
using TypeIndices = std::vector<uint32_t>;
|
||||||
using Langs = base::SafeSmallSet<StringUtf8Multilang::kMaxSupportedLanguages>;
|
using Langs = ankerl::unordered_dense::set<int8_t>;
|
||||||
|
|
||||||
class Token
|
class Token
|
||||||
{
|
{
|
||||||
@@ -127,7 +128,7 @@ public:
|
|||||||
|
|
||||||
Langs & GetLangs() { return m_langs; }
|
Langs & GetLangs() { return m_langs; }
|
||||||
Langs const & GetLangs() const { return m_langs; }
|
Langs const & GetLangs() const { return m_langs; }
|
||||||
bool LangExists(int8_t lang) const { return m_langs.Contains(lang); }
|
bool LangExists(int8_t lang) const { return m_langs.contains(lang); }
|
||||||
|
|
||||||
void SetCategorialRequest(bool isCategorial) { m_isCategorialRequest = isCategorial; }
|
void SetCategorialRequest(bool isCategorial) { m_isCategorialRequest = isCategorial; }
|
||||||
bool IsCategorialRequest() const { return m_isCategorialRequest; }
|
bool IsCategorialRequest() const { return m_isCategorialRequest; }
|
||||||
@@ -147,5 +148,10 @@ private:
|
|||||||
std::vector<TypeIndices> m_typeIndices;
|
std::vector<TypeIndices> m_typeIndices;
|
||||||
|
|
||||||
Langs m_langs;
|
Langs m_langs;
|
||||||
|
|
||||||
|
inline std::string DebugPrint(Langs const & v)
|
||||||
|
{
|
||||||
|
return DebugPrintSequence(v.cbegin(), v.cend());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace search
|
} // namespace search
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "3party/ankerl/unordered_dense.h"
|
#include "3party/ankerl/unordered_dense.h"
|
||||||
|
#include "3party/skarupke/flat_hash_map.hpp"
|
||||||
|
|
||||||
namespace locality_scorer_test
|
namespace locality_scorer_test
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ std::vector<uint32_t> GetCategoryTypes(std::string const & name, std::string con
|
|||||||
|
|
||||||
int8_t const code = CategoriesHolder::MapLocaleToInteger(locale);
|
int8_t const code = CategoriesHolder::MapLocaleToInteger(locale);
|
||||||
Locales locales;
|
Locales locales;
|
||||||
locales.Insert(static_cast<uint64_t>(code));
|
locales.insert(static_cast<uint64_t>(code));
|
||||||
|
|
||||||
auto const tokens = NormalizeAndTokenizeString(name);
|
auto const tokens = NormalizeAndTokenizeString(name);
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ bool FillCategories(QuerySliceOnRawStrings<T> const & slice, Locales const & loc
|
|||||||
types.clear();
|
types.clear();
|
||||||
catHolder.ForEachNameAndType([&](CategoriesHolder::Category::Name const & categorySynonym, uint32_t type)
|
catHolder.ForEachNameAndType([&](CategoriesHolder::Category::Name const & categorySynonym, uint32_t type)
|
||||||
{
|
{
|
||||||
if (!locales.Contains(static_cast<uint64_t>(categorySynonym.m_locale)))
|
if (!locales.contains(static_cast<uint64_t>(categorySynonym.m_locale)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto const categoryTokens = NormalizeAndTokenizeString(categorySynonym.m_name);
|
auto const categoryTokens = NormalizeAndTokenizeString(categorySynonym.m_name);
|
||||||
|
|||||||
Reference in New Issue
Block a user