All tests pass.
This commit is contained in:
parent
bcf4962604
commit
48155e5b66
@ -21,8 +21,8 @@ fi
|
|||||||
if test "x$ac_cv_sys_largefile_LIBS" = "xno" ; then
|
if test "x$ac_cv_sys_largefile_LIBS" = "xno" ; then
|
||||||
ac_cv_sys_largefile_LIBS=""
|
ac_cv_sys_largefile_LIBS=""
|
||||||
fi
|
fi
|
||||||
CFLAGS="$CFLAGS $ac_cv_sys_largefile_CFLAGS"
|
CFLAGS="$$ac_cv_sys_largefile_CFLAGS $CFLAGS"
|
||||||
LDFLAGS="$LDFLAGS $ac_cv_sys_largefile_LDFLAGS"
|
LDFLAGS="$ac_cv_sys_largefile_LDFLAGS $LDFLAGS"
|
||||||
LIBS="$LIBS $ac_cv_sys_largefile_LIBS"
|
LIBS="$LIBS $ac_cv_sys_largefile_LIBS"
|
||||||
|
|
||||||
dnl Checks for headers
|
dnl Checks for headers
|
||||||
@ -34,6 +34,7 @@ LDFLAGS="$LIBM $LDFLAGS"
|
|||||||
CFLAGS="-Wall -Werror"
|
CFLAGS="-Wall -Werror"
|
||||||
|
|
||||||
AC_PROG_CXX
|
AC_PROG_CXX
|
||||||
|
CXXFLAGS="-Wall -Winline -Wno-unused-function -Werror -DNDEBUG -O3 -fomit-frame-pointer $CXXFLAGS"
|
||||||
AC_ENABLE_CXXMPH
|
AC_ENABLE_CXXMPH
|
||||||
if test x$cxxmph = xtrue; then
|
if test x$cxxmph = xtrue; then
|
||||||
AC_COMPILE_STDCXX_0X
|
AC_COMPILE_STDCXX_0X
|
||||||
|
@ -3,7 +3,7 @@ check_PROGRAMS = seeded_hash_test mph_bits_test hollow_iterator_test mph_map_tes
|
|||||||
noinst_PROGRAMS = bm_index bm_map
|
noinst_PROGRAMS = bm_index bm_map
|
||||||
bin_PROGRAMS = cxxmph
|
bin_PROGRAMS = cxxmph
|
||||||
lib_LTLIBRARIES = libcxxmph.la
|
lib_LTLIBRARIES = libcxxmph.la
|
||||||
libcxxmph_la_SOURCES = MurmurHash3.h MurmurHash3.cpp trigragh.h trigraph.cc mph_index.h mph_index.cc seeded_hash.h stringpiece.h benchmark.h benchmark.cc mph_bits.h mph_bits.cc
|
libcxxmph_la_SOURCES = MurmurHash3.h MurmurHash3.cpp trigragh.h trigraph.cc mph_bits.h mph_bits.cc mph_index.h mph_index.cc seeded_hash.h stringpiece.h benchmark.h benchmark.cc
|
||||||
libcxxmph_la_LDFLAGS = -version-info 0:0:0
|
libcxxmph_la_LDFLAGS = -version-info 0:0:0
|
||||||
cxxmph_includedir = $(includedir)/cxxmph/
|
cxxmph_includedir = $(includedir)/cxxmph/
|
||||||
cxxmph_include_HEADERS = mph_map.h mph_index.h MurmurHash3.h trigraph.h seeded_hash.h stringpiece.h hollow_iterator.h
|
cxxmph_include_HEADERS = mph_map.h mph_index.h MurmurHash3.h trigraph.h seeded_hash.h stringpiece.h hollow_iterator.h
|
||||||
|
@ -106,7 +106,7 @@ namespace cxxmph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void Benchmark::RunAll() {
|
/* static */ void Benchmark::RunAll() {
|
||||||
for (int i = 0; i < g_benchmarks.size(); ++i) {
|
for (uint32_t i = 0; i < g_benchmarks.size(); ++i) {
|
||||||
std::auto_ptr<Benchmark> bm(g_benchmarks[i]);
|
std::auto_ptr<Benchmark> bm(g_benchmarks[i]);
|
||||||
if (!bm->SetUp()) {
|
if (!bm->SetUp()) {
|
||||||
cerr << "Set up phase for benchmark "
|
cerr << "Set up phase for benchmark "
|
||||||
|
@ -14,6 +14,7 @@ using std::vector;
|
|||||||
|
|
||||||
namespace cxxmph {
|
namespace cxxmph {
|
||||||
|
|
||||||
|
UrlsBenchmark::~UrlsBenchmark() {}
|
||||||
bool UrlsBenchmark::SetUp() {
|
bool UrlsBenchmark::SetUp() {
|
||||||
vector<string> urls;
|
vector<string> urls;
|
||||||
std::ifstream f(urls_file_.c_str());
|
std::ifstream f(urls_file_.c_str());
|
||||||
@ -32,12 +33,13 @@ bool UrlsBenchmark::SetUp() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchUrlsBenchmark::~SearchUrlsBenchmark() {}
|
||||||
bool SearchUrlsBenchmark::SetUp() {
|
bool SearchUrlsBenchmark::SetUp() {
|
||||||
if (!UrlsBenchmark::SetUp()) return false;
|
if (!UrlsBenchmark::SetUp()) return false;
|
||||||
int32_t miss_ratio_int32 = std::numeric_limits<int32_t>::max() * miss_ratio_;
|
int32_t miss_ratio_int32 = std::numeric_limits<int32_t>::max() * miss_ratio_;
|
||||||
forced_miss_urls_.resize(nsearches_);
|
forced_miss_urls_.resize(nsearches_);
|
||||||
random_.resize(nsearches_);
|
random_.resize(nsearches_);
|
||||||
for (int i = 0; i < nsearches_; ++i) {
|
for (uint32_t i = 0; i < nsearches_; ++i) {
|
||||||
random_[i] = urls_[random() % urls_.size()];
|
random_[i] = urls_[random() % urls_.size()];
|
||||||
if (random() < miss_ratio_int32) {
|
if (random() < miss_ratio_int32) {
|
||||||
forced_miss_urls_[i] = random_[i].as_string() + ".force_miss";
|
forced_miss_urls_[i] = random_[i].as_string() + ".force_miss";
|
||||||
@ -47,9 +49,10 @@ bool SearchUrlsBenchmark::SetUp() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Uint64Benchmark::~Uint64Benchmark() {}
|
||||||
bool Uint64Benchmark::SetUp() {
|
bool Uint64Benchmark::SetUp() {
|
||||||
set<uint64_t> unique;
|
set<uint64_t> unique;
|
||||||
for (int i = 0; i < count_; ++i) {
|
for (uint32_t i = 0; i < count_; ++i) {
|
||||||
uint64_t v;
|
uint64_t v;
|
||||||
do { v = random(); } while (unique.find(v) != unique.end());
|
do { v = random(); } while (unique.find(v) != unique.end());
|
||||||
values_.push_back(v);
|
values_.push_back(v);
|
||||||
@ -58,10 +61,11 @@ bool Uint64Benchmark::SetUp() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchUint64Benchmark::~SearchUint64Benchmark() {}
|
||||||
bool SearchUint64Benchmark::SetUp() {
|
bool SearchUint64Benchmark::SetUp() {
|
||||||
if (!Uint64Benchmark::SetUp()) return false;
|
if (!Uint64Benchmark::SetUp()) return false;
|
||||||
random_.resize(nsearches_);
|
random_.resize(nsearches_);
|
||||||
for (int i = 0; i < nsearches_; ++i) {
|
for (uint32_t i = 0; i < nsearches_; ++i) {
|
||||||
uint32_t pos = random() % values_.size();
|
uint32_t pos = random() % values_.size();
|
||||||
random_[i] = values_[pos];
|
random_[i] = values_[pos];
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace cxxmph {
|
|||||||
class UrlsBenchmark : public Benchmark {
|
class UrlsBenchmark : public Benchmark {
|
||||||
public:
|
public:
|
||||||
UrlsBenchmark(const std::string& urls_file) : urls_file_(urls_file) { }
|
UrlsBenchmark(const std::string& urls_file) : urls_file_(urls_file) { }
|
||||||
virtual ~UrlsBenchmark() {}
|
virtual ~UrlsBenchmark();
|
||||||
protected:
|
protected:
|
||||||
virtual bool SetUp();
|
virtual bool SetUp();
|
||||||
const std::string urls_file_;
|
const std::string urls_file_;
|
||||||
@ -36,7 +36,7 @@ class SearchUrlsBenchmark : public UrlsBenchmark {
|
|||||||
public:
|
public:
|
||||||
SearchUrlsBenchmark(const std::string& urls_file, uint32_t nsearches, float miss_ratio)
|
SearchUrlsBenchmark(const std::string& urls_file, uint32_t nsearches, float miss_ratio)
|
||||||
: UrlsBenchmark(urls_file), nsearches_(nsearches), miss_ratio_(miss_ratio) {}
|
: UrlsBenchmark(urls_file), nsearches_(nsearches), miss_ratio_(miss_ratio) {}
|
||||||
virtual ~SearchUrlsBenchmark() {}
|
virtual ~SearchUrlsBenchmark();
|
||||||
protected:
|
protected:
|
||||||
virtual bool SetUp();
|
virtual bool SetUp();
|
||||||
const uint32_t nsearches_;
|
const uint32_t nsearches_;
|
||||||
@ -48,6 +48,7 @@ class SearchUrlsBenchmark : public UrlsBenchmark {
|
|||||||
class Uint64Benchmark : public Benchmark {
|
class Uint64Benchmark : public Benchmark {
|
||||||
public:
|
public:
|
||||||
Uint64Benchmark(uint32_t count) : count_(count) { }
|
Uint64Benchmark(uint32_t count) : count_(count) { }
|
||||||
|
virtual ~Uint64Benchmark();
|
||||||
virtual void Run() {}
|
virtual void Run() {}
|
||||||
protected:
|
protected:
|
||||||
virtual bool SetUp();
|
virtual bool SetUp();
|
||||||
@ -59,6 +60,7 @@ class SearchUint64Benchmark : public Uint64Benchmark {
|
|||||||
public:
|
public:
|
||||||
SearchUint64Benchmark(uint32_t count, uint32_t nsearches)
|
SearchUint64Benchmark(uint32_t count, uint32_t nsearches)
|
||||||
: Uint64Benchmark(count), nsearches_(nsearches) { }
|
: Uint64Benchmark(count), nsearches_(nsearches) { }
|
||||||
|
virtual ~SearchUint64Benchmark();
|
||||||
virtual void Run() {};
|
virtual void Run() {};
|
||||||
protected:
|
protected:
|
||||||
virtual bool SetUp();
|
virtual bool SetUp();
|
||||||
|
@ -47,7 +47,7 @@ class BM_MPHIndexSearch : public SearchUrlsBenchmark {
|
|||||||
for (auto it = random_.begin(); it != random_.end(); ++it) {
|
for (auto it = random_.begin(); it != random_.end(); ++it) {
|
||||||
auto idx = index_.index(*it);
|
auto idx = index_.index(*it);
|
||||||
// Collision check to be fair with STL
|
// Collision check to be fair with STL
|
||||||
// if (strcmp(urls_[idx].c_str(), it->data()) != 0) idx = -1;
|
if (strcmp(urls_[idx].c_str(), it->data()) != 0) idx = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
|
@ -42,7 +42,7 @@ class BM_SearchUrls : public SearchUrlsBenchmark {
|
|||||||
virtual ~BM_SearchUrls() {}
|
virtual ~BM_SearchUrls() {}
|
||||||
virtual void Run() {
|
virtual void Run() {
|
||||||
for (auto it = random_.begin(); it != random_.end(); ++it) {
|
for (auto it = random_.begin(); it != random_.end(); ++it) {
|
||||||
auto v = myfind(mymap_, *it);
|
myfind(mymap_, *it);
|
||||||
assert(it->ends_with(".force_miss") ^ v != NULL);
|
assert(it->ends_with(".force_miss") ^ v != NULL);
|
||||||
assert(!v || *v == *it);
|
assert(!v || *v == *it);
|
||||||
}
|
}
|
||||||
@ -66,12 +66,12 @@ class BM_SearchUint64 : public SearchUint64Benchmark {
|
|||||||
BM_SearchUint64() : SearchUint64Benchmark(100000, 10*1000*1000) { }
|
BM_SearchUint64() : SearchUint64Benchmark(100000, 10*1000*1000) { }
|
||||||
virtual bool SetUp() {
|
virtual bool SetUp() {
|
||||||
if (!SearchUint64Benchmark::SetUp()) return false;
|
if (!SearchUint64Benchmark::SetUp()) return false;
|
||||||
for (int i = 0; i < values_.size(); ++i) {
|
for (uint32_t i = 0; i < values_.size(); ++i) {
|
||||||
mymap_[values_[i]] = values_[i];
|
mymap_[values_[i]] = values_[i];
|
||||||
}
|
}
|
||||||
mymap_.rehash(mymap_.bucket_count());
|
mymap_.rehash(mymap_.bucket_count());
|
||||||
// Double check if everything is all right
|
// Double check if everything is all right
|
||||||
for (int i = 0; i < values_.size(); ++i) {
|
for (uint32_t i = 0; i < values_.size(); ++i) {
|
||||||
if (mymap_[values_[i]] != values_[i]) return false;
|
if (mymap_[values_[i]] != values_[i]) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -80,7 +80,7 @@ class BM_SearchUint64 : public SearchUint64Benchmark {
|
|||||||
for (auto it = random_.begin(); it != random_.end(); ++it) {
|
for (auto it = random_.begin(); it != random_.end(); ++it) {
|
||||||
auto v = myfind(mymap_, *it);
|
auto v = myfind(mymap_, *it);
|
||||||
if (*v != *it) {
|
if (*v != *it) {
|
||||||
fprintf(stderr, "Looked for %lu got %lu\n", *it, *v);
|
fprintf(stderr, "Looked for %llu got %llu\n", *it, *v);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,10 +57,10 @@ int main(int argc, char** argv) {
|
|||||||
ifstream f(argv[optind]);
|
ifstream f(argv[optind]);
|
||||||
string buffer;
|
string buffer;
|
||||||
while (!getline(f, buffer).eof()) keys.push_back(buffer);
|
while (!getline(f, buffer).eof()) keys.push_back(buffer);
|
||||||
for (int i = 0; i < keys.size(); ++i) string s = keys[i];
|
for (uint32_t i = 0; i < keys.size(); ++i) string s = keys[i];
|
||||||
mph_map<string, string> table;
|
mph_map<string, string> table;
|
||||||
|
|
||||||
for (int i = 0; i < keys.size(); ++i) table[keys[i]] = keys[i];
|
for (uint32_t i = 0; i < keys.size(); ++i) table[keys[i]] = keys[i];
|
||||||
mph_map<string, string>::const_iterator it = table.begin();
|
mph_map<string, string>::const_iterator it = table.begin();
|
||||||
mph_map<string, string>::const_iterator end = table.end();
|
mph_map<string, string>::const_iterator end = table.end();
|
||||||
for (int i = 0; it != end; ++it, ++i) {
|
for (int i = 0; it != end; ++it, ++i) {
|
||||||
|
@ -5,66 +5,65 @@
|
|||||||
|
|
||||||
namespace cxxmph {
|
namespace cxxmph {
|
||||||
|
|
||||||
template <typename container_type, typename presence_type, typename iterator_type>
|
using std::vector;
|
||||||
|
|
||||||
|
template <typename container_type>
|
||||||
|
struct is_empty {
|
||||||
|
public:
|
||||||
|
is_empty() : c_(NULL), p_(NULL) {};
|
||||||
|
is_empty(const container_type* c, const vector<bool>* p) : c_(c), p_(p) {};
|
||||||
|
bool operator()(typename container_type::const_iterator it) const {
|
||||||
|
if (it == c_->end()) return false;
|
||||||
|
return !(*p_)[it - c_->begin()];
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const container_type* c_;
|
||||||
|
const vector<bool>* p_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename iterator, typename is_empty>
|
||||||
struct hollow_iterator_base
|
struct hollow_iterator_base
|
||||||
: public std::iterator<std::forward_iterator_tag,
|
: public std::iterator<std::forward_iterator_tag,
|
||||||
typename container_type::value_type> {
|
typename iterator::value_type> {
|
||||||
typedef presence_type presence;
|
public:
|
||||||
typedef container_type container;
|
typedef hollow_iterator_base<iterator, is_empty>& self_type;
|
||||||
typedef iterator_type iterator;
|
typedef self_type& self_reference;
|
||||||
typedef hollow_iterator_base<container, presence, iterator>& self_reference;
|
|
||||||
typedef typename iterator::reference reference;
|
typedef typename iterator::reference reference;
|
||||||
typedef typename iterator::pointer pointer;
|
typedef typename iterator::pointer pointer;
|
||||||
|
hollow_iterator_base() : it_(), empty_() { }
|
||||||
|
hollow_iterator_base(iterator it, is_empty empty) : it_(it), empty_(empty) {
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
hollow_iterator_base(const self_type& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; }
|
||||||
|
template <typename const_iterator>
|
||||||
|
hollow_iterator_base(const hollow_iterator_base<const_iterator, is_empty>& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; }
|
||||||
|
|
||||||
hollow_iterator_base(container* c, presence* p, iterator it)
|
|
||||||
: c_(c), p_(p), it_(it) { if (c_) find_present(); }
|
|
||||||
self_reference operator++() {
|
|
||||||
++it_; find_present();
|
|
||||||
}
|
|
||||||
reference operator*() { return *it_; }
|
reference operator*() { return *it_; }
|
||||||
pointer operator->() { return &(*it_); }
|
pointer operator->() { return &(*it_); }
|
||||||
|
self_reference operator++() { ++it_; advance(); return *this; }
|
||||||
|
// self_type operator++() { auto tmp(*this); ++tmp; return tmp; }
|
||||||
|
|
||||||
// TODO find syntax to make this less permissible at compile time
|
template <typename const_iterator>
|
||||||
template <class T>
|
bool operator==(const hollow_iterator_base<const_iterator, is_empty>& rhs) { return rhs.it_ == it_; }
|
||||||
bool operator==(const T& rhs) { return rhs.it_ == this->it_; }
|
template <typename const_iterator>
|
||||||
template <class T>
|
bool operator!=(const hollow_iterator_base<const_iterator, is_empty>& rhs) { return rhs.it_ != it_; }
|
||||||
bool operator!=(const T& rhs) { return rhs.it_ != this->it_; }
|
|
||||||
|
|
||||||
public: // TODO find syntax to make this friend of const iterator
|
// should be friend
|
||||||
void find_present() {
|
|
||||||
while (it_ != c_->end() && !((*p_)[it_-c_->begin()])) ++it_;
|
|
||||||
}
|
|
||||||
container* c_;
|
|
||||||
presence* p_;
|
|
||||||
iterator it_;
|
iterator it_;
|
||||||
|
is_empty empty_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void advance() {
|
||||||
|
while (empty_(it_)) ++it_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename container_type>
|
template <typename container_type, typename iterator> auto make_hollow(
|
||||||
struct hollow_iterator : public hollow_iterator_base<
|
container_type* v, vector<bool>* p, iterator it) ->
|
||||||
container_type, std::vector<bool>, typename container_type::iterator> {
|
hollow_iterator_base<iterator, is_empty<container_type>> {
|
||||||
typedef hollow_iterator_base<
|
return hollow_iterator_base<iterator, is_empty<container_type>>(
|
||||||
container_type, std::vector<bool>, typename container_type::iterator> parent_class;
|
it, is_empty<container_type>(v, p));
|
||||||
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)
|
|
||||||
: parent_class(c, p, it) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename container_type>
|
|
||||||
struct hollow_const_iterator : public hollow_iterator_base<
|
|
||||||
const container_type, const std::vector<bool>, typename container_type::const_iterator> {
|
|
||||||
typedef hollow_iterator_base<
|
|
||||||
const container_type, const std::vector<bool>, typename container_type::const_iterator> parent_class;
|
|
||||||
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)
|
|
||||||
: parent_class(c, p, it) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cxxmph
|
} // namespace cxxmph
|
||||||
|
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "hollow_iterator.h"
|
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using cxxmph::hollow_iterator;
|
#include "hollow_iterator.h"
|
||||||
using cxxmph::hollow_const_iterator;
|
using cxxmph::hollow_iterator_base;
|
||||||
|
using cxxmph::make_hollow;
|
||||||
|
using cxxmph::is_empty;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
vector<int> v;
|
vector<int> v;
|
||||||
@ -15,24 +19,27 @@ int main(int argc, char** argv) {
|
|||||||
v.push_back(i);
|
v.push_back(i);
|
||||||
p.push_back(i % 2 == 0);
|
p.push_back(i % 2 == 0);
|
||||||
}
|
}
|
||||||
auto begin = hollow_iterator<vector<int>>(&v, &p, v.begin());
|
auto begin = make_hollow(&v, &p, v.begin());
|
||||||
auto end = hollow_iterator<vector<int>>(&v, &p, v.end());
|
auto end = make_hollow(&v, &p, v.end());
|
||||||
for (auto it = begin; it != end; ++it) {
|
for (auto it = begin; it != end; ++it) {
|
||||||
if (((*it) % 2) != 0) exit(-1);
|
if (((*it) % 2) != 0) exit(-1);
|
||||||
}
|
}
|
||||||
hollow_const_iterator<vector<int>> const_begin(begin);
|
const vector<int>* cv(&v);
|
||||||
hollow_const_iterator<vector<int>> const_end(end);
|
auto cbegin(make_hollow(cv, &p, cv->begin()));
|
||||||
for (auto it = const_begin; it != const_end; ++it) {
|
auto cend(make_hollow(cv, &p, cv->begin()));
|
||||||
|
for (auto it = cbegin; it != cend; ++it) {
|
||||||
if (((*it) % 2) != 0) exit(-1);
|
if (((*it) % 2) != 0) exit(-1);
|
||||||
}
|
}
|
||||||
vector<int>::iterator vit1 = v.begin();
|
vector<int>::iterator vit1 = v.begin();
|
||||||
vector<int>::const_iterator vit2 = v.begin();
|
vector<int>::const_iterator vit2 = v.begin();
|
||||||
if (vit1 != vit2) exit(-1);
|
if (vit1 != vit2) exit(-1);
|
||||||
auto it1 = hollow_iterator<vector<int>>(&v, &p, v.begin());
|
auto it1 = make_hollow(&v, &p, vit1);
|
||||||
auto it2 = hollow_const_iterator<vector<int>>(&v, &p, v.begin());
|
auto it2 = make_hollow(&v, &p, vit2);
|
||||||
if (it1 != it2) exit(-1);
|
if (it1 != it2) exit(-1);
|
||||||
|
|
||||||
hollow_iterator<vector<int>> default_constructed;
|
typedef is_empty<vector<int>> iev;
|
||||||
default_constructed = hollow_iterator<vector<int>>(&v, &p, v.begin());
|
hollow_iterator_base<vector<int>::iterator, iev> default_constructed;
|
||||||
|
default_constructed = make_hollow(&v, &p, v.begin());
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
namespace cxxmph {
|
namespace cxxmph {
|
||||||
|
|
||||||
const uint8_t dynamic_2bitset::vmask[] = { 0xfc, 0xf3, 0xcf, 0x3f};
|
const uint8_t dynamic_2bitset::vmask[] = { 0xfc, 0xf3, 0xcf, 0x3f};
|
||||||
|
dynamic_2bitset::dynamic_2bitset() : size_(0), fill_(false) {}
|
||||||
|
dynamic_2bitset::dynamic_2bitset(uint32_t size, bool fill)
|
||||||
|
: size_(size), fill_(fill), data_(ceil(size / 4.0), ones()*fill) {}
|
||||||
|
dynamic_2bitset::~dynamic_2bitset() {}
|
||||||
|
|
||||||
template <int n, int mask = (1 << 7)> struct bitcount {
|
template <int n, int mask = (1 << 7)> struct bitcount {
|
||||||
enum { value = (n & mask ? 1:0) + bitcount<n, (mask >> 1)>::value };
|
enum { value = (n & mask ? 1:0) + bitcount<n, (mask >> 1)>::value };
|
||||||
@ -23,6 +27,9 @@ static CompileTimeRankTable<256> kRanktable;
|
|||||||
|
|
||||||
uint8_t Ranktable::get(uint8_t i) { return kRanktable[i]; }
|
uint8_t Ranktable::get(uint8_t i) { return kRanktable[i]; }
|
||||||
|
|
||||||
|
void stop_unused_warning() {
|
||||||
|
rank64(4);
|
||||||
|
nextpoweroftwo(4);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,9 @@ namespace cxxmph {
|
|||||||
|
|
||||||
class dynamic_2bitset {
|
class dynamic_2bitset {
|
||||||
public:
|
public:
|
||||||
dynamic_2bitset() : size_(0), fill_(false) {}
|
dynamic_2bitset();
|
||||||
dynamic_2bitset(uint32_t size, bool fill = false)
|
~dynamic_2bitset();
|
||||||
: size_(size), fill_(fill), data_(ceil(size / 4.0), ones()*fill) {
|
dynamic_2bitset(uint32_t size, bool fill = false);
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t operator[](uint32_t i) const { return get(i); }
|
const uint8_t operator[](uint32_t i) const { return get(i); }
|
||||||
const uint8_t get(uint32_t i) const {
|
const uint8_t get(uint32_t i) const {
|
||||||
@ -28,7 +27,7 @@ class dynamic_2bitset {
|
|||||||
assert((i >> 2) < data_.size());
|
assert((i >> 2) < data_.size());
|
||||||
return (data_[(i >> 2)] >> (((i & 3) << 1)) & 3);
|
return (data_[(i >> 2)] >> (((i & 3) << 1)) & 3);
|
||||||
}
|
}
|
||||||
uint8_t set(uint32_t i, uint8_t v) {
|
void set(uint32_t i, uint8_t v) {
|
||||||
assert((i >> 2) < data_.size());
|
assert((i >> 2) < data_.size());
|
||||||
data_[(i >> 2)] |= ones() ^ dynamic_2bitset::vmask[i & 3];
|
data_[(i >> 2)] |= ones() ^ dynamic_2bitset::vmask[i & 3];
|
||||||
data_[(i >> 2)] &= ((v << ((i & 3) << 1)) | dynamic_2bitset::vmask[i & 3]);
|
data_[(i >> 2)] &= ((v << ((i & 3) << 1)) | dynamic_2bitset::vmask[i & 3]);
|
||||||
@ -59,7 +58,7 @@ class dynamic_2bitset {
|
|||||||
static uint32_t nextpoweroftwo(uint32_t k) {
|
static uint32_t nextpoweroftwo(uint32_t k) {
|
||||||
if (k == 0) return 1;
|
if (k == 0) return 1;
|
||||||
k--;
|
k--;
|
||||||
for (int i=1; i<sizeof(uint32_t)*CHAR_BIT; i<<=1) k = k | k >> i;
|
for (uint32_t i=1; i<sizeof(uint32_t)*CHAR_BIT; i<<=1) k = k | k >> i;
|
||||||
return k+1;
|
return k+1;
|
||||||
}
|
}
|
||||||
// Interesting bit tricks that might end up here:
|
// Interesting bit tricks that might end up here:
|
||||||
|
@ -5,34 +5,35 @@
|
|||||||
|
|
||||||
using cxxmph::dynamic_2bitset;
|
using cxxmph::dynamic_2bitset;
|
||||||
using cxxmph::rank64;
|
using cxxmph::rank64;
|
||||||
|
using cxxmph::nextpoweroftwo;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
dynamic_2bitset small(256, true);
|
dynamic_2bitset small(256, true);
|
||||||
for (int i = 0; i < small.size(); ++i) small.set(i, i % 4);
|
for (uint32_t i = 0; i < small.size(); ++i) small.set(i, i % 4);
|
||||||
for (int i = 0; i < small.size(); ++i) {
|
for (uint32_t i = 0; i < small.size(); ++i) {
|
||||||
if (small[i] != i % 4) {
|
if (small[i] != i % 4) {
|
||||||
fprintf(stderr, "wrong bits %d at %d expected %d\n", small[i], i, i % 4);
|
fprintf(stderr, "wrong bits %d at %d expected %d\n", small[i], i, i % 4);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = 256;
|
uint32_t size = 256;
|
||||||
dynamic_2bitset bits(size, true /* fill with ones */);
|
dynamic_2bitset bits(size, true /* fill with ones */);
|
||||||
for (int i = 0; i < size; ++i) {
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
if (bits[i] != 3) {
|
if (bits[i] != 3) {
|
||||||
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, 3);
|
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, 3);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < size; ++i) bits.set(i, 0);
|
for (uint32_t i = 0; i < size; ++i) bits.set(i, 0);
|
||||||
for (int i = 0; i < size; ++i) {
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
if (bits[i] != 0) {
|
if (bits[i] != 0) {
|
||||||
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, 0);
|
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, 0);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < size; ++i) bits.set(i, i % 4);
|
for (uint32_t i = 0; i < size; ++i) bits.set(i, i % 4);
|
||||||
for (int i = 0; i < size; ++i) {
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
if (bits[i] != i % 4) {
|
if (bits[i] != i % 4) {
|
||||||
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, i % 4);
|
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, i % 4);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -44,7 +45,7 @@ int main(int argc, char** argv) {
|
|||||||
if (size_corner2.size() != 2) exit(-1);
|
if (size_corner2.size() != 2) exit(-1);
|
||||||
(dynamic_2bitset(4, true)).swap(size_corner2);
|
(dynamic_2bitset(4, true)).swap(size_corner2);
|
||||||
if (size_corner2.size() != 4) exit(-1);
|
if (size_corner2.size() != 4) exit(-1);
|
||||||
for (int i = 0; i < size_corner2.size(); ++i) {
|
for (uint32_t i = 0; i < size_corner2.size(); ++i) {
|
||||||
if (size_corner2[i] != 3) exit(-1);
|
if (size_corner2[i] != 3) exit(-1);
|
||||||
}
|
}
|
||||||
size_corner2.clear();
|
size_corner2.clear();
|
||||||
@ -54,6 +55,8 @@ int main(int argc, char** argv) {
|
|||||||
empty.clear();
|
empty.clear();
|
||||||
dynamic_2bitset large(1000, true);
|
dynamic_2bitset large(1000, true);
|
||||||
empty.swap(large);
|
empty.swap(large);
|
||||||
|
|
||||||
|
if (nextpoweroftwo(3) != 4) exit(-1);
|
||||||
|
|
||||||
if (rank64(0) != 0) exit(-1);
|
if (rank64(0) != 0) exit(-1);
|
||||||
if (rank64(1) != 1) exit(-1);
|
if (rank64(1) != 1) exit(-1);
|
||||||
|
@ -128,7 +128,7 @@ bool MPHIndex::Reset(
|
|||||||
nest_displacement_[0] = 0;
|
nest_displacement_[0] = 0;
|
||||||
nest_displacement_[1] = r_;
|
nest_displacement_[1] = r_;
|
||||||
nest_displacement_[2] = (r_ << 1);
|
nest_displacement_[2] = (r_ << 1);
|
||||||
for (int i = 0; i < sizeof(threebit_mod3); ++i) threebit_mod3[i] = i % 3;
|
for (uint32_t i = 0; i < sizeof(threebit_mod3); ++i) threebit_mod3[i] = i % 3;
|
||||||
|
|
||||||
n_ = 3*r_;
|
n_ = 3*r_;
|
||||||
k_ = 1U << b_;
|
k_ = 1U << b_;
|
||||||
|
@ -35,6 +35,7 @@ using std::vector;
|
|||||||
#define MPH_MAP_TMPL_SPEC template <class Key, class Data, class HashFcn, class EqualKey, class Alloc>
|
#define MPH_MAP_TMPL_SPEC template <class Key, class Data, class HashFcn, class EqualKey, class Alloc>
|
||||||
#define MPH_MAP_CLASS_SPEC mph_map<Key, Data, HashFcn, EqualKey, Alloc>
|
#define MPH_MAP_CLASS_SPEC mph_map<Key, Data, HashFcn, EqualKey, Alloc>
|
||||||
#define MPH_MAP_METHOD_DECL(r, m) MPH_MAP_TMPL_SPEC typename MPH_MAP_CLASS_SPEC::r MPH_MAP_CLASS_SPEC::m
|
#define MPH_MAP_METHOD_DECL(r, m) MPH_MAP_TMPL_SPEC typename MPH_MAP_CLASS_SPEC::r MPH_MAP_CLASS_SPEC::m
|
||||||
|
#define MPH_MAP_INLINE_METHOD_DECL(r, m) MPH_MAP_TMPL_SPEC inline typename MPH_MAP_CLASS_SPEC::r MPH_MAP_CLASS_SPEC::m
|
||||||
|
|
||||||
template <class Key, class Data, class HashFcn = std::hash<Key>, class EqualKey = std::equal_to<Key>, class Alloc = std::allocator<Data> >
|
template <class Key, class Data, class HashFcn = std::hash<Key>, class EqualKey = std::equal_to<Key>, class Alloc = std::allocator<Data> >
|
||||||
class mph_map {
|
class mph_map {
|
||||||
@ -72,10 +73,10 @@ class mph_map {
|
|||||||
void erase(iterator pos);
|
void erase(iterator pos);
|
||||||
void erase(const key_type& k);
|
void erase(const key_type& k);
|
||||||
pair<iterator, bool> insert(const value_type& x);
|
pair<iterator, bool> insert(const value_type& x);
|
||||||
iterator find(const key_type& k);
|
inline iterator find(const key_type& k);
|
||||||
const_iterator find(const key_type& k) const;
|
inline const_iterator find(const key_type& k) const;
|
||||||
typedef int32_t my_int32_t; // help macros
|
typedef int32_t my_int32_t; // help macros
|
||||||
int32_t index(const key_type& k) const;
|
inline int32_t index(const key_type& k) const;
|
||||||
data_type& operator[](const key_type &k);
|
data_type& operator[](const key_type &k);
|
||||||
const data_type& operator[](const key_type &k) const;
|
const data_type& operator[](const key_type &k) const;
|
||||||
|
|
||||||
@ -149,7 +150,7 @@ MPH_MAP_METHOD_DECL(void_type, pack)() {
|
|||||||
bool success = index_.Reset(
|
bool success = index_.Reset(
|
||||||
make_iterator_first(begin()),
|
make_iterator_first(begin()),
|
||||||
make_iterator_first(end()), size_);
|
make_iterator_first(end()), size_);
|
||||||
assert(success);
|
if (!success) { exit(-1); }
|
||||||
std::vector<value_type> new_values(index_.minimal_perfect_hash_size());
|
std::vector<value_type> new_values(index_.minimal_perfect_hash_size());
|
||||||
new_values.reserve(new_values.size() * 2);
|
new_values.reserve(new_values.size() * 2);
|
||||||
std::vector<bool> new_present(index_.minimal_perfect_hash_size(), false);
|
std::vector<bool> new_present(index_.minimal_perfect_hash_size(), false);
|
||||||
@ -193,21 +194,21 @@ MPH_MAP_METHOD_DECL(void_type, erase)(const key_type& k) {
|
|||||||
erase(it);
|
erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPH_MAP_METHOD_DECL(const_iterator, find)(const key_type& k) const {
|
MPH_MAP_INLINE_METHOD_DECL(const_iterator, find)(const key_type& k) const {
|
||||||
auto idx = index(k);
|
auto idx = index(k);
|
||||||
auto it = begin() + idx;
|
auto it = begin() + idx;
|
||||||
if (idx == -1 || it->first != k) return end();
|
if (idx == -1 || it->first != k) return end();
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPH_MAP_METHOD_DECL(iterator, find)(const key_type& k) {
|
MPH_MAP_INLINE_METHOD_DECL(iterator, find)(const key_type& k) {
|
||||||
auto idx = index(k);
|
auto idx = index(k);
|
||||||
auto it = begin() + idx;
|
auto it = begin() + idx;
|
||||||
if (idx == -1 || it->first != k) return end();
|
if (idx == -1 || it->first != k) return end();
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPH_MAP_METHOD_DECL(my_int32_t, index)(const key_type& k) const {
|
MPH_MAP_INLINE_METHOD_DECL(my_int32_t, index)(const key_type& k) const {
|
||||||
if (__builtin_expect(!slack_.empty(), 0)) {
|
if (__builtin_expect(!slack_.empty(), 0)) {
|
||||||
auto sit = slack_.find(hasher128_.hash128(k, 0));
|
auto sit = slack_.find(hasher128_.hash128(k, 0));
|
||||||
if (sit != slack_.end()) return sit->second;
|
if (sit != slack_.end()) return sit->second;
|
||||||
|
@ -88,6 +88,7 @@ struct Murmur3Fmix64bitsType {
|
|||||||
h128 h;
|
h128 h;
|
||||||
h.set64(fmix(k), 0);
|
h.set64(fmix(k), 0);
|
||||||
h.set64(fmix(h.get64(0)), 1);
|
h.set64(fmix(h.get64(0)), 1);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ int main(int argc, char** argv) {
|
|||||||
for (int i = 0; i < 1000; ++i) if (g[i] != i) exit(-1);
|
for (int i = 0; i < 1000; ++i) if (g[i] != i) exit(-1);
|
||||||
|
|
||||||
auto inthasher = seeded_hash_function<std::hash<uint64_t>>();
|
auto inthasher = seeded_hash_function<std::hash<uint64_t>>();
|
||||||
unordered_map<h128, int, h128::hash32> g2;
|
unordered_map<h128, uint64_t, h128::hash32> g2;
|
||||||
for (uint64_t i = 0; i < 1000; ++i) {
|
for (uint64_t i = 0; i < 1000; ++i) {
|
||||||
auto h = inthasher.hash128(i, 0);
|
auto h = inthasher.hash128(i, 0);
|
||||||
if (g2.find(h) != g2.end()) {
|
if (g2.find(h) != g2.end()) {
|
||||||
|
@ -20,6 +20,7 @@ TriGraph::TriGraph(uint32_t nvertices, uint32_t nedges)
|
|||||||
next_edge_(nedges),
|
next_edge_(nedges),
|
||||||
first_edge_(nvertices, kInvalidEdge),
|
first_edge_(nvertices, kInvalidEdge),
|
||||||
vertex_degree_(nvertices, 0) { }
|
vertex_degree_(nvertices, 0) { }
|
||||||
|
TriGraph::~TriGraph() {}
|
||||||
|
|
||||||
void TriGraph::ExtractEdgesAndClear(vector<Edge>* edges) {
|
void TriGraph::ExtractEdgesAndClear(vector<Edge>* edges) {
|
||||||
vector<Edge>().swap(next_edge_);
|
vector<Edge>().swap(next_edge_);
|
||||||
@ -67,7 +68,7 @@ void TriGraph::RemoveEdge(uint32_t current_edge) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TriGraph::DebugGraph() const {
|
void TriGraph::DebugGraph() const {
|
||||||
int i;
|
uint32_t i;
|
||||||
for(i = 0; i < edges_.size(); i++){
|
for(i = 0; i < edges_.size(); i++){
|
||||||
cerr << i << " " << edges_[i][0] << " " << edges_[i][1] << " " << edges_[i][2]
|
cerr << i << " " << edges_[i][0] << " " << edges_[i][1] << " " << edges_[i][2]
|
||||||
<< " nexts " << next_edge_[i][0] << " " << next_edge_[i][1] << " " << next_edge_[i][2] << endl;
|
<< " nexts " << next_edge_[i][0] << " " << next_edge_[i][1] << " " << next_edge_[i][2] << endl;
|
||||||
|
@ -26,6 +26,7 @@ class TriGraph {
|
|||||||
uint32_t vertices[3];
|
uint32_t vertices[3];
|
||||||
};
|
};
|
||||||
TriGraph(uint32_t nedges, uint32_t nvertices);
|
TriGraph(uint32_t nedges, uint32_t nvertices);
|
||||||
|
~TriGraph();
|
||||||
void AddEdge(const Edge& edge);
|
void AddEdge(const Edge& edge);
|
||||||
void RemoveEdge(uint32_t edge_id);
|
void RemoveEdge(uint32_t edge_id);
|
||||||
void ExtractEdgesAndClear(std::vector<Edge>* edges);
|
void ExtractEdgesAndClear(std::vector<Edge>* edges);
|
||||||
|
Loading…
Reference in New Issue
Block a user