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