summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval/src/vespa/eval/tensor/sparse/CMakeLists.txt1
-rw-r--r--eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.cpp62
-rw-r--r--eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h54
-rw-r--r--eval/src/vespa/eval/tensor/sparse/sparse_tensor.cpp3
-rw-r--r--eval/src/vespa/eval/tensor/sparse/sparse_tensor.h2
-rw-r--r--searchlib/src/vespa/searchlib/features/fieldlengthfeature.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/features/matchcountfeature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/features/matchesfeature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/features/nativeattributematchfeature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/features/nativefieldmatchfeature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/features/nativeproximityfeature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/features/nativerankfeature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/features/queryfeature.cpp5
-rw-r--r--searchlib/src/vespa/searchlib/features/querytermcountfeature.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/features/terminfofeature.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/features/valuefeature.cpp15
-rw-r--r--searchlib/src/vespa/searchlib/features/valuefeature.h15
-rw-r--r--searchlib/src/vespa/searchlib/fef/properties.h7
-rw-r--r--searchlib/src/vespa/searchlib/fef/rank_program.cpp3
-rw-r--r--searchlib/src/vespa/searchlib/fef/rank_program.h5
-rw-r--r--vespalib/src/tests/stllike/hash_test.cpp3
-rw-r--r--vespalib/src/vespa/vespalib/stllike/hash_map.hpp7
-rw-r--r--vespalib/src/vespa/vespalib/stllike/hash_set.h1
23 files changed, 127 insertions, 80 deletions
diff --git a/eval/src/vespa/eval/tensor/sparse/CMakeLists.txt b/eval/src/vespa/eval/tensor/sparse/CMakeLists.txt
index 8e1d18a87b7..a25d2abb477 100644
--- a/eval/src/vespa/eval/tensor/sparse/CMakeLists.txt
+++ b/eval/src/vespa/eval/tensor/sparse/CMakeLists.txt
@@ -1,6 +1,7 @@
# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(eval_tensor_sparse OBJECT
SOURCES
+ direct_sparse_tensor_builder.cpp
sparse_tensor.cpp
sparse_tensor_add.cpp
sparse_tensor_address_builder.cpp
diff --git a/eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.cpp b/eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.cpp
new file mode 100644
index 00000000000..4a28b54d201
--- /dev/null
+++ b/eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.cpp
@@ -0,0 +1,62 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "direct_sparse_tensor_builder.h"
+
+namespace vespalib::tensor {
+
+void
+DirectSparseTensorBuilder::copyCells(const Cells &cells_in)
+{
+ for (const auto &cell : cells_in) {
+ SparseTensorAddressRef oldRef = cell.first;
+ SparseTensorAddressRef newRef(oldRef, _stash);
+ _cells[newRef] = cell.second;
+ }
+}
+
+DirectSparseTensorBuilder::DirectSparseTensorBuilder()
+ : _stash(SparseTensor::STASH_CHUNK_SIZE),
+ _type(eval::ValueType::double_type()),
+ _cells()
+{
+}
+
+DirectSparseTensorBuilder::DirectSparseTensorBuilder(const eval::ValueType &type_in)
+ : _stash(SparseTensor::STASH_CHUNK_SIZE),
+ _type(type_in),
+ _cells()
+{
+}
+
+DirectSparseTensorBuilder::DirectSparseTensorBuilder(const eval::ValueType &type_in, const Cells &cells_in)
+ : _stash(SparseTensor::STASH_CHUNK_SIZE),
+ _type(type_in),
+ _cells()
+{
+ copyCells(cells_in);
+}
+
+DirectSparseTensorBuilder::~DirectSparseTensorBuilder() = default;
+
+Tensor::UP
+DirectSparseTensorBuilder::build() {
+ return std::make_unique<SparseTensor>(std::move(_type), std::move(_cells), std::move(_stash));
+}
+
+void
+DirectSparseTensorBuilder::insertCell(SparseTensorAddressRef address, double value) {
+ // This address should not already exist and a new cell should be inserted.
+ insertCell(address, value, [](double, double) -> double { HDR_ABORT("should not be reached"); });
+}
+
+void
+DirectSparseTensorBuilder::insertCell(SparseTensorAddressBuilder &address, double value) {
+ // This address should not already exist and a new cell should be inserted.
+ insertCell(address.getAddressRef(), value, [](double, double) -> double { HDR_ABORT("should not be reached"); });
+}
+
+void DirectSparseTensorBuilder::reserve(uint32_t estimatedCells) {
+ _cells.resize(estimatedCells*2);
+}
+
+} \ No newline at end of file
diff --git a/eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h b/eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h
index d54c8810a81..f9182a199be 100644
--- a/eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h
+++ b/eval/src/vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h
@@ -25,43 +25,13 @@ private:
Cells _cells;
public:
- void
- copyCells(const Cells &cells_in)
- {
- for (const auto &cell : cells_in) {
- SparseTensorAddressRef oldRef = cell.first;
- SparseTensorAddressRef newRef(oldRef, _stash);
- _cells[newRef] = cell.second;
- }
- }
-
- DirectSparseTensorBuilder()
- : _stash(SparseTensor::STASH_CHUNK_SIZE),
- _type(eval::ValueType::double_type()),
- _cells()
- {
- }
-
- DirectSparseTensorBuilder(const eval::ValueType &type_in)
- : _stash(SparseTensor::STASH_CHUNK_SIZE),
- _type(type_in),
- _cells()
- {
- }
-
- DirectSparseTensorBuilder(const eval::ValueType &type_in, const Cells &cells_in)
- : _stash(SparseTensor::STASH_CHUNK_SIZE),
- _type(type_in),
- _cells()
- {
- copyCells(cells_in);
- }
+ void copyCells(const Cells &cells_in);
+ DirectSparseTensorBuilder();
+ DirectSparseTensorBuilder(const eval::ValueType &type_in);
+ DirectSparseTensorBuilder(const eval::ValueType &type_in, const Cells &cells_in);
+ ~DirectSparseTensorBuilder();
- ~DirectSparseTensorBuilder() {};
-
- Tensor::UP build() {
- return std::make_unique<SparseTensor>(std::move(_type), std::move(_cells), std::move(_stash));
- }
+ Tensor::UP build();
template <class Function>
void insertCell(SparseTensorAddressRef address, double value, Function &&func)
@@ -75,10 +45,7 @@ public:
}
}
- void insertCell(SparseTensorAddressRef address, double value) {
- // This address should not already exist and a new cell should be inserted.
- insertCell(address, value, [](double, double) -> double { HDR_ABORT("should not be reached"); });
- }
+ void insertCell(SparseTensorAddressRef address, double value);
template <class Function>
void insertCell(SparseTensorAddressBuilder &address, double value, Function &&func)
@@ -86,14 +53,11 @@ public:
insertCell(address.getAddressRef(), value, func);
}
- void insertCell(SparseTensorAddressBuilder &address, double value) {
- // This address should not already exist and a new cell should be inserted.
- insertCell(address.getAddressRef(), value, [](double, double) -> double { HDR_ABORT("should not be reached"); });
- }
+ void insertCell(SparseTensorAddressBuilder &address, double value);
eval::ValueType &fast_type() { return _type; }
Cells &cells() { return _cells; }
- void reserve(uint32_t estimatedCells) { _cells.resize(estimatedCells*2); }
+ void reserve(uint32_t estimatedCells);
};
}
diff --git a/eval/src/vespa/eval/tensor/sparse/sparse_tensor.cpp b/eval/src/vespa/eval/tensor/sparse/sparse_tensor.cpp
index 1fc93e8234f..d183c33f5cd 100644
--- a/eval/src/vespa/eval/tensor/sparse/sparse_tensor.cpp
+++ b/eval/src/vespa/eval/tensor/sparse/sparse_tensor.cpp
@@ -245,5 +245,4 @@ SparseTensor::remove(const CellValues &cellAddresses) const
}
-VESPALIB_HASH_MAP_INSTANTIATE_H_E_M(vespalib::tensor::SparseTensorAddressRef, double, vespalib::hash<vespalib::tensor::SparseTensorAddressRef>,
- std::equal_to<vespalib::tensor::SparseTensorAddressRef>, vespalib::hashtable_base::and_modulator);
+VESPALIB_HASH_MAP_INSTANTIATE(vespalib::tensor::SparseTensorAddressRef, double);
diff --git a/eval/src/vespa/eval/tensor/sparse/sparse_tensor.h b/eval/src/vespa/eval/tensor/sparse/sparse_tensor.h
index 880cd32c605..e5ea639b460 100644
--- a/eval/src/vespa/eval/tensor/sparse/sparse_tensor.h
+++ b/eval/src/vespa/eval/tensor/sparse/sparse_tensor.h
@@ -22,7 +22,7 @@ class SparseTensor : public Tensor
{
public:
using Cells = hash_map<SparseTensorAddressRef, double, hash<SparseTensorAddressRef>,
- std::equal_to<SparseTensorAddressRef>, hashtable_base::and_modulator>;
+ std::equal_to<>, hashtable_base::and_modulator>;
static constexpr size_t STASH_CHUNK_SIZE = 16384u;
diff --git a/searchlib/src/vespa/searchlib/features/fieldlengthfeature.cpp b/searchlib/src/vespa/searchlib/features/fieldlengthfeature.cpp
index 74bfa156b5f..0cbcf62de6b 100644
--- a/searchlib/src/vespa/searchlib/features/fieldlengthfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/fieldlengthfeature.cpp
@@ -92,9 +92,7 @@ FeatureExecutor &
FieldLengthBlueprint::createExecutor(const IQueryEnvironment &env, vespalib::Stash &stash) const
{
if (_field == 0) {
- std::vector<feature_t> values;
- values.push_back(fef::FieldPositionsIterator::UNKNOWN_LENGTH);
- return stash.create<ValueExecutor>(values);
+ return stash.create<SingleValueExecutor>(fef::FieldPositionsIterator::UNKNOWN_LENGTH);
}
return stash.create<FieldLengthExecutor>(env, _field->id());
}
diff --git a/searchlib/src/vespa/searchlib/features/matchcountfeature.cpp b/searchlib/src/vespa/searchlib/features/matchcountfeature.cpp
index c061ace4854..f19e32793a1 100644
--- a/searchlib/src/vespa/searchlib/features/matchcountfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/matchcountfeature.cpp
@@ -70,7 +70,7 @@ FeatureExecutor &
MatchCountBlueprint::createExecutor(const IQueryEnvironment & queryEnv, vespalib::Stash &stash) const
{
if (_field == nullptr) {
- return stash.create<ValueExecutor>(std::vector<feature_t>(1, 0.0));
+ return stash.create<SingleZeroValueExecutor>();
}
return stash.create<MatchCountExecutor>(_field->id(), queryEnv);
}
diff --git a/searchlib/src/vespa/searchlib/features/matchesfeature.cpp b/searchlib/src/vespa/searchlib/features/matchesfeature.cpp
index a99c2330ee3..8d72978adf7 100644
--- a/searchlib/src/vespa/searchlib/features/matchesfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/matchesfeature.cpp
@@ -81,7 +81,7 @@ FeatureExecutor &
MatchesBlueprint::createExecutor(const IQueryEnvironment & queryEnv, vespalib::Stash &stash) const
{
if (_field == 0) {
- return stash.create<ValueExecutor>(std::vector<feature_t>(1, 0.0));
+ return stash.create<SingleZeroValueExecutor>();
}
if (_termIdx != std::numeric_limits<uint32_t>::max()) {
return stash.create<MatchesExecutor>(_field->id(), queryEnv, _termIdx, _termIdx + 1);
diff --git a/searchlib/src/vespa/searchlib/features/nativeattributematchfeature.cpp b/searchlib/src/vespa/searchlib/features/nativeattributematchfeature.cpp
index 865ea9fc3c4..ab8544634b5 100644
--- a/searchlib/src/vespa/searchlib/features/nativeattributematchfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/nativeattributematchfeature.cpp
@@ -51,7 +51,7 @@ NativeAttributeMatchExecutor::createExecutor(const IQueryEnvironment & env,
{
Precomputed setup = preComputeSetup(env, params);
if (setup.first.size() == 0) {
- return stash.create<ValueExecutor>(std::vector<feature_t>(1, 0.0));
+ return stash.create<SingleZeroValueExecutor>();
} else if (setup.first.size() == 1) {
return stash.create<NativeAttributeMatchExecutorSingle>(setup);
} else {
diff --git a/searchlib/src/vespa/searchlib/features/nativefieldmatchfeature.cpp b/searchlib/src/vespa/searchlib/features/nativefieldmatchfeature.cpp
index 2b6841750ad..2cdda669dd7 100644
--- a/searchlib/src/vespa/searchlib/features/nativefieldmatchfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/nativefieldmatchfeature.cpp
@@ -173,7 +173,7 @@ NativeFieldMatchBlueprint::createExecutor(const IQueryEnvironment &env, vespalib
{
NativeFieldMatchExecutor &native = stash.create<NativeFieldMatchExecutor>(env, _params);
if (native.empty()) {
- return stash.create<ValueExecutor>(std::vector<feature_t>(1, 0.0));
+ return stash.create<SingleZeroValueExecutor>();
} else {
return native;
}
diff --git a/searchlib/src/vespa/searchlib/features/nativeproximityfeature.cpp b/searchlib/src/vespa/searchlib/features/nativeproximityfeature.cpp
index 2809417e382..4da819b4dd3 100644
--- a/searchlib/src/vespa/searchlib/features/nativeproximityfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/nativeproximityfeature.cpp
@@ -208,7 +208,7 @@ NativeProximityBlueprint::createExecutor(const IQueryEnvironment &env, vespalib:
{
NativeProximityExecutor &native = stash.create<NativeProximityExecutor>(env, _params);
if (native.empty()) {
- return stash.create<ValueExecutor>(std::vector<feature_t>(1, 0.0));
+ return stash.create<SingleZeroValueExecutor>();
} else {
return native;
}
diff --git a/searchlib/src/vespa/searchlib/features/nativerankfeature.cpp b/searchlib/src/vespa/searchlib/features/nativerankfeature.cpp
index a980c265484..07f1dfb9d15 100644
--- a/searchlib/src/vespa/searchlib/features/nativerankfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/nativerankfeature.cpp
@@ -157,7 +157,7 @@ NativeRankBlueprint::createExecutor(const IQueryEnvironment &, vespalib::Stash &
if (_params.proximityWeight + _params.fieldMatchWeight + _params.attributeMatchWeight > 0) {
return stash.create<NativeRankExecutor>(_params);
} else {
- return stash.create<ValueExecutor>(std::vector<feature_t>(1, 0.0));
+ return stash.create<SingleZeroValueExecutor>();
}
}
diff --git a/searchlib/src/vespa/searchlib/features/queryfeature.cpp b/searchlib/src/vespa/searchlib/features/queryfeature.cpp
index b927188c1aa..12cad613a80 100644
--- a/searchlib/src/vespa/searchlib/features/queryfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/queryfeature.cpp
@@ -146,11 +146,10 @@ QueryBlueprint::createExecutor(const IQueryEnvironment &env, vespalib::Stash &st
p = env.getProperties().lookup(_key2);
}
if (p.found()) {
- values.push_back(asFeature(p.get()));
+ return stash.create<SingleValueExecutor>(asFeature(p.get()));
} else {
- values.push_back(_defaultValue);
+ return stash.create<SingleValueExecutor>(_defaultValue);
}
- return stash.create<ValueExecutor>(values);
}
}
diff --git a/searchlib/src/vespa/searchlib/features/querytermcountfeature.cpp b/searchlib/src/vespa/searchlib/features/querytermcountfeature.cpp
index cbaf9e97cb6..741501d3b6d 100644
--- a/searchlib/src/vespa/searchlib/features/querytermcountfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/querytermcountfeature.cpp
@@ -43,9 +43,7 @@ QueryTermCountBlueprint::setup(const IIndexEnvironment &,
FeatureExecutor &
QueryTermCountBlueprint::createExecutor(const IQueryEnvironment &env, vespalib::Stash &stash) const
{
- std::vector<feature_t> values;
- values.push_back(static_cast<feature_t>(env.getNumTerms()));
- return stash.create<ValueExecutor>(values);
+ return stash.create<SingleValueExecutor>(env.getNumTerms());
}
}
diff --git a/searchlib/src/vespa/searchlib/features/terminfofeature.cpp b/searchlib/src/vespa/searchlib/features/terminfofeature.cpp
index ca7a5d8e248..b61021c4aa2 100644
--- a/searchlib/src/vespa/searchlib/features/terminfofeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/terminfofeature.cpp
@@ -39,9 +39,7 @@ TermInfoBlueprint::createExecutor(const IQueryEnvironment &queryEnv, vespalib::S
if (queryEnv.getNumTerms() > _termIdx) {
queryIdx = _termIdx;
}
- std::vector<feature_t> values;
- values.push_back(queryIdx);
- return stash.create<ValueExecutor>(values);
+ return stash.create<SingleValueExecutor>(queryIdx);
}
}
diff --git a/searchlib/src/vespa/searchlib/features/valuefeature.cpp b/searchlib/src/vespa/searchlib/features/valuefeature.cpp
index 2b91cf1688b..64f2ba862e2 100644
--- a/searchlib/src/vespa/searchlib/features/valuefeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/valuefeature.cpp
@@ -22,6 +22,12 @@ ValueExecutor::execute(uint32_t)
}
void
+SingleValueExecutor::execute(uint32_t)
+{
+ outputs().set_number(0, _value);
+}
+
+void
SingleZeroValueExecutor::execute(uint32_t)
{
outputs().set_number(0, 0.0);
@@ -56,10 +62,13 @@ ValueBlueprint::setup(const IIndexEnvironment &, const ParameterList & params)
}
FeatureExecutor &
-ValueBlueprint::createExecutor(const IQueryEnvironment &queryEnv, vespalib::Stash &stash) const
+ValueBlueprint::createExecutor(const IQueryEnvironment &, vespalib::Stash &stash) const
{
- (void) queryEnv;
- return stash.create<ValueExecutor>(_values);
+ if (_values.size() == 1) {
+ return stash.create<SingleValueExecutor>(_values[0]);
+ } else {
+ return stash.create<ValueExecutor>(_values);
+ }
}
diff --git a/searchlib/src/vespa/searchlib/features/valuefeature.h b/searchlib/src/vespa/searchlib/features/valuefeature.h
index 1cc6bd55bc1..d8e2ab70d0b 100644
--- a/searchlib/src/vespa/searchlib/features/valuefeature.h
+++ b/searchlib/src/vespa/searchlib/features/valuefeature.h
@@ -7,7 +7,7 @@
namespace search::features {
-class ValueExecutor : public fef::FeatureExecutor
+class ValueExecutor final : public fef::FeatureExecutor
{
private:
std::vector<feature_t> _values;
@@ -19,7 +19,18 @@ public:
const std::vector<feature_t> & getValues() const { return _values; }
};
-class SingleZeroValueExecutor : public fef::FeatureExecutor
+class SingleValueExecutor final : public fef::FeatureExecutor
+{
+private:
+ feature_t _value;
+
+public:
+ SingleValueExecutor(feature_t value) : _value(value) { }
+ bool isPure() override { return true; }
+ void execute(uint32_t docId) override;
+};
+
+class SingleZeroValueExecutor final : public fef::FeatureExecutor
{
public:
SingleZeroValueExecutor() : FeatureExecutor() {}
diff --git a/searchlib/src/vespa/searchlib/fef/properties.h b/searchlib/src/vespa/searchlib/fef/properties.h
index 1cbc0ba9064..377926509bd 100644
--- a/searchlib/src/vespa/searchlib/fef/properties.h
+++ b/searchlib/src/vespa/searchlib/fef/properties.h
@@ -129,9 +129,10 @@ public:
class Properties
{
private:
- typedef vespalib::string Key;
- typedef Property::Values Value;
- typedef vespalib::hash_map<Key, Value> Map;
+ using Key = vespalib::string;
+ using Value = Property::Values;
+ using Map = vespalib::hash_map<Key, Value, vespalib::hash<Key>,
+ std::equal_to<>, vespalib::hashtable_base::and_modulator>;
uint32_t _numValues;
Map _data;
diff --git a/searchlib/src/vespa/searchlib/fef/rank_program.cpp b/searchlib/src/vespa/searchlib/fef/rank_program.cpp
index 48a9c7be147..0bc85a63ceb 100644
--- a/searchlib/src/vespa/searchlib/fef/rank_program.cpp
+++ b/searchlib/src/vespa/searchlib/fef/rank_program.cpp
@@ -3,6 +3,7 @@
#include "rank_program.h"
#include "featureoverrider.h"
#include <vespa/vespalib/locale/c.h>
+#include <vespa/vespalib/stllike/hash_set.hpp>
#include <algorithm>
#include <cassert>
@@ -14,7 +15,6 @@ using vespalib::Stash;
namespace search::fef {
using MappedValues = std::map<const NumberOrObject *, LazyValue>;
-using ValueSet = std::set<const NumberOrObject *>;
namespace {
@@ -179,6 +179,7 @@ RankProgram::setup(const MatchData &md,
const auto &specs = _resolver->getExecutorSpecs();
_executors.reserve(specs.size());
+ _is_const.resize(specs.size()*2); // Reserve space in hashmap for executors to be const
for (uint32_t i = 0; i < specs.size(); ++i) {
vespalib::ArrayRef<NumberOrObject> outputs = _hot_stash.create_array<NumberOrObject>(specs[i].output_types.size());
StashSelector stash(_hot_stash, _cold_stash);
diff --git a/searchlib/src/vespa/searchlib/fef/rank_program.h b/searchlib/src/vespa/searchlib/fef/rank_program.h
index aa6f77abce4..15b7912bfb1 100644
--- a/searchlib/src/vespa/searchlib/fef/rank_program.h
+++ b/searchlib/src/vespa/searchlib/fef/rank_program.h
@@ -10,7 +10,7 @@
#include <vespa/vespalib/stllike/string.h>
#include <vespa/vespalib/util/array.h>
#include <vespa/vespalib/util/stash.h>
-#include <set>
+#include <vespa/vespalib/stllike/hash_set.h>
namespace search::fef {
@@ -31,7 +31,8 @@ private:
RankProgram &operator=(const RankProgram &) = delete;
using MappedValues = std::map<const NumberOrObject *, LazyValue>;
- using ValueSet = std::set<const NumberOrObject *>;
+ using ValueSet = vespalib::hash_set<const NumberOrObject *, vespalib::hash<const NumberOrObject *>,
+ std::equal_to<>, vespalib::hashtable_base::and_modulator>;
BlueprintResolver::SP _resolver;
vespalib::Stash _hot_stash;
diff --git a/vespalib/src/tests/stllike/hash_test.cpp b/vespalib/src/tests/stllike/hash_test.cpp
index 017a16ee7b6..b39b6859623 100644
--- a/vespalib/src/tests/stllike/hash_test.cpp
+++ b/vespalib/src/tests/stllike/hash_test.cpp
@@ -356,6 +356,9 @@ TEST("test hash set find")
EXPECT_TRUE(*set.find(S(1)) == S(1));
auto cit = set.find<uint32_t>(7);
EXPECT_TRUE(*cit == S(7));
+
+ EXPECT_EQUAL(1u, set.count(S(7)));
+ EXPECT_EQUAL(0u, set.count(S(10007)));
}
TEST("test hash set range constructor")
diff --git a/vespalib/src/vespa/vespalib/stllike/hash_map.hpp b/vespalib/src/vespa/vespalib/stllike/hash_map.hpp
index 08edcf3c837..61789f6e2be 100644
--- a/vespalib/src/vespa/vespalib/stllike/hash_map.hpp
+++ b/vespalib/src/vespa/vespalib/stllike/hash_map.hpp
@@ -73,11 +73,12 @@ hash_map<K, V, H, EQ, M>::getMemoryUsed() const
template vespalib::hashtable<K, std::pair<K,V>, H, E, vespalib::Select1st<std::pair<K,V>>, M>::insert_result \
vespalib::hashtable<K, std::pair<K,V>, H, E, vespalib::Select1st<std::pair<K,V>>, M>::insert(std::pair<K,V> &&); \
template vespalib::hashtable<K, std::pair<K,V>, H, E, vespalib::Select1st<std::pair<K,V>>, M>::insert_result \
- vespalib::hashtable<K, std::pair<K,V>, H, E, vespalib::Select1st<std::pair<K,V>>, M>::insertInternal(std::pair<K,V> &&); \
- template class vespalib::Array<vespalib::hash_node<std::pair<K,V>>>;
+ vespalib::hashtable<K, std::pair<K,V>, H, E, vespalib::Select1st<std::pair<K,V>>, M>::insertInternal(std::pair<K,V> &&);
#define VESPALIB_HASH_MAP_INSTANTIATE_H_E(K, V, H, E) \
- VESPALIB_HASH_MAP_INSTANTIATE_H_E_M(K, V, H, E, vespalib::hashtable_base::prime_modulator)
+ template class vespalib::Array<vespalib::hash_node<std::pair<K,V>>>; \
+ VESPALIB_HASH_MAP_INSTANTIATE_H_E_M(K, V, H, E, vespalib::hashtable_base::prime_modulator) \
+ VESPALIB_HASH_MAP_INSTANTIATE_H_E_M(K, V, H, E, vespalib::hashtable_base::and_modulator)
#define VESPALIB_HASH_MAP_INSTANTIATE_H(K, V, H) VESPALIB_HASH_MAP_INSTANTIATE_H_E(K, V, H, std::equal_to<>)
diff --git a/vespalib/src/vespa/vespalib/stllike/hash_set.h b/vespalib/src/vespa/vespalib/stllike/hash_set.h
index 8d315ebfd07..08288086bf3 100644
--- a/vespalib/src/vespa/vespalib/stllike/hash_set.h
+++ b/vespalib/src/vespa/vespalib/stllike/hash_set.h
@@ -42,6 +42,7 @@ public:
template<typename InputIt>
void insert(InputIt first, InputIt last);
void erase(const K & key);
+ size_t count(const K & key) const { return _ht.find(key) != end() ? 1 : 0; }
iterator find(const K & key) { return _ht.find(key); }
const_iterator find(const K & key) const { return _ht.find(key); }