Pioneer
Loading...
Searching...
No Matches
Weld.h
Go to the documentation of this file.
1// This code is in the public domain -- castanyo@yahoo.es
2
3#ifndef NV_MESH_WELD_H
4#define NV_MESH_WELD_H
5
6#include "libs.h"
7
8// Weld function to remove array duplicates in linear time using hashing.
9
10namespace nv {
11
12 template <class T>
13 struct Equal {
14 bool operator()(const T &a, const T &b) const
15 {
16 return a == b;
17 }
18 };
19
21#define NIL Uint32(~0)
22
23 template <typename Key>
24 struct hash {
25 inline Uint32 sdbm_hash(const void *data_in, Uint32 size, Uint32 h = 5381)
26 {
27 const Uint8 *data = static_cast<const Uint8 *>(data_in);
28 Uint32 i = 0;
29 while (i < size) {
30 h = (h << 16) + (h << 6) - h + static_cast<Uint32>(data[i++]);
31 }
32 return h;
33 }
34
35 Uint32 operator()(const Key &k)
36 {
37 return sdbm_hash(&k, sizeof(Key));
38 }
39 };
40 template <>
41 struct hash<int> {
42 Uint32 operator()(int x) const { return x; }
43 };
44 template <>
45 struct hash<Uint32> {
46 Uint32 operator()(Uint32 x) const { return x; }
47 };
48
55 inline Uint32 nextPowerOfTwo(Uint32 x)
56 {
57 assert(x != 0);
58#if 1 // On modern CPUs this is supposed to be as fast as using the bsr instruction.
59 x--;
60 x |= x >> 1;
61 x |= x >> 2;
62 x |= x >> 4;
63 x |= x >> 8;
64 x |= x >> 16;
65 return x + 1;
66#else
67 Uint32 p = 1;
68 while (x > p) {
69 p += p;
70 }
71 return p;
72#endif
73 }
74
76 inline bool isPowerOfTwo(Uint32 n)
77 {
78 return (n & (n - 1)) == 0;
79 }
80
86 template <class T, class H = hash<T>, class E = Equal<T>>
87 struct Weld {
88 // xrefs maps old elements to new elements
89 Uint32 operator()(std::vector<T> &p, std::vector<Uint32> &xrefs)
90 {
91 const Uint32 N = p.size(); // # of input vertices.
92 Uint32 outputCount = 0; // # of output vertices
93 Uint32 hashSize = nextPowerOfTwo(N); // size of the hash table
94 Uint32 *hashTable = new Uint32[hashSize + N]; // hash table + linked list
95 Uint32 *next = hashTable + hashSize; // use bottom part as linked list
96
97 xrefs.resize(N);
98 memset(hashTable, NIL, (hashSize + N) * sizeof(Uint32)); // init hash table (NIL = 0xFFFFFFFF so memset works)
99
100 H hash;
101 E equal;
102 for (Uint32 i = 0; i < N; i++) {
103 const T &e = p[i];
104 const Uint32 hashValue = hash(e) & (hashSize - 1);
105 //const Uint32 hashValue = CodeSupHash(e) & (hashSize-1);
106 Uint32 offset = hashTable[hashValue];
107
108 // traverse linked list
109 while (offset != NIL && !equal(p[offset], e)) {
110 offset = next[offset];
111 }
112
113 xrefs[i] = offset;
114
115 // no match found - copy vertex & add to hash
116 if (offset == NIL) {
117 // save xref
118 xrefs[i] = outputCount;
119
120 // copy element
121 p[outputCount] = e;
122
123 // link to hash table
124 next[outputCount] = hashTable[hashValue];
125
126 // update hash heads and increase output counter
127 hashTable[hashValue] = outputCount++;
128 }
129 }
130
131 // cleanup
132 delete[] hashTable;
133
134 p.resize(outputCount);
135
136 // number of output vertices
137 return outputCount;
138 }
139 };
140
141} // namespace nv
142
143#endif // NV_MESH_WELD_H
#define NIL
Null index. @ Move this somewhere else... This could have collisions with other definitions!
Definition Weld.h:21
Definition Weld.h:10
Uint32 nextPowerOfTwo(Uint32 x)
Definition Weld.h:55
bool isPowerOfTwo(Uint32 n)
Return true if n is a power of two.
Definition Weld.h:76
Definition Weld.h:13
bool operator()(const T &a, const T &b) const
Definition Weld.h:14
Definition Weld.h:87
Uint32 operator()(std::vector< T > &p, std::vector< Uint32 > &xrefs)
Definition Weld.h:89
Uint32 operator()(Uint32 x) const
Definition Weld.h:46
Uint32 operator()(int x) const
Definition Weld.h:42
Definition Weld.h:24
Uint32 sdbm_hash(const void *data_in, Uint32 size, Uint32 h=5381)
Definition Weld.h:25
Uint32 operator()(const Key &k)
Definition Weld.h:35