trivalize data structure

This commit is contained in:
Andreas Fabri 2020-04-10 12:20:08 +01:00
parent e5d1739608
commit a79c6720c7
2 changed files with 36 additions and 120 deletions

View File

@ -783,7 +783,7 @@ void add_faces(const RangeofVertexRange& faces_to_add, PolygonMesh& pm)
typedef boost::container::small_vector<halfedge_descriptor,8> Halfedges; typedef boost::container::small_vector<halfedge_descriptor,8> Halfedges;
#else #else
//typedef boost::unordered_map<vertex_descriptor, halfedge_descriptor, boost::hash<vertex_descriptor> > Halfedges; //typedef boost::unordered_map<vertex_descriptor, halfedge_descriptor, boost::hash<vertex_descriptor> > Halfedges;
typedef Small_unordered_mapV2<vertex_descriptor, halfedge_descriptor, boost::hash<vertex_descriptor>,8,1> Halfedges; typedef Small_unordered_mapV2<vertex_descriptor, halfedge_descriptor, 8> Halfedges;
#endif #endif
typedef typename CGAL::GetInitializedVertexIndexMap<PolygonMesh>::type Vid_map; typedef typename CGAL::GetInitializedVertexIndexMap<PolygonMesh>::type Vid_map;

View File

@ -21,96 +21,47 @@
namespace CGAL { namespace CGAL {
template <typename K, typename T, typename H, unsigned int M, unsigned int Factor> template <typename K, typename T, int M>
class Small_unordered_mapV2 { class Small_unordered_mapV2 {
#ifdef CGAL_SMALL_UNORDERED_MAP_STATS
std::array<int, 20> collisions = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; std::array<std::pair<K, T>, M> data;
#endif
static constexpr int B = M * Factor ; // the number of bins
int head = B;
// mutable std::array<boost::int8_t, B> occupied {}; // all 0
mutable std::bitset<B> occupied;
std::array<std::pair<K, T>, B> data;
const H hash = {};
boost::unordered_map<K, T> * big = nullptr; boost::unordered_map<K, T> * big = nullptr;
std::size_t N = 0; // the number of stored elements int N = 0; // the number of stored elements
public: public:
Small_unordered_mapV2() Small_unordered_mapV2()
{} {}
#ifdef CGAL_SMALL_UNORDERED_MAP_STATS
~Small_unordered_mapV2()
{
std::cout << "N = "<< N << std::endl;
int total = 0;
std::cout << "0 " << collisions[0] << std::endl;
for (int i = 1; i < 20; i++) {
total += collisions[i];
if (collisions[i] != 0) {
std::cout << i << " " << collisions[i] << std::endl;
}
}
std::cout << "Total: " << total << " " << 100 * (double(total) / double(total + collisions[0])) << "%" << std::endl;
}
#else
~Small_unordered_mapV2() ~Small_unordered_mapV2()
{ {
if(big != nullptr){ if(big != nullptr){
delete big; delete big;
} }
} }
#endif
/// Set only once for a key /// Set only once for a key
void set(const K& k, const T& t) void set(const K& k, const T& t)
{ {
if (N < M) { if (N < M) {
unsigned int h = hash(k) % B; data[N].first = k;
unsigned i = h; data[N].second = t;
#ifdef CGAL_SMALL_UNORDERED_MAP_STATS
int collision = 0;
#endif
do {
if (occupied[i] == false) {
occupied[i] = true;
data[i].first = k;
data[i].second = t;
if(i < head){
head = i;
}
#ifdef CGAL_SMALL_UNORDERED_MAP_STATS
if (collision > 19) {
std::cerr << collision << " collisions" << std::endl;
}
else {
++collisions[collision];
}
#endif
++N; ++N;
return; }else{
} if (N == M) {
i = (i + 1) % B;
#ifdef CGAL_SMALL_UNORDERED_MAP_STATS
++collision;
#endif
} while (i != h);
CGAL_error();
}
else if (N == M) {
big = new boost::unordered_map<K, T>(); big = new boost::unordered_map<K, T>();
for(int pos = head; pos < B; ++pos){ for(int pos = 0; pos < M; ++pos){
if(occupied[pos]){
big->insert(data[pos]); big->insert(data[pos]);
} }
}
(*big)[k] = t; (*big)[k] = t;
} }else{
else {
(*big)[k] = t; (*big)[k] = t;
} }
++N; ++N;
} }
}
void insert(const std::pair<K,T>& p) void insert(const std::pair<K,T>& p)
@ -119,44 +70,19 @@ public:
} }
const T& at(const K& k) const
{
if (N <= M) {
unsigned int h = hash(k) % B;
unsigned int i = h;
do {
if ((occupied[i]) && (data[i].first == k)) {
return data[i].second;
}
i = (i + 1) % B;
} while (i != h);
CGAL_error();
}
else {
return big.at(k);
}
}
struct const_iterator; struct const_iterator;
const_iterator find(const K& k) const const_iterator find(const K& k) const
{ {
if (N <= M) { if (N <= M) {
unsigned int h = hash(k) % B; for(int i =0; i < M; ++i){
unsigned int i = h;
do {
if(! occupied[i]){
// the element is not in the map
return end();
}
if (data[i].first == k) { if (data[i].first == k) {
return const_iterator(*this,i); return const_iterator(*this,i);
} }
i = (i + 1) % B;
} while (i != h);
CGAL_error();
} }
else { return end();
}else{
return const_iterator(*this, big->find(k)); return const_iterator(*this, big->find(k));
} }
} }
@ -170,18 +96,6 @@ public:
return N; return N;
} }
/*
void clear()
{
head = B;
// occupied.fill(0);
if(big != nullptr){
delete big;
big = nullptr;
}
N = 0;
}
*/
struct const_iterator { struct const_iterator {
typedef std::pair<K, T> value_type; typedef std::pair<K, T> value_type;
@ -198,7 +112,7 @@ public:
bool big = false; bool big = false;
const_iterator(const Small_unordered_mapV2& map) const_iterator(const Small_unordered_mapV2& map)
: map(map), pos(B), big(map.N > M) : map(map), pos(M), big(map.N > M)
{ {
if(big){ if(big){
bigit = map.big->end(); bigit = map.big->end();
@ -214,7 +128,7 @@ public:
} }
const_iterator(const Small_unordered_mapV2& map, const Bigit& bigit) const_iterator(const Small_unordered_mapV2& map, const Bigit& bigit)
: map(map), pos(B), bigit(bigit), big(true) : map(map), pos(M), bigit(bigit), big(true)
{} {}
bool operator==(const const_iterator& other) const bool operator==(const const_iterator& other) const
@ -234,12 +148,11 @@ public:
{ {
if (big) { if (big) {
++bigit; ++bigit;
} else { } else if(pos < map.N-1){
if(pos != B){
do {
++pos; ++pos;
}while((pos !=B) && (! map.occupied[pos])); }else {
} CGAL_assertion((pos == map.N-1) || (pos = M));
pos = M;
} }
return *this; return *this;
} }
@ -258,7 +171,10 @@ public:
const_iterator begin() const const_iterator begin() const
{ {
return const_iterator(*this, head); if(N==0){
return const_iterator(*this);
}
return const_iterator(*this, 0);
} }
const_iterator end() const const_iterator end() const