Perfect hash working, but it is slower.
This commit is contained in:
parent
238e384367
commit
09c1af7771
@ -17,7 +17,7 @@ struct hollow_iterator_base
|
||||
typedef typename iterator::pointer pointer;
|
||||
|
||||
hollow_iterator_base(container* c, presence* p, iterator it)
|
||||
: c_(c), p_(p), it_(it) { find_present(); }
|
||||
: c_(c), p_(p), it_(it) { if (c_) find_present(); }
|
||||
self_reference operator++() {
|
||||
++it_; find_present();
|
||||
}
|
||||
@ -44,6 +44,7 @@ struct hollow_iterator : public hollow_iterator_base<
|
||||
container_type, std::vector<bool>, typename container_type::iterator> {
|
||||
typedef hollow_iterator_base<
|
||||
container_type, std::vector<bool>, typename container_type::iterator> parent_class;
|
||||
hollow_iterator() : parent_class(NULL, NULL, typename container_type::iterator()) { }
|
||||
hollow_iterator(typename parent_class::container* c,
|
||||
typename parent_class::presence* p,
|
||||
typename parent_class::iterator it)
|
||||
@ -58,6 +59,7 @@ struct hollow_const_iterator : public hollow_iterator_base<
|
||||
typedef hollow_const_iterator<container_type> self_type;
|
||||
typedef hollow_iterator<container_type> non_const_type;
|
||||
hollow_const_iterator(non_const_type rhs) : parent_class(rhs.c_, rhs.p_, typename container_type::const_iterator(rhs.it_)) { }
|
||||
hollow_const_iterator() : parent_class(NULL, NULL, typename container_type::iterator()) { }
|
||||
hollow_const_iterator(const typename parent_class::container* c,
|
||||
const typename parent_class::presence* p,
|
||||
typename parent_class::iterator it)
|
||||
|
@ -31,5 +31,8 @@ int main(int argc, char** argv) {
|
||||
auto it1 = hollow_iterator<vector<int>>(&v, &p, v.begin());
|
||||
auto it2 = hollow_const_iterator<vector<int>>(&v, &p, v.begin());
|
||||
if (it1 != it2) exit(-1);
|
||||
|
||||
hollow_iterator<vector<int>> default_constructed;
|
||||
default_constructed = hollow_iterator<vector<int>>(&v, &p, v.begin());
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
// and should not be used if performance is a concern. In fact, you should only
|
||||
// use it for educational purposes.
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@ -71,9 +72,8 @@ class mph_map {
|
||||
data_type& operator[](const key_type &k);
|
||||
const data_type& operator[](const key_type &k) const;
|
||||
|
||||
size_type bucket_count() const { return index_.perfect_hash_size() + slack_.bucket_count(); }
|
||||
// FIXME: not sure if this has the semantics I want
|
||||
void rehash(size_type nbuckets /*ignored*/) { pack(); }
|
||||
size_type bucket_count() const { return index_.size() + slack_.bucket_count(); }
|
||||
void rehash(size_type nbuckets /*ignored*/);
|
||||
|
||||
protected: // mimicking STL implementation
|
||||
EqualKey equal_;
|
||||
@ -131,6 +131,7 @@ MPH_MAP_METHOD_DECL(insert_return_type, insert)(const value_type& x) {
|
||||
}
|
||||
values_.push_back(x);
|
||||
present_.push_back(true);
|
||||
++size_;
|
||||
slack_.insert(make_pair(x.first, values_.size() - 1));
|
||||
if (should_pack) pack();
|
||||
it = find(x.first);
|
||||
@ -143,10 +144,12 @@ MPH_MAP_METHOD_DECL(void_type, pack)() {
|
||||
make_iterator_first(begin()),
|
||||
make_iterator_first(end()), size_);
|
||||
assert(success);
|
||||
std::vector<value_type> new_values(index_.size());
|
||||
std::vector<bool> new_present(index_.size(), false);
|
||||
for (iterator it(begin()), it_end(end()); it != it_end; ++it) {
|
||||
size_type id = index_.index(it->first);
|
||||
std::vector<value_type> new_values(index_.perfect_hash_size());
|
||||
new_values.reserve(new_values.size() * 2);
|
||||
std::vector<bool> new_present(index_.perfect_hash_size(), false);
|
||||
new_present.reserve(new_present.size() * 2);
|
||||
for (iterator it = begin(), it_end = end(); it != it_end; ++it) {
|
||||
size_type id = index_.perfect_hash(it->first);
|
||||
assert(id < new_values.size());
|
||||
new_values[id] = *it;
|
||||
new_present[id] = true;
|
||||
@ -168,11 +171,13 @@ MPH_MAP_METHOD_DECL(void_type, clear)() {
|
||||
present_.clear();
|
||||
slack_.clear();
|
||||
index_.clear();
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
MPH_MAP_METHOD_DECL(void_type, erase)(iterator pos) {
|
||||
present_[pos - begin] = false;
|
||||
*pos = value_type();
|
||||
--size_;
|
||||
}
|
||||
MPH_MAP_METHOD_DECL(void_type, erase)(const key_type& k) {
|
||||
iterator it = find(k);
|
||||
@ -214,6 +219,13 @@ MPH_MAP_METHOD_DECL(my_int32_t, index)(const key_type& k) const {
|
||||
MPH_MAP_METHOD_DECL(data_type&, operator[])(const key_type& k) {
|
||||
return insert(make_pair(k, data_type())).first->second;
|
||||
}
|
||||
MPH_MAP_METHOD_DECL(void_type, rehash)(size_type nbuckets) {
|
||||
pack();
|
||||
vector<value_type>(values_.begin(), values_.end()).swap(values_);
|
||||
vector<bool>(present_.begin(), present_.end()).swap(present_);
|
||||
slack_type().swap(slack_);
|
||||
}
|
||||
|
||||
|
||||
} // namespace cxxmph
|
||||
|
||||
|
@ -11,21 +11,25 @@ using cxxmph::mph_map;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mph_map<int64_t, int64_t> b;
|
||||
for (int i = 0; i < 100*1000; ++i) {
|
||||
int32_t num_keys = 1000*10;
|
||||
for (int i = 0; i < num_keys; ++i) {
|
||||
b.insert(make_pair(i, i));
|
||||
}
|
||||
for (int i = 0; i < 1000*1000; ++i) {
|
||||
b.find(i);
|
||||
for (int i = 0; i < num_keys; ++i) {
|
||||
auto it = b.find(i);
|
||||
if (it->first != it->second || it->first != i) {
|
||||
std::cerr << "Found " << it->first << " looking for " << i << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
mph_map<string, int> h;
|
||||
h.insert(std::make_pair("-1",-1));
|
||||
mph_map<string, int>::const_iterator it;
|
||||
for (it = h.begin(); it != h.end(); ++it) {
|
||||
std::cerr << it->first << " -> " << it->second << std::endl;
|
||||
if (it->second != -1) exit(-1);
|
||||
}
|
||||
std::cerr << "Search -1 gives " << h.find("-1")->second << std::endl;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
int32_t num_valid = 100;
|
||||
for (int i = 0; i < num_valid; ++i) {
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "%d", i);
|
||||
h.insert(std::make_pair(buf, i));
|
||||
@ -34,18 +38,17 @@ int main(int argc, char** argv) {
|
||||
for (int i = 1000; i > 0; --i) {
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "%d", i - 1);
|
||||
h.find(buf);
|
||||
std::cerr << "Search " << i - 1 << " gives " << h.find(buf)->second << std::endl;
|
||||
auto it = h.find(buf);
|
||||
if (i < num_valid && it->second != i - 1) exit(-1);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
for (int i = 1000; i > 0; --i) {
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "%d", i*100 - 1);
|
||||
h.find(buf);
|
||||
std::cerr << "Search " << i*100 - 1 << " gives " << h.find(buf)->second << std::endl;
|
||||
int key = i*100 - 1;
|
||||
snprintf(buf, 10, "%d", key);
|
||||
auto it = h.find(buf);
|
||||
if (key < num_valid && it->second != key) exit(-1);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user