1
Fork 0

All tests pass.

main
Davi Reis 2012-04-15 00:03:00 -03:00
parent bcf4962604
commit 48155e5b66
19 changed files with 128 additions and 102 deletions

View File

@ -21,8 +21,8 @@ fi
if test "x$ac_cv_sys_largefile_LIBS" = "xno" ; then
ac_cv_sys_largefile_LIBS=""
fi
CFLAGS="$CFLAGS $ac_cv_sys_largefile_CFLAGS"
LDFLAGS="$LDFLAGS $ac_cv_sys_largefile_LDFLAGS"
CFLAGS="$$ac_cv_sys_largefile_CFLAGS $CFLAGS"
LDFLAGS="$ac_cv_sys_largefile_LDFLAGS $LDFLAGS"
LIBS="$LIBS $ac_cv_sys_largefile_LIBS"
dnl Checks for headers
@ -34,6 +34,7 @@ LDFLAGS="$LIBM $LDFLAGS"
CFLAGS="-Wall -Werror"
AC_PROG_CXX
CXXFLAGS="-Wall -Winline -Wno-unused-function -Werror -DNDEBUG -O3 -fomit-frame-pointer $CXXFLAGS"
AC_ENABLE_CXXMPH
if test x$cxxmph = xtrue; then
AC_COMPILE_STDCXX_0X

View File

@ -3,7 +3,7 @@ check_PROGRAMS = seeded_hash_test mph_bits_test hollow_iterator_test mph_map_tes
noinst_PROGRAMS = bm_index bm_map
bin_PROGRAMS = cxxmph
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
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

View File

@ -106,7 +106,7 @@ namespace cxxmph {
}
/* 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]);
if (!bm->SetUp()) {
cerr << "Set up phase for benchmark "

View File

@ -14,6 +14,7 @@ using std::vector;
namespace cxxmph {
UrlsBenchmark::~UrlsBenchmark() {}
bool UrlsBenchmark::SetUp() {
vector<string> urls;
std::ifstream f(urls_file_.c_str());
@ -32,12 +33,13 @@ bool UrlsBenchmark::SetUp() {
return true;
}
SearchUrlsBenchmark::~SearchUrlsBenchmark() {}
bool SearchUrlsBenchmark::SetUp() {
if (!UrlsBenchmark::SetUp()) return false;
int32_t miss_ratio_int32 = std::numeric_limits<int32_t>::max() * miss_ratio_;
forced_miss_urls_.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()];
if (random() < miss_ratio_int32) {
forced_miss_urls_[i] = random_[i].as_string() + ".force_miss";
@ -47,9 +49,10 @@ bool SearchUrlsBenchmark::SetUp() {
return true;
}
Uint64Benchmark::~Uint64Benchmark() {}
bool Uint64Benchmark::SetUp() {
set<uint64_t> unique;
for (int i = 0; i < count_; ++i) {
for (uint32_t i = 0; i < count_; ++i) {
uint64_t v;
do { v = random(); } while (unique.find(v) != unique.end());
values_.push_back(v);
@ -58,10 +61,11 @@ bool Uint64Benchmark::SetUp() {
return true;
}
SearchUint64Benchmark::~SearchUint64Benchmark() {}
bool SearchUint64Benchmark::SetUp() {
if (!Uint64Benchmark::SetUp()) return false;
random_.resize(nsearches_);
for (int i = 0; i < nsearches_; ++i) {
for (uint32_t i = 0; i < nsearches_; ++i) {
uint32_t pos = random() % values_.size();
random_[i] = values_[pos];
}

View File

@ -25,7 +25,7 @@ namespace cxxmph {
class UrlsBenchmark : public Benchmark {
public:
UrlsBenchmark(const std::string& urls_file) : urls_file_(urls_file) { }
virtual ~UrlsBenchmark() {}
virtual ~UrlsBenchmark();
protected:
virtual bool SetUp();
const std::string urls_file_;
@ -36,7 +36,7 @@ class SearchUrlsBenchmark : public UrlsBenchmark {
public:
SearchUrlsBenchmark(const std::string& urls_file, uint32_t nsearches, float miss_ratio)
: UrlsBenchmark(urls_file), nsearches_(nsearches), miss_ratio_(miss_ratio) {}
virtual ~SearchUrlsBenchmark() {}
virtual ~SearchUrlsBenchmark();
protected:
virtual bool SetUp();
const uint32_t nsearches_;
@ -48,6 +48,7 @@ class SearchUrlsBenchmark : public UrlsBenchmark {
class Uint64Benchmark : public Benchmark {
public:
Uint64Benchmark(uint32_t count) : count_(count) { }
virtual ~Uint64Benchmark();
virtual void Run() {}
protected:
virtual bool SetUp();
@ -59,6 +60,7 @@ class SearchUint64Benchmark : public Uint64Benchmark {
public:
SearchUint64Benchmark(uint32_t count, uint32_t nsearches)
: Uint64Benchmark(count), nsearches_(nsearches) { }
virtual ~SearchUint64Benchmark();
virtual void Run() {};
protected:
virtual bool SetUp();

View File

@ -47,7 +47,7 @@ class BM_MPHIndexSearch : public SearchUrlsBenchmark {
for (auto it = random_.begin(); it != random_.end(); ++it) {
auto idx = index_.index(*it);
// 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:

View File

@ -42,7 +42,7 @@ class BM_SearchUrls : public SearchUrlsBenchmark {
virtual ~BM_SearchUrls() {}
virtual void Run() {
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(!v || *v == *it);
}
@ -66,12 +66,12 @@ class BM_SearchUint64 : public SearchUint64Benchmark {
BM_SearchUint64() : SearchUint64Benchmark(100000, 10*1000*1000) { }
virtual bool SetUp() {
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_.rehash(mymap_.bucket_count());
// 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;
}
return true;
@ -80,7 +80,7 @@ class BM_SearchUint64 : public SearchUint64Benchmark {
for (auto it = random_.begin(); it != random_.end(); ++it) {
auto v = myfind(mymap_, *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);
}
}

View File

@ -57,10 +57,10 @@ int main(int argc, char** argv) {
ifstream f(argv[optind]);
string 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;
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 end = table.end();
for (int i = 0; it != end; ++it, ++i) {

View File

@ -5,66 +5,65 @@
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
: public std::iterator<std::forward_iterator_tag,
typename container_type::value_type> {
typedef presence_type presence;
typedef container_type container;
typedef iterator_type iterator;
typedef hollow_iterator_base<container, presence, iterator>& self_reference;
typename iterator::value_type> {
public:
typedef hollow_iterator_base<iterator, is_empty>& self_type;
typedef self_type& self_reference;
typedef typename iterator::reference reference;
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_; }
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 <class T>
bool operator==(const T& rhs) { return rhs.it_ == this->it_; }
template <class T>
bool operator!=(const T& rhs) { return rhs.it_ != this->it_; }
template <typename const_iterator>
bool operator==(const hollow_iterator_base<const_iterator, is_empty>& rhs) { return rhs.it_ == it_; }
template <typename const_iterator>
bool operator!=(const hollow_iterator_base<const_iterator, is_empty>& rhs) { return rhs.it_ != it_; }
public: // TODO find syntax to make this friend of const iterator
void find_present() {
while (it_ != c_->end() && !((*p_)[it_-c_->begin()])) ++it_;
}
container* c_;
presence* p_;
// should be friend
iterator it_;
is_empty empty_;
private:
void advance() {
while (empty_(it_)) ++it_;
}
};
template <typename container_type>
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)
: 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) { }
};
template <typename container_type, typename iterator> auto make_hollow(
container_type* v, vector<bool>* p, iterator it) ->
hollow_iterator_base<iterator, is_empty<container_type>> {
return hollow_iterator_base<iterator, is_empty<container_type>>(
it, is_empty<container_type>(v, p));
}
} // namespace cxxmph

View File

@ -1,12 +1,16 @@
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <iostream>
#include "hollow_iterator.h"
using std::cerr;
using std::endl;
using std::vector;
using cxxmph::hollow_iterator;
using cxxmph::hollow_const_iterator;
#include "hollow_iterator.h"
using cxxmph::hollow_iterator_base;
using cxxmph::make_hollow;
using cxxmph::is_empty;
int main(int argc, char** argv) {
vector<int> v;
@ -15,24 +19,27 @@ int main(int argc, char** argv) {
v.push_back(i);
p.push_back(i % 2 == 0);
}
auto begin = hollow_iterator<vector<int>>(&v, &p, v.begin());
auto end = hollow_iterator<vector<int>>(&v, &p, v.end());
auto begin = make_hollow(&v, &p, v.begin());
auto end = make_hollow(&v, &p, v.end());
for (auto it = begin; it != end; ++it) {
if (((*it) % 2) != 0) exit(-1);
}
hollow_const_iterator<vector<int>> const_begin(begin);
hollow_const_iterator<vector<int>> const_end(end);
for (auto it = const_begin; it != const_end; ++it) {
const vector<int>* cv(&v);
auto cbegin(make_hollow(cv, &p, cv->begin()));
auto cend(make_hollow(cv, &p, cv->begin()));
for (auto it = cbegin; it != cend; ++it) {
if (((*it) % 2) != 0) exit(-1);
}
vector<int>::iterator vit1 = v.begin();
vector<int>::const_iterator vit2 = v.begin();
if (vit1 != vit2) exit(-1);
auto it1 = hollow_iterator<vector<int>>(&v, &p, v.begin());
auto it2 = hollow_const_iterator<vector<int>>(&v, &p, v.begin());
auto it1 = make_hollow(&v, &p, vit1);
auto it2 = make_hollow(&v, &p, vit2);
if (it1 != it2) exit(-1);
hollow_iterator<vector<int>> default_constructed;
default_constructed = hollow_iterator<vector<int>>(&v, &p, v.begin());
typedef is_empty<vector<int>> iev;
hollow_iterator_base<vector<int>::iterator, iev> default_constructed;
default_constructed = make_hollow(&v, &p, v.begin());
return 0;
}

View File

@ -3,6 +3,10 @@
namespace cxxmph {
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 {
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]; }
void stop_unused_warning() {
rank64(4);
nextpoweroftwo(4);
}
}

View File

@ -17,10 +17,9 @@ namespace cxxmph {
class dynamic_2bitset {
public:
dynamic_2bitset() : size_(0), fill_(false) {}
dynamic_2bitset(uint32_t size, bool fill = false)
: size_(size), fill_(fill), data_(ceil(size / 4.0), ones()*fill) {
}
dynamic_2bitset();
~dynamic_2bitset();
dynamic_2bitset(uint32_t size, bool fill = false);
const uint8_t operator[](uint32_t i) const { return get(i); }
const uint8_t get(uint32_t i) const {
@ -28,7 +27,7 @@ class dynamic_2bitset {
assert((i >> 2) < data_.size());
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());
data_[(i >> 2)] |= ones() ^ 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) {
if (k == 0) return 1;
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;
}
// Interesting bit tricks that might end up here:

View File

@ -5,34 +5,35 @@
using cxxmph::dynamic_2bitset;
using cxxmph::rank64;
using cxxmph::nextpoweroftwo;
int main(int argc, char** argv) {
dynamic_2bitset small(256, true);
for (int 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) small.set(i, i % 4);
for (uint32_t i = 0; i < small.size(); ++i) {
if (small[i] != i % 4) {
fprintf(stderr, "wrong bits %d at %d expected %d\n", small[i], i, i % 4);
exit(-1);
}
}
int size = 256;
uint32_t size = 256;
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) {
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, 3);
exit(-1);
}
}
for (int i = 0; i < size; ++i) bits.set(i, 0);
for (int i = 0; i < size; ++i) {
for (uint32_t i = 0; i < size; ++i) bits.set(i, 0);
for (uint32_t i = 0; i < size; ++i) {
if (bits[i] != 0) {
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, 0);
exit(-1);
}
}
for (int 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) bits.set(i, i % 4);
for (uint32_t i = 0; i < size; ++i) {
if (bits[i] != i % 4) {
fprintf(stderr, "wrong bits %d at %d expected %d\n", bits[i], i, i % 4);
exit(-1);
@ -44,7 +45,7 @@ int main(int argc, char** argv) {
if (size_corner2.size() != 2) exit(-1);
(dynamic_2bitset(4, true)).swap(size_corner2);
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);
}
size_corner2.clear();
@ -54,6 +55,8 @@ int main(int argc, char** argv) {
empty.clear();
dynamic_2bitset large(1000, true);
empty.swap(large);
if (nextpoweroftwo(3) != 4) exit(-1);
if (rank64(0) != 0) exit(-1);
if (rank64(1) != 1) exit(-1);

View File

@ -128,7 +128,7 @@ bool MPHIndex::Reset(
nest_displacement_[0] = 0;
nest_displacement_[1] = r_;
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_;
k_ = 1U << b_;

View File

@ -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_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_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> >
class mph_map {
@ -72,10 +73,10 @@ class mph_map {
void erase(iterator pos);
void erase(const key_type& k);
pair<iterator, bool> insert(const value_type& x);
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
inline iterator find(const key_type& k);
inline const_iterator find(const key_type& k) const;
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);
const data_type& operator[](const key_type &k) const;
@ -149,7 +150,7 @@ MPH_MAP_METHOD_DECL(void_type, pack)() {
bool success = index_.Reset(
make_iterator_first(begin()),
make_iterator_first(end()), size_);
assert(success);
if (!success) { exit(-1); }
std::vector<value_type> new_values(index_.minimal_perfect_hash_size());
new_values.reserve(new_values.size() * 2);
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);
}
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 it = begin() + idx;
if (idx == -1 || it->first != k) return end();
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 it = begin() + idx;
if (idx == -1 || it->first != k) return end();
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)) {
auto sit = slack_.find(hasher128_.hash128(k, 0));
if (sit != slack_.end()) return sit->second;

View File

@ -88,6 +88,7 @@ struct Murmur3Fmix64bitsType {
h128 h;
h.set64(fmix(k), 0);
h.set64(fmix(h.get64(0)), 1);
return h;
}
};

View File

@ -26,7 +26,7 @@ int main(int argc, char** argv) {
for (int i = 0; i < 1000; ++i) if (g[i] != i) exit(-1);
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) {
auto h = inthasher.hash128(i, 0);
if (g2.find(h) != g2.end()) {

View File

@ -20,6 +20,7 @@ TriGraph::TriGraph(uint32_t nvertices, uint32_t nedges)
next_edge_(nedges),
first_edge_(nvertices, kInvalidEdge),
vertex_degree_(nvertices, 0) { }
TriGraph::~TriGraph() {}
void TriGraph::ExtractEdgesAndClear(vector<Edge>* edges) {
vector<Edge>().swap(next_edge_);
@ -67,7 +68,7 @@ void TriGraph::RemoveEdge(uint32_t current_edge) {
}
void TriGraph::DebugGraph() const {
int i;
uint32_t i;
for(i = 0; i < edges_.size(); i++){
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;

View File

@ -26,6 +26,7 @@ class TriGraph {
uint32_t vertices[3];
};
TriGraph(uint32_t nedges, uint32_t nvertices);
~TriGraph();
void AddEdge(const Edge& edge);
void RemoveEdge(uint32_t edge_id);
void ExtractEdgesAndClear(std::vector<Edge>* edges);