Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/search
diff options
context:
space:
mode:
authorYuri Gorshenin <y@maps.me>2016-07-04 16:24:47 +0300
committerYuri Gorshenin <y@maps.me>2016-07-05 12:40:47 +0300
commit7df300bc547e7fbb845ff3cedf95d27b61a7ad73 (patch)
treed058fe814917d70bf9cff3e95f4eb11bd6c15c4e /search
parent36fe4a08508b790a16677465e2e0ed5db70f0414 (diff)
Minor fixes - get rid of redundant copying.
Diffstat (limited to 'search')
-rw-r--r--search/cbv.cpp114
-rw-r--r--search/cbv.hpp59
-rw-r--r--search/cbv_ptr.cpp106
-rw-r--r--search/cbv_ptr.hpp58
-rw-r--r--search/features_filter.cpp29
-rw-r--r--search/features_filter.hpp26
-rw-r--r--search/features_layer_matcher.cpp2
-rw-r--r--search/features_layer_matcher.hpp11
-rw-r--r--search/geocoder.cpp171
-rw-r--r--search/geocoder.hpp25
-rw-r--r--search/geocoder_context.hpp13
-rw-r--r--search/geometry_cache.cpp10
-rw-r--r--search/geometry_cache.hpp15
-rw-r--r--search/search.pro4
-rw-r--r--search/streets_matcher.cpp53
-rw-r--r--search/streets_matcher.hpp4
16 files changed, 328 insertions, 372 deletions
diff --git a/search/cbv.cpp b/search/cbv.cpp
new file mode 100644
index 0000000000..437abe7c36
--- /dev/null
+++ b/search/cbv.cpp
@@ -0,0 +1,114 @@
+#include "search/cbv.hpp"
+
+#include "std/limits.hpp"
+#include "std/vector.hpp"
+
+using namespace my;
+
+namespace search
+{
+namespace
+{
+uint64_t const kModulo = 18446744073709551557LLU;
+} // namespace
+
+CBV::CBV(unique_ptr<coding::CompressedBitVector> p) : m_p(move(p)) {}
+
+CBV::CBV(CBV && cbv) : m_p(move(cbv.m_p)), m_isFull(cbv.m_isFull) { cbv.m_isFull = false; }
+
+CBV & CBV::operator=(unique_ptr<coding::CompressedBitVector> p)
+{
+ m_p = move(p);
+ m_isFull = false;
+
+ return *this;
+}
+
+CBV & CBV::operator=(CBV && rhs)
+{
+ if (this == &rhs)
+ return *this;
+
+ m_p = move(rhs.m_p);
+ m_isFull = rhs.m_isFull;
+
+ rhs.m_isFull = false;
+
+ return *this;
+}
+
+void CBV::SetFull()
+{
+ m_p.Reset();
+ m_isFull = true;
+}
+
+void CBV::Reset()
+{
+ m_p.Reset();
+ m_isFull = false;
+}
+
+bool CBV::HasBit(uint64_t id) const
+{
+ if (IsFull())
+ return true;
+ if (IsEmpty())
+ return false;
+ return m_p->GetBit(id);
+}
+
+uint64_t CBV::PopCount() const
+{
+ ASSERT(!IsFull(), ());
+ if (IsEmpty())
+ return 0;
+ return m_p->PopCount();
+}
+
+CBV CBV::Union(CBV const & rhs) const
+{
+ if (IsFull() || rhs.IsEmpty())
+ return *this;
+ if (IsEmpty() || rhs.IsFull())
+ return rhs;
+ return CBV(coding::CompressedBitVector::Union(*m_p, *rhs.m_p));
+}
+
+CBV CBV::Intersect(CBV const & rhs) const
+{
+ if (IsFull() || rhs.IsEmpty())
+ return rhs;
+ if (IsEmpty() || rhs.IsFull())
+ return *this;
+ return CBV(coding::CompressedBitVector::Intersect(*m_p, *rhs.m_p));
+}
+
+CBV CBV::Take(uint64_t n) const
+{
+ if (IsEmpty())
+ return *this;
+ if (IsFull())
+ {
+ vector<uint64_t> groups((n + 63) / 64, numeric_limits<uint64_t>::max());
+ uint64_t const r = n % 64;
+ if (r != 0)
+ {
+ ASSERT(!groups.empty(), ());
+ groups.back() = (static_cast<uint64_t>(1) << r) - 1;
+ }
+ return CBV(coding::DenseCBV::BuildFromBitGroups(move(groups)));
+ }
+
+ return CBV(m_p->LeaveFirstSetNBits(n));
+}
+
+uint64_t CBV::Hash() const
+{
+ if (IsEmpty())
+ return 0;
+ if (IsFull())
+ return kModulo;
+ return coding::CompressedBitVectorHasher::Hash(*m_p) % kModulo;
+}
+} // namespace search
diff --git a/search/cbv.hpp b/search/cbv.hpp
new file mode 100644
index 0000000000..b52ff839f6
--- /dev/null
+++ b/search/cbv.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include "coding/compressed_bit_vector.hpp"
+
+#include "base/ref_counted.hpp"
+
+#include "std/function.hpp"
+#include "std/utility.hpp"
+
+namespace search
+{
+// A wrapper around coding::CompressedBitVector that augments the
+// latter with the "full" state and uses reference counting for
+// ownership sharing.
+class CBV
+{
+public:
+ CBV() = default;
+ explicit CBV(unique_ptr<coding::CompressedBitVector> p);
+ CBV(CBV const & cbv) = default;
+ CBV(CBV && cbv);
+
+ inline operator bool() const { return !IsEmpty(); }
+ CBV & operator=(unique_ptr<coding::CompressedBitVector> p);
+ CBV & operator=(CBV const & rhs) = default;
+ CBV & operator=(CBV && rhs);
+
+ void SetFull();
+ void Reset();
+
+ inline bool IsEmpty() const { return !m_isFull && coding::CompressedBitVector::IsEmpty(m_p.Get()); }
+ inline bool IsFull() const { return m_isFull; }
+
+ bool HasBit(uint64_t id) const;
+ uint64_t PopCount() const;
+
+ template <class TFn>
+ void ForEach(TFn && fn) const
+ {
+ ASSERT(!m_isFull, ());
+ if (!IsEmpty())
+ coding::CompressedBitVectorEnumerator::ForEach(*m_p, forward<TFn>(fn));
+ }
+
+ CBV Union(CBV const & rhs) const;
+ CBV Intersect(CBV const & rhs) const;
+
+ // Takes first set |n| bits.
+ CBV Take(uint64_t n) const;
+
+ uint64_t Hash() const;
+
+private:
+ my::RefCountPtr<coding::CompressedBitVector> m_p;
+
+ // True iff all bits are set to one.
+ bool m_isFull = false;
+};
+} // namespace search
diff --git a/search/cbv_ptr.cpp b/search/cbv_ptr.cpp
deleted file mode 100644
index 65eef82fd7..0000000000
--- a/search/cbv_ptr.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "search/cbv_ptr.hpp"
-
-namespace search
-{
-CBVPtr::CBVPtr(coding::CompressedBitVector const * p, bool isOwner) { Set(p, isOwner); }
-
-CBVPtr::CBVPtr(CBVPtr && rhs) { *this = move(rhs); }
-
-CBVPtr::~CBVPtr() { Release(); }
-
-void CBVPtr::Release()
-{
- if (m_isOwner)
- delete m_ptr;
-
- m_ptr = nullptr;
- m_isOwner = false;
- m_isFull = false;
-}
-
-void CBVPtr::SetFull()
-{
- Release();
- m_isFull = true;
-}
-
-void CBVPtr::Set(coding::CompressedBitVector const * p, bool isOwner /* = false*/)
-{
- Release();
-
- m_ptr = p;
- m_isOwner = p && isOwner;
-}
-
-void CBVPtr::Set(unique_ptr<coding::CompressedBitVector> p)
-{
- Set(p.release(), true /* isOwner */);
-}
-
-CBVPtr & CBVPtr::operator=(CBVPtr && rhs) noexcept
-{
- if (this == &rhs)
- return *this;
-
- m_ptr = rhs.m_ptr;
- m_isOwner = rhs.m_isOwner;
- m_isFull = rhs.m_isFull;
-
- rhs.m_ptr = nullptr;
- rhs.m_isOwner = false;
- rhs.m_isFull = false;
-
- return *this;
-}
-
-void CBVPtr::Union(coding::CompressedBitVector const * p)
-{
- if (!p || m_isFull)
- return;
-
- if (!m_ptr)
- {
- m_ptr = p;
- m_isFull = false;
- m_isOwner = false;
- }
- else
- {
- Set(coding::CompressedBitVector::Union(*m_ptr, *p).release(), true /* isOwner */);
- }
-}
-
-void CBVPtr::Intersect(coding::CompressedBitVector const * p)
-{
- if (!p)
- {
- Release();
- return;
- }
-
- if (m_ptr)
- {
- Set(coding::CompressedBitVector::Intersect(*m_ptr, *p).release(), true /* isOwner */);
- }
- else if (m_isFull)
- {
- m_ptr = p;
- m_isFull = false;
- m_isOwner = false;
- }
-}
-
-void CBVPtr::CopyTo(CBVPtr & rhs)
-{
- rhs.Release();
-
- if (m_isFull)
- {
- rhs.SetFull();
- return;
- }
-
- if (m_ptr)
- rhs.Set(m_ptr->Clone());
-}
-} // namespace search
diff --git a/search/cbv_ptr.hpp b/search/cbv_ptr.hpp
deleted file mode 100644
index a769ac6886..0000000000
--- a/search/cbv_ptr.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#pragma once
-
-#include "coding/compressed_bit_vector.hpp"
-
-#include "base/assert.hpp"
-#include "base/macros.hpp"
-
-#include "std/function.hpp"
-#include "std/utility.hpp"
-
-namespace search
-{
-/// CompressedBitVector pointer class that incapsulates
-/// binary operators logic and takes ownership if needed.
-class CBVPtr
-{
- DISALLOW_COPY(CBVPtr);
-
- coding::CompressedBitVector const * m_ptr = nullptr;
- bool m_isOwner = false;
- bool m_isFull = false; ///< True iff all bits are set to one.
-
- void Release();
-
-public:
- CBVPtr() = default;
- CBVPtr(coding::CompressedBitVector const * p, bool isOwner);
- CBVPtr(CBVPtr && rhs);
- ~CBVPtr();
-
- void SetFull();
- void Set(coding::CompressedBitVector const * p, bool isOwner = false);
- void Set(unique_ptr<coding::CompressedBitVector> p);
-
- inline coding::CompressedBitVector const * Get() const { return m_ptr; }
-
- inline coding::CompressedBitVector const & operator*() const { return *m_ptr; }
- inline coding::CompressedBitVector const * operator->() const { return m_ptr; }
- CBVPtr & operator=(CBVPtr && rhs) noexcept;
-
- inline bool IsEmpty() const { return !m_isFull && coding::CompressedBitVector::IsEmpty(m_ptr); }
- inline bool IsFull() const { return m_isFull; }
- inline bool IsOwner() const noexcept { return m_isOwner; }
-
- void Union(coding::CompressedBitVector const * p);
- void Intersect(coding::CompressedBitVector const * p);
-
- void CopyTo(CBVPtr & rhs);
-
- template <class TFn>
- void ForEach(TFn && fn) const
- {
- ASSERT(!m_isFull, ());
- if (!IsEmpty())
- coding::CompressedBitVectorEnumerator::ForEach(*m_ptr, forward<TFn>(fn));
- }
-};
-} // namespace search
diff --git a/search/features_filter.cpp b/search/features_filter.cpp
index 0f9912ad07..5f04345b6c 100644
--- a/search/features_filter.cpp
+++ b/search/features_filter.cpp
@@ -1,47 +1,48 @@
#include "search/features_filter.hpp"
-#include "coding/compressed_bit_vector.hpp"
+#include "search/cbv.hpp"
#include "std/algorithm.hpp"
+#include "std/vector.hpp"
namespace search
{
// FeaturesFilter ----------------------------------------------------------------------------------
-FeaturesFilter::FeaturesFilter(coding::CompressedBitVector const & filter, uint32_t threshold)
+FeaturesFilter::FeaturesFilter(CBV const & filter, uint32_t threshold)
: m_filter(filter), m_threshold(threshold)
{
}
-bool FeaturesFilter::NeedToFilter(coding::CompressedBitVector const & cbv) const
+bool FeaturesFilter::NeedToFilter(CBV const & cbv) const
{
+ if (cbv.IsFull())
+ return true;
return cbv.PopCount() > m_threshold;
}
// LocalityFilter ----------------------------------------------------------------------------------
-LocalityFilter::LocalityFilter(coding::CompressedBitVector const & filter)
+LocalityFilter::LocalityFilter(CBV const & filter)
: FeaturesFilter(filter, 0 /* threshold */)
{
}
-unique_ptr<coding::CompressedBitVector> LocalityFilter::Filter(
- coding::CompressedBitVector const & cbv) const
+CBV LocalityFilter::Filter(CBV const & cbv) const
{
- return coding::CompressedBitVector::Intersect(m_filter, cbv);
+ return m_filter.Intersect(cbv);
}
// ViewportFilter ----------------------------------------------------------------------------------
-ViewportFilter::ViewportFilter(coding::CompressedBitVector const & filter, uint32_t threshold)
+ViewportFilter::ViewportFilter(CBV const & filter, uint32_t threshold)
: FeaturesFilter(filter, threshold)
{
}
-unique_ptr<coding::CompressedBitVector> ViewportFilter::Filter(
- coding::CompressedBitVector const & cbv) const
+CBV ViewportFilter::Filter(CBV const & cbv) const
{
- auto result = coding::CompressedBitVector::Intersect(m_filter, cbv);
- if (!coding::CompressedBitVector::IsEmpty(result))
+ auto result = m_filter.Intersect(cbv);
+ if (!result.IsEmpty())
return result;
- return cbv.LeaveFirstSetNBits(m_threshold);
-}
+ return cbv.Take(m_threshold);
+}
} // namespace search
diff --git a/search/features_filter.hpp b/search/features_filter.hpp
index fb5f425c3c..8aaf27d782 100644
--- a/search/features_filter.hpp
+++ b/search/features_filter.hpp
@@ -2,30 +2,26 @@
#include "std/unique_ptr.hpp"
-namespace coding
-{
-class CompressedBitVector;
-}
-
namespace search
{
+class CBV;
+
// A lightweight filter of features.
//
// NOTE: this class and its subclasses *ARE* thread-safe.
class FeaturesFilter
{
public:
- FeaturesFilter(coding::CompressedBitVector const & filter, uint32_t threshold);
+ FeaturesFilter(CBV const & filter, uint32_t threshold);
virtual ~FeaturesFilter() = default;
- bool NeedToFilter(coding::CompressedBitVector const & features) const;
+ bool NeedToFilter(CBV const & features) const;
- virtual unique_ptr<coding::CompressedBitVector> Filter(
- coding::CompressedBitVector const & cbv) const = 0;
+ virtual CBV Filter(CBV const & cbv) const = 0;
protected:
- coding::CompressedBitVector const & m_filter;
+ CBV const & m_filter;
uint32_t const m_threshold;
};
@@ -34,11 +30,10 @@ protected:
class LocalityFilter : public FeaturesFilter
{
public:
- LocalityFilter(coding::CompressedBitVector const & filter);
+ LocalityFilter(CBV const & filter);
// FeaturesFilter overrides:
- unique_ptr<coding::CompressedBitVector> Filter(
- coding::CompressedBitVector const & cbv) const override;
+ CBV Filter(CBV const & cbv) const override;
};
// Fuzzy filter - tries to leave only features belonging to the set it
@@ -49,11 +44,10 @@ public:
class ViewportFilter : public FeaturesFilter
{
public:
- ViewportFilter(coding::CompressedBitVector const & filter, uint32_t threshold);
+ ViewportFilter(CBV const & filter, uint32_t threshold);
// FeaturesFilter overrides:
- unique_ptr<coding::CompressedBitVector> Filter(
- coding::CompressedBitVector const & cbv) const override;
+ CBV Filter(CBV const & cbv) const override;
};
} // namespace search
diff --git a/search/features_layer_matcher.cpp b/search/features_layer_matcher.cpp
index 1f98b22ffb..9dae2741fd 100644
--- a/search/features_layer_matcher.cpp
+++ b/search/features_layer_matcher.cpp
@@ -34,7 +34,7 @@ void FeaturesLayerMatcher::SetContext(MwmContext * context)
m_loader.SetContext(context);
}
-void FeaturesLayerMatcher::SetPostcodes(coding::CompressedBitVector const * postcodes)
+void FeaturesLayerMatcher::SetPostcodes(CBV const * postcodes)
{
m_postcodes = postcodes;
}
diff --git a/search/features_layer_matcher.hpp b/search/features_layer_matcher.hpp
index f9ae2df657..387b98feb6 100644
--- a/search/features_layer_matcher.hpp
+++ b/search/features_layer_matcher.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "search/cancel_exception.hpp"
+#include "search/cbv.hpp"
#include "search/features_layer.hpp"
#include "search/house_numbers_matcher.hpp"
#include "search/model.hpp"
@@ -19,8 +20,6 @@
#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"
-#include "coding/compressed_bit_vector.hpp"
-
#include "base/cancellable.hpp"
#include "base/logging.hpp"
#include "base/macros.hpp"
@@ -61,7 +60,7 @@ public:
FeaturesLayerMatcher(Index & index, my::Cancellable const & cancellable);
void SetContext(MwmContext * context);
- void SetPostcodes(coding::CompressedBitVector const * postcodes);
+ void SetPostcodes(CBV const * postcodes);
template <typename TFn>
void Match(FeaturesLayer const & child, FeaturesLayer const & parent, TFn && fn)
@@ -165,7 +164,7 @@ private:
MercatorBounds::RectByCenterXYAndSizeInMeters(poiCenters[i], kBuildingRadiusMeters),
[&](FeatureType & ft)
{
- if (m_postcodes && !m_postcodes->GetBit(ft.GetID().m_index))
+ if (m_postcodes && !m_postcodes->HasBit(ft.GetID().m_index))
return;
if (house_numbers::HouseNumbersMatch(strings::MakeUniString(ft.GetHouseNumber()),
queryParse))
@@ -252,7 +251,7 @@ private:
if (binary_search(buildings.begin(), buildings.end(), id))
return true;
- if (m_postcodes && !m_postcodes->GetBit(id))
+ if (m_postcodes && !m_postcodes->HasBit(id))
return false;
if (!loaded)
@@ -344,7 +343,7 @@ private:
MwmContext * m_context;
- coding::CompressedBitVector const * m_postcodes;
+ CBV const * m_postcodes;
ReverseGeocoder m_reverseGeocoder;
diff --git a/search/geocoder.cpp b/search/geocoder.cpp
index 0c5079f6fb..de8a7a5b00 100644
--- a/search/geocoder.cpp
+++ b/search/geocoder.cpp
@@ -1,6 +1,6 @@
#include "search/geocoder.hpp"
-#include "search/cbv_ptr.hpp"
+#include "search/cbv.hpp"
#include "search/dummy_rank_table.hpp"
#include "search/features_filter.hpp"
#include "search/features_layer_matcher.hpp"
@@ -387,14 +387,14 @@ size_t OrderCountries(m2::RectD const & pivot, vector<shared_ptr<MwmInfo>> & inf
// Performs pairwise union of adjacent bit vectors
// until at most one bit vector is left.
-void UniteCBVs(vector<unique_ptr<coding::CompressedBitVector>> & cbvs)
+void UniteCBVs(vector<CBV> & cbvs)
{
while (cbvs.size() > 1)
{
size_t i = 0;
size_t j = 0;
for (; j + 1 < cbvs.size(); j += 2)
- cbvs[i++] = coding::CompressedBitVector::Union(*cbvs[j], *cbvs[j + 1]);
+ cbvs[i++] = cbvs[j].Union(cbvs[j + 1]);
for (; j < cbvs.size(); ++j)
cbvs[i++] = move(cbvs[j]);
cbvs.resize(i);
@@ -580,14 +580,12 @@ void Geocoder::GoImpl(PreRanker & preRanker, vector<shared_ptr<MwmInfo>> & infos
BaseContext ctx;
InitBaseContext(ctx);
- coding::CompressedBitVector const * viewportCBV = nullptr;
if (inViewport)
- viewportCBV = RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RECT_ID_PIVOT);
-
- if (viewportCBV)
{
+ auto const viewportCBV =
+ RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RECT_ID_PIVOT);
for (auto & features : ctx.m_features)
- features = coding::CompressedBitVector::Intersect(*features, *viewportCBV);
+ features = features.Intersect(viewportCBV);
}
ctx.m_villages = LoadVillages(*m_context);
@@ -659,7 +657,6 @@ void Geocoder::InitBaseContext(BaseContext & ctx)
PrepareRetrievalParams(i, i + 1);
ctx.m_features[i] = RetrieveAddressFeatures(m_context->GetId(), m_context->m_value,
m_cancellable, m_retrievalParams);
- ASSERT(ctx.m_features[i], ());
}
}
@@ -676,8 +673,7 @@ void Geocoder::InitLayer(SearchModel::SearchType type, size_t startToken, size_t
layer.m_lastTokenIsPrefix = (layer.m_endToken > m_params.m_tokens.size());
}
-void Geocoder::FillLocalityCandidates(BaseContext const & ctx,
- coding::CompressedBitVector const * filter,
+void Geocoder::FillLocalityCandidates(BaseContext const & ctx, CBV const & filter,
size_t const maxNumLocalities,
vector<Locality> & preLocalities)
{
@@ -685,19 +681,12 @@ void Geocoder::FillLocalityCandidates(BaseContext const & ctx,
for (size_t startToken = 0; startToken < ctx.m_numTokens; ++startToken)
{
- CBVPtr intersection;
- CBVPtr unfilteredIntersection;
- intersection.SetFull();
- unfilteredIntersection.SetFull();
- if (filter)
- {
- intersection.Intersect(filter);
- unfilteredIntersection.Intersect(ctx.m_features[startToken].get());
- }
- intersection.Intersect(ctx.m_features[startToken].get());
+ CBV intersection = filter.Intersect(ctx.m_features[startToken]);
if (intersection.IsEmpty())
continue;
+ CBV unfilteredIntersection = ctx.m_features[startToken];
+
for (size_t endToken = startToken + 1; endToken <= ctx.m_numTokens; ++endToken)
{
// Skip locality candidates that match only numbers.
@@ -710,22 +699,19 @@ void Geocoder::FillLocalityCandidates(BaseContext const & ctx,
l.m_featureId = featureId;
l.m_startToken = startToken;
l.m_endToken = endToken;
- if (filter)
- {
- l.m_prob = static_cast<double>(intersection->PopCount()) /
- static_cast<double>(unfilteredIntersection->PopCount());
- }
+ l.m_prob = static_cast<double>(intersection.PopCount()) /
+ static_cast<double>(unfilteredIntersection.PopCount());
preLocalities.push_back(l);
});
}
if (endToken < ctx.m_numTokens)
{
- intersection.Intersect(ctx.m_features[endToken].get());
- if (filter)
- unfilteredIntersection.Intersect(ctx.m_features[endToken].get());
+ intersection = intersection.Intersect(ctx.m_features[endToken]);
if (intersection.IsEmpty())
break;
+
+ unfilteredIntersection = unfilteredIntersection.Intersect(ctx.m_features[endToken]);
}
}
}
@@ -738,7 +724,10 @@ void Geocoder::FillLocalityCandidates(BaseContext const & ctx,
void Geocoder::FillLocalitiesTable(BaseContext const & ctx)
{
vector<Locality> preLocalities;
- FillLocalityCandidates(ctx, nullptr /* filter */, kMaxNumLocalities, preLocalities);
+
+ CBV filter;
+ filter.SetFull();
+ FillLocalityCandidates(ctx, filter, kMaxNumLocalities, preLocalities);
size_t numCities = 0;
size_t numStates = 0;
@@ -810,7 +799,7 @@ void Geocoder::FillLocalitiesTable(BaseContext const & ctx)
void Geocoder::FillVillageLocalities(BaseContext const & ctx)
{
vector<Locality> preLocalities;
- FillLocalityCandidates(ctx, ctx.m_villages.get() /* filter */, kMaxNumVillages, preLocalities);
+ FillLocalityCandidates(ctx, ctx.m_villages /* filter */, kMaxNumVillages, preLocalities);
size_t numVillages = 0;
@@ -971,13 +960,12 @@ void Geocoder::MatchCities(BaseContext & ctx)
if (m_context->GetInfo()->GetType() == MwmInfo::WORLD)
continue;
- auto const * cityFeatures =
- RetrieveGeometryFeatures(*m_context, city.m_rect, RECT_ID_LOCALITY);
+ auto cityFeatures = RetrieveGeometryFeatures(*m_context, city.m_rect, RECT_ID_LOCALITY);
- if (coding::CompressedBitVector::IsEmpty(cityFeatures))
+ if (cityFeatures.IsEmpty())
continue;
- LocalityFilter filter(*cityFeatures);
+ LocalityFilter filter(cityFeatures);
LimitedSearch(ctx, filter);
}
}
@@ -985,12 +973,8 @@ void Geocoder::MatchCities(BaseContext & ctx)
void Geocoder::MatchAroundPivot(BaseContext & ctx)
{
- auto const * features = RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RECT_ID_PIVOT);
-
- if (!features)
- return;
-
- ViewportFilter filter(*features, m_preRanker->Limit() /* threshold */);
+ auto const features = RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RECT_ID_PIVOT);
+ ViewportFilter filter(features, m_preRanker->Limit() /* threshold */);
LimitedSearch(ctx, filter);
}
@@ -1007,7 +991,7 @@ void Geocoder::LimitedSearch(BaseContext & ctx, FeaturesFilter const & filter)
MatchUnclassified(ctx, 0 /* curToken */);
- auto search = [this, &ctx]()
+ auto const search = [this, &ctx]()
{
GreedilyMatchStreets(ctx);
MatchPOIsAndBuildings(ctx, 0 /* curToken */);
@@ -1045,7 +1029,7 @@ void Geocoder::WithPostcodes(BaseContext & ctx, TFn && fn)
m_postcodes.Clear();
});
- if (!coding::CompressedBitVector::IsEmpty(postcodes))
+ if (!postcodes.IsEmpty())
{
ScopedMarkTokens mark(ctx.m_usedTokens, startToken, endToken);
@@ -1080,7 +1064,7 @@ void Geocoder::CreateStreetsLayerAndMatchLowerLayers(BaseContext & ctx,
InitLayer(SearchModel::SEARCH_TYPE_STREET, prediction.m_startToken, prediction.m_endToken, layer);
vector<uint32_t> sortedFeatures;
- sortedFeatures.reserve(prediction.m_features->PopCount());
+ sortedFeatures.reserve(prediction.m_features.PopCount());
prediction.m_features.ForEach(MakeBackInsertFunctor(sortedFeatures));
layer.m_sortedFeatures = &sortedFeatures;
@@ -1097,18 +1081,16 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken)
{
// All tokens were consumed, find paths through layers, emit
// features.
- if (m_postcodes.IsEmpty())
+ if (m_postcodes.m_features.IsEmpty())
return FindPaths();
// When there are no layers but user entered a postcode, we have
// to emit all features matching to the postcode.
if (m_layers.size() == 0)
{
- CBVPtr filtered;
- if (m_filter->NeedToFilter(*m_postcodes.m_features))
- filtered.Set(m_filter->Filter(*m_postcodes.m_features));
- else
- filtered.Set(m_postcodes.m_features.get(), false /* isOwner */);
+ CBV filtered = m_postcodes.m_features;
+ if (m_filter->NeedToFilter(m_postcodes.m_features))
+ filtered = m_filter->Filter(m_postcodes.m_features);
filtered.ForEach([&](uint32_t id)
{
EmitResult(m_context->GetId(), id, GetSearchTypeInGeocoding(ctx, id),
@@ -1130,7 +1112,7 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken)
{
for (auto const & id : *m_layers.back().m_sortedFeatures)
{
- if (!m_postcodes.Has(id))
+ if (!m_postcodes.m_features.HasBit(id))
continue;
EmitResult(m_context->GetId(), id, SearchModel::SEARCH_TYPE_STREET,
m_layers.back().m_startToken, m_layers.back().m_endToken);
@@ -1147,8 +1129,7 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken)
layer);
vector<uint32_t> features;
- coding::CompressedBitVectorEnumerator::ForEach(*m_postcodes.m_features,
- MakeBackInsertFunctor(features));
+ m_postcodes.m_features.ForEach(MakeBackInsertFunctor(features));
layer.m_sortedFeatures = &features;
return FindPaths();
}
@@ -1172,12 +1153,12 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken)
// filtered in GreedilyMatchStreets().
if (searchType < kNumClusters)
{
- if (m_postcodes.IsEmpty() || m_postcodes.m_features->GetBit(featureId))
+ if (m_postcodes.m_features.IsEmpty() || m_postcodes.m_features.HasBit(featureId))
clusters[searchType].push_back(featureId);
}
};
- CBVPtr features;
+ CBV features;
features.SetFull();
// Try to consume [curToken, m_numTokens) tokens range.
@@ -1194,15 +1175,11 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken)
InitLayer(layer.m_type, curToken, curToken + n, layer);
}
- features.Intersect(ctx.m_features[curToken + n - 1].get());
- ASSERT(features.Get(), ());
+ features = features.Intersect(ctx.m_features[curToken + n - 1]);
- CBVPtr filtered;
- if (m_filter->NeedToFilter(*features))
- filtered.Set(m_filter->Filter(*features));
- else
- filtered.Set(features.Get(), false /* isOwner */);
- ASSERT(filtered.Get(), ());
+ CBV filtered = features;
+ if (m_filter->NeedToFilter(features))
+ filtered = m_filter->Filter(features);
bool const looksLikeHouseNumber = house_numbers::LooksLikeHouseNumber(
m_layers.back().m_subQuery, m_layers.back().m_lastTokenIsPrefix);
@@ -1218,7 +1195,7 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken)
{
auto noFeature = [&filtered](uint32_t featureId) -> bool
{
- return !filtered->GetBit(featureId);
+ return !filtered.HasBit(featureId);
};
for (auto & cluster : clusters)
my::EraseIf(cluster, noFeature);
@@ -1330,7 +1307,10 @@ void Geocoder::FindPaths()
auto const & innermostLayer = *sortedLayers.front();
- m_matcher->SetPostcodes(m_postcodes.m_features.get());
+ if (!m_postcodes.m_features.IsEmpty())
+ m_matcher->SetPostcodes(&m_postcodes.m_features);
+ else
+ m_matcher->SetPostcodes(nullptr);
m_finder.ForEachReachableVertex(
*m_matcher, sortedLayers, [this, &innermostLayer](IntersectionResult const & result)
{
@@ -1427,21 +1407,18 @@ void Geocoder::MatchUnclassified(BaseContext & ctx, size_t curToken)
if (ctx.NumUnusedTokenGroups() != 1)
return;
- CBVPtr allFeatures;
+ CBV allFeatures;
allFeatures.SetFull();
auto startToken = curToken;
for (curToken = ctx.SkipUsedTokens(curToken);
curToken < ctx.m_numTokens && !ctx.m_usedTokens[curToken]; ++curToken)
{
- allFeatures.Intersect(ctx.m_features[curToken].get());
+ allFeatures = allFeatures.Intersect(ctx.m_features[curToken]);
}
- if (m_filter->NeedToFilter(*allFeatures))
- allFeatures.Set(m_filter->Filter(*allFeatures));
-
- if (allFeatures.IsEmpty())
- return;
+ if (m_filter->NeedToFilter(allFeatures))
+ allFeatures = m_filter->Filter(allFeatures);
auto emitUnclassified = [&](uint32_t featureId)
{
@@ -1452,8 +1429,7 @@ void Geocoder::MatchUnclassified(BaseContext & ctx, size_t curToken)
allFeatures.ForEach(emitUnclassified);
}
-unique_ptr<coding::CompressedBitVector> Geocoder::LoadCategories(
- MwmContext & context, vector<strings::UniString> const & categories)
+CBV Geocoder::LoadCategories(MwmContext & context, vector<strings::UniString> const & categories)
{
ASSERT(context.m_handle.IsAlive(), ());
ASSERT(HasSearchIndex(context.m_value), ());
@@ -1462,75 +1438,69 @@ unique_ptr<coding::CompressedBitVector> Geocoder::LoadCategories(
m_retrievalParams.m_tokens[0].resize(1);
m_retrievalParams.m_prefixTokens.clear();
- vector<unique_ptr<coding::CompressedBitVector>> cbvs;
+ vector<CBV> cbvs;
for_each(categories.begin(), categories.end(), [&](strings::UniString const & category)
{
m_retrievalParams.m_tokens[0][0] = category;
- auto cbv = RetrieveAddressFeatures(context.GetId(), context.m_value, m_cancellable,
- m_retrievalParams);
- if (!coding::CompressedBitVector::IsEmpty(cbv))
+ CBV cbv(RetrieveAddressFeatures(context.GetId(), context.m_value, m_cancellable,
+ m_retrievalParams));
+ if (!cbv.IsEmpty())
cbvs.push_back(move(cbv));
});
UniteCBVs(cbvs);
if (cbvs.empty())
- cbvs.push_back(make_unique<coding::DenseCBV>());
+ cbvs.emplace_back();
return move(cbvs[0]);
}
-coding::CompressedBitVector const * Geocoder::LoadStreets(MwmContext & context)
+CBV Geocoder::LoadStreets(MwmContext & context)
{
if (!context.m_handle.IsAlive() || !HasSearchIndex(context.m_value))
- return nullptr;
+ return CBV();
auto mwmId = context.m_handle.GetId();
auto const it = m_streetsCache.find(mwmId);
if (it != m_streetsCache.cend())
- return it->second.get();
+ return it->second;
auto streets = LoadCategories(context, StreetCategories::Instance().GetCategories());
-
- auto const * result = streets.get();
- m_streetsCache[mwmId] = move(streets);
- return result;
+ m_streetsCache[mwmId] = streets;
+ return streets;
}
-unique_ptr<coding::CompressedBitVector> Geocoder::LoadVillages(MwmContext & context)
+CBV Geocoder::LoadVillages(MwmContext & context)
{
if (!context.m_handle.IsAlive() || !HasSearchIndex(context.m_value))
- return make_unique<coding::DenseCBV>();
+ return CBV();
return LoadCategories(context, GetVillageCategories());
}
-unique_ptr<coding::CompressedBitVector> Geocoder::RetrievePostcodeFeatures(
- MwmContext const & context, TokenSlice const & slice)
+CBV Geocoder::RetrievePostcodeFeatures(MwmContext const & context, TokenSlice const & slice)
{
- return ::search::RetrievePostcodeFeatures(context.GetId(), context.m_value, m_cancellable, slice);
+ return CBV(
+ ::search::RetrievePostcodeFeatures(context.GetId(), context.m_value, m_cancellable, slice));
}
-coding::CompressedBitVector const * Geocoder::RetrieveGeometryFeatures(MwmContext const & context,
- m2::RectD const & rect,
- RectId id)
+CBV Geocoder::RetrieveGeometryFeatures(MwmContext const & context, m2::RectD const & rect,
+ RectId id)
{
switch (id)
{
case RECT_ID_PIVOT: return m_pivotRectsCache.Get(context, rect, m_params.m_scale);
case RECT_ID_LOCALITY: return m_localityRectsCache.Get(context, rect, m_params.m_scale);
- case RECT_ID_COUNT: ASSERT(false, ("Invalid RectId.")); return nullptr;
+ case RECT_ID_COUNT: ASSERT(false, ("Invalid RectId.")); return CBV();
}
}
SearchModel::SearchType Geocoder::GetSearchTypeInGeocoding(BaseContext const & ctx,
uint32_t featureId)
{
- ASSERT(ctx.m_streets, ());
- ASSERT(ctx.m_villages, ());
-
- if (ctx.m_streets->GetBit(featureId))
+ if (ctx.m_streets.HasBit(featureId))
return SearchModel::SEARCH_TYPE_STREET;
- if (ctx.m_villages->GetBit(featureId))
+ if (ctx.m_villages.HasBit(featureId))
return SearchModel::SEARCH_TYPE_VILLAGE;
FeatureType feature;
@@ -1545,5 +1515,4 @@ string DebugPrint(Geocoder::Locality const & locality)
<< ", startToken=" << locality.m_startToken << ", endToken=" << locality.m_endToken << "]";
return os.str();
}
-
} // namespace search
diff --git a/search/geocoder.hpp b/search/geocoder.hpp
index 876f5b762b..1afd6798e7 100644
--- a/search/geocoder.hpp
+++ b/search/geocoder.hpp
@@ -172,16 +172,12 @@ private:
{
m_startToken = 0;
m_endToken = 0;
- m_features.reset();
+ m_features.Reset();
}
- inline bool Has(uint64_t id) const { return m_features->GetBit(id); }
-
- inline bool IsEmpty() const { return coding::CompressedBitVector::IsEmpty(m_features); }
-
size_t m_startToken = 0;
size_t m_endToken = 0;
- unique_ptr<coding::CompressedBitVector> m_features;
+ CBV m_features;
};
void GoImpl(PreRanker & preRanker, vector<shared_ptr<MwmInfo>> & infos, bool inViewport);
@@ -202,7 +198,7 @@ private:
void InitLayer(SearchModel::SearchType type, size_t startToken, size_t endToken,
FeaturesLayer & layer);
- void FillLocalityCandidates(BaseContext const & ctx, coding::CompressedBitVector const * filter,
+ void FillLocalityCandidates(BaseContext const & ctx, CBV const & filter,
size_t const maxNumLocalities, vector<Locality> & preLocalities);
void FillLocalitiesTable(BaseContext const & ctx);
@@ -272,20 +268,17 @@ private:
// UNCLASSIFIED objects that match to all currently unused tokens.
void MatchUnclassified(BaseContext & ctx, size_t curToken);
- unique_ptr<coding::CompressedBitVector> LoadCategories(
- MwmContext & context, vector<strings::UniString> const & categories);
+ CBV LoadCategories(MwmContext & context, vector<strings::UniString> const & categories);
- coding::CompressedBitVector const * LoadStreets(MwmContext & context);
+ CBV LoadStreets(MwmContext & context);
- unique_ptr<coding::CompressedBitVector> LoadVillages(MwmContext & context);
+ CBV LoadVillages(MwmContext & context);
// A wrapper around RetrievePostcodeFeatures.
- unique_ptr<coding::CompressedBitVector> RetrievePostcodeFeatures(MwmContext const & context,
- TokenSlice const & slice);
+ CBV RetrievePostcodeFeatures(MwmContext const & context, TokenSlice const & slice);
// A caching wrapper around Retrieval::RetrieveGeometryFeatures.
- coding::CompressedBitVector const * RetrieveGeometryFeatures(MwmContext const & context,
- m2::RectD const & rect, RectId id);
+ CBV RetrieveGeometryFeatures(MwmContext const & context, m2::RectD const & rect, RectId id);
// This is a faster wrapper around SearchModel::GetSearchType(), as
// it uses pre-loaded lists of streets and villages.
@@ -327,7 +320,7 @@ private:
NestedRectsCache m_pivotFeatures;
// Cache of street ids in mwms.
- map<MwmSet::MwmId, unique_ptr<coding::CompressedBitVector>> m_streetsCache;
+ map<MwmSet::MwmId, CBV> m_streetsCache;
// Postcodes features in the mwm that is currently being processed.
Postcodes m_postcodes;
diff --git a/search/geocoder_context.hpp b/search/geocoder_context.hpp
index ab43007047..3954416af6 100644
--- a/search/geocoder_context.hpp
+++ b/search/geocoder_context.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "coding/compressed_bit_vector.hpp"
+#include "search/cbv.hpp"
#include "std/unique_ptr.hpp"
#include "std/vector.hpp"
@@ -25,14 +25,15 @@ struct BaseContext
// Counts number of groups of consecutive unused tokens.
size_t NumUnusedTokenGroups() const;
- vector<unique_ptr<coding::CompressedBitVector>> m_features;
- unique_ptr<coding::CompressedBitVector> m_villages;
- coding::CompressedBitVector const * m_streets = nullptr;
+ vector<CBV> m_features;
+ CBV m_villages;
+ CBV m_streets;
- // This vector is used to indicate what tokens were matched by
- // locality and can't be re-used during the geocoding process.
+ // This vector is used to indicate what tokens were already matched
+ // and can't be re-used during the geocoding process.
vector<bool> m_usedTokens;
+ // Number of tokens in the query.
size_t m_numTokens = 0;
};
} // namespace search
diff --git a/search/geometry_cache.cpp b/search/geometry_cache.cpp
index 275c2ff875..990cae77cd 100644
--- a/search/geometry_cache.cpp
+++ b/search/geometry_cache.cpp
@@ -35,8 +35,7 @@ PivotRectsCache::PivotRectsCache(size_t maxNumEntries, my::Cancellable const & c
{
}
-coding::CompressedBitVector const * PivotRectsCache::Get(MwmContext const & context,
- m2::RectD const & rect, int scale)
+CBV PivotRectsCache::Get(MwmContext const & context, m2::RectD const & rect, int scale)
{
auto p = FindOrCreateEntry(
context.GetId(), [&rect, &scale](Entry const & entry)
@@ -53,7 +52,7 @@ coding::CompressedBitVector const * PivotRectsCache::Get(MwmContext const & cont
normRect = rect;
InitEntry(context, normRect, scale, entry);
}
- return entry.m_cbv.get();
+ return entry.m_cbv;
}
// LocalityRectsCache ------------------------------------------------------------------------------
@@ -62,8 +61,7 @@ LocalityRectsCache::LocalityRectsCache(size_t maxNumEntries, my::Cancellable con
{
}
-coding::CompressedBitVector const * LocalityRectsCache::Get(MwmContext const & context,
- m2::RectD const & rect, int scale)
+CBV LocalityRectsCache::Get(MwmContext const & context, m2::RectD const & rect, int scale)
{
auto p = FindOrCreateEntry(context.GetId(), [&rect, &scale](Entry const & entry)
{
@@ -73,7 +71,7 @@ coding::CompressedBitVector const * LocalityRectsCache::Get(MwmContext const & c
auto & entry = p.first;
if (p.second)
InitEntry(context, rect, scale, entry);
- return entry.m_cbv.get();
+ return entry.m_cbv;
}
} // namespace search
diff --git a/search/geometry_cache.hpp b/search/geometry_cache.hpp
index d5d305301b..2b36707cc2 100644
--- a/search/geometry_cache.hpp
+++ b/search/geometry_cache.hpp
@@ -1,8 +1,8 @@
#pragma once
-#include "indexer/mwm_set.hpp"
+#include "search/cbv.hpp"
-#include "coding/compressed_bit_vector.hpp"
+#include "indexer/mwm_set.hpp"
#include "geometry/rect2d.hpp"
@@ -35,8 +35,7 @@ public:
// Returns (hopefully, cached) list of features in a given
// rect. Note that return value may be invalidated on next calls to
// this method.
- virtual coding::CompressedBitVector const * Get(MwmContext const & context,
- m2::RectD const & rect, int scale) = 0;
+ virtual CBV Get(MwmContext const & context, m2::RectD const & rect, int scale) = 0;
inline void Clear() { m_entries.clear(); }
@@ -44,7 +43,7 @@ protected:
struct Entry
{
m2::RectD m_rect;
- unique_ptr<coding::CompressedBitVector> m_cbv;
+ CBV m_cbv;
int m_scale = 0;
};
@@ -87,8 +86,7 @@ public:
double maxRadiusMeters);
// GeometryCache overrides:
- coding::CompressedBitVector const * Get(MwmContext const & context, m2::RectD const & rect,
- int scale) override;
+ CBV Get(MwmContext const & context, m2::RectD const & rect, int scale) override;
private:
double const m_maxRadiusMeters;
@@ -100,8 +98,7 @@ public:
LocalityRectsCache(size_t maxNumEntries, my::Cancellable const & cancellable);
// GeometryCache overrides:
- coding::CompressedBitVector const * Get(MwmContext const & context, m2::RectD const & rect,
- int scale) override;
+ CBV Get(MwmContext const & context, m2::RectD const & rect, int scale) override;
};
} // namespace search
diff --git a/search/search.pro b/search/search.pro
index 5ddaf35a28..2f5b17318c 100644
--- a/search/search.pro
+++ b/search/search.pro
@@ -12,7 +12,7 @@ HEADERS += \
algos.hpp \
approximate_string_match.hpp \
cancel_exception.hpp \
- cbv_ptr.hpp \
+ cbv.hpp \
common.hpp \
dummy_rank_table.hpp \
engine.hpp \
@@ -69,7 +69,7 @@ HEADERS += \
SOURCES += \
approximate_string_match.cpp \
- cbv_ptr.cpp \
+ cbv.cpp \
dummy_rank_table.cpp \
engine.cpp \
features_filter.cpp \
diff --git a/search/streets_matcher.cpp b/search/streets_matcher.cpp
index 7d8125437c..dfd524f327 100644
--- a/search/streets_matcher.cpp
+++ b/search/streets_matcher.cpp
@@ -31,7 +31,7 @@ bool LessByHash(StreetsMatcher::Prediction const & lhs, StreetsMatcher::Predicti
void StreetsMatcher::Go(BaseContext const & ctx, FeaturesFilter const & filter,
QueryParams const & params, vector<Prediction> & predictions)
{
- size_t const kMaxNumPredictions = 3;
+ size_t const kMaxNumOfImprobablePredictions = 3;
double const kTailProbability = 0.05;
predictions.clear();
@@ -46,8 +46,11 @@ void StreetsMatcher::Go(BaseContext const & ctx, FeaturesFilter const & filter,
predictions.end());
sort(predictions.rbegin(), predictions.rend(), my::LessBy(&Prediction::m_prob));
- while (predictions.size() > kMaxNumPredictions && predictions.back().m_prob < kTailProbability)
+ while (predictions.size() > kMaxNumOfImprobablePredictions &&
+ predictions.back().m_prob < kTailProbability)
+ {
predictions.pop_back();
+ }
}
// static
@@ -65,9 +68,9 @@ void StreetsMatcher::FindStreets(BaseContext const & ctx, FeaturesFilter const &
// each time a token that looks like a beginning of a house number
// is met, we try to use current intersection of tokens as a
// street layer and try to match BUILDINGs or POIs.
- CBVPtr streets(ctx.m_streets, false /* isOwner */);
+ CBV streets(ctx.m_streets);
- CBVPtr all;
+ CBV all;
all.SetFull();
size_t curToken = startToken;
@@ -88,23 +91,20 @@ void StreetsMatcher::FindStreets(BaseContext const & ctx, FeaturesFilter const &
{
if (!streets.IsEmpty() && !emptyIntersection && !incomplete && lastToken != curToken)
{
- CBVPtr fs(streets.Get(), false /* isOwner */);
- CBVPtr fa(all.Get(), false /* isOwner */);
+ CBV fs(streets);
+ CBV fa(all);
ASSERT(!fs.IsFull(), ());
ASSERT(!fa.IsFull(), ());
- if (filter.NeedToFilter(*fs))
- fs.Set(filter.Filter(*fs));
+ if (filter.NeedToFilter(fs))
+ fs = filter.Filter(fs);
if (fs.IsEmpty())
return;
- if (filter.NeedToFilter(*fa))
- {
- fa.Set(filter.Filter(*fa));
- fa.Union(fs.Get());
- }
+ if (filter.NeedToFilter(fa))
+ fa = filter.Filter(fa).Union(fs);
predictions.emplace_back();
auto & prediction = predictions.back();
@@ -112,31 +112,26 @@ void StreetsMatcher::FindStreets(BaseContext const & ctx, FeaturesFilter const &
prediction.m_startToken = startToken;
prediction.m_endToken = curToken;
- ASSERT_LESS_OR_EQUAL(fs->PopCount(), fa->PopCount(), ());
- prediction.m_prob =
- static_cast<double>(fs->PopCount()) / static_cast<double>(fa->PopCount());
-
- if (fs.IsOwner())
- prediction.m_features = move(fs);
- else
- fs.CopyTo(prediction.m_features);
+ ASSERT_NOT_EQUAL(fs.PopCount(), 0, ());
+ ASSERT_LESS_OR_EQUAL(fs.PopCount(), fa.PopCount(), ());
+ prediction.m_prob = static_cast<double>(fs.PopCount()) / static_cast<double>(fa.PopCount());
- prediction.m_hash = coding::CompressedBitVectorHasher::Hash(*prediction.m_features);
+ prediction.m_features = move(fs);
+ prediction.m_hash = prediction.m_features.Hash();
}
};
StreetTokensFilter filter([&](strings::UniString const & /* token */, size_t tag)
{
- auto buffer = coding::CompressedBitVector::Intersect(
- *streets, *ctx.m_features[tag]);
+ auto buffer = streets.Intersect(ctx.m_features[tag]);
if (tag < curToken)
{
// This is the case for delayed
// street synonym. Therefore,
// |streets| is temporarily in the
// incomplete state.
- streets.Set(move(buffer));
- all.Intersect(ctx.m_features[tag].get());
+ streets = buffer;
+ all = all.Intersect(ctx.m_features[tag]);
emptyIntersection = false;
incomplete = true;
@@ -147,11 +142,11 @@ void StreetsMatcher::FindStreets(BaseContext const & ctx, FeaturesFilter const &
// |streets| will become empty after
// the intersection. Therefore we need
// to create streets layer right now.
- if (coding::CompressedBitVector::IsEmpty(buffer))
+ if (buffer.IsEmpty())
emit();
- streets.Set(move(buffer));
- all.Intersect(ctx.m_features[tag].get());
+ streets = buffer;
+ all = all.Intersect(ctx.m_features[tag]);
emptyIntersection = false;
incomplete = false;
});
diff --git a/search/streets_matcher.hpp b/search/streets_matcher.hpp
index 43062db676..7918380774 100644
--- a/search/streets_matcher.hpp
+++ b/search/streets_matcher.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "search/cbv_ptr.hpp"
+#include "search/cbv.hpp"
#include "search/geocoder_context.hpp"
#include "std/vector.hpp"
@@ -17,7 +17,7 @@ public:
{
inline size_t GetNumTokens() const { return m_endToken - m_startToken; }
- CBVPtr m_features;
+ CBV m_features;
size_t m_startToken = 0;
size_t m_endToken = 0;