Bullet Collision Detection & Physics Library
btHashMap.h
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16#ifndef BT_HASH_MAP_H
17#define BT_HASH_MAP_H
18
19#include <string>
21
24{
25 std::string m_string1;
26 unsigned int m_hash;
27
28 SIMD_FORCE_INLINE unsigned int getHash() const
29 {
30 return m_hash;
31 }
32
34 {
35 m_string1 = "";
36 m_hash = 0;
37 }
38 btHashString(const char* name)
39 : m_string1(name)
40 {
41 /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
42 static const unsigned int InitialFNV = 2166136261u;
43 static const unsigned int FNVMultiple = 16777619u;
44
45 /* Fowler / Noll / Vo (FNV) Hash */
46 unsigned int hash = InitialFNV;
47
48 for (int i = 0; m_string1.c_str()[i]; i++)
49 {
50 hash = hash ^ (m_string1.c_str()[i]); /* xor the low 8 bits */
51 hash = hash * FNVMultiple; /* multiply by the magic number */
52 }
53 m_hash = hash;
54 }
55
56 bool equals(const btHashString& other) const
57 {
58 return (m_string1 == other.m_string1);
59 }
60};
61
62const int BT_HASH_NULL = 0xffffffff;
63
65{
66 int m_uid;
67
68public:
70 {
71 }
72
73 btHashInt(int uid) : m_uid(uid)
74 {
75 }
76
77 int getUid1() const
78 {
79 return m_uid;
80 }
81
82 void setUid1(int uid)
83 {
84 m_uid = uid;
85 }
86
87 bool equals(const btHashInt& other) const
88 {
89 return getUid1() == other.getUid1();
90 }
91 //to our success
92 SIMD_FORCE_INLINE unsigned int getHash() const
93 {
94 unsigned int key = m_uid;
95 // Thomas Wang's hash
96 key += ~(key << 15);
97 key ^= (key >> 10);
98 key += (key << 3);
99 key ^= (key >> 6);
100 key += ~(key << 11);
101 key ^= (key >> 16);
102
103 return key;
104 }
105};
106
108{
109 union {
110 const void* m_pointer;
111 unsigned int m_hashValues[2];
112 };
113
114public:
115 btHashPtr(const void* ptr)
116 : m_pointer(ptr)
117 {
118 }
119
120 const void* getPointer() const
121 {
122 return m_pointer;
123 }
124
125 bool equals(const btHashPtr& other) const
126 {
127 return getPointer() == other.getPointer();
128 }
129
130 //to our success
131 SIMD_FORCE_INLINE unsigned int getHash() const
132 {
133 const bool VOID_IS_8 = ((sizeof(void*) == 8));
134
135 unsigned int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
136 // Thomas Wang's hash
137 key += ~(key << 15);
138 key ^= (key >> 10);
139 key += (key << 3);
140 key ^= (key >> 6);
141 key += ~(key << 11);
142 key ^= (key >> 16);
143 return key;
144 }
145};
146
147template <class Value>
149{
150 int m_uid;
151
152public:
153 btHashKeyPtr(int uid) : m_uid(uid)
154 {
155 }
156
157 int getUid1() const
158 {
159 return m_uid;
160 }
161
162 bool equals(const btHashKeyPtr<Value>& other) const
163 {
164 return getUid1() == other.getUid1();
165 }
166
167 //to our success
168 SIMD_FORCE_INLINE unsigned int getHash() const
169 {
170 unsigned int key = m_uid;
171 // Thomas Wang's hash
172 key += ~(key << 15);
173 key ^= (key >> 10);
174 key += (key << 3);
175 key ^= (key >> 6);
176 key += ~(key << 11);
177 key ^= (key >> 16);
178 return key;
179 }
180};
181
182template <class Value>
184{
185 int m_uid;
186
187public:
188 btHashKey(int uid) : m_uid(uid)
189 {
190 }
191
192 int getUid1() const
193 {
194 return m_uid;
195 }
196
197 bool equals(const btHashKey<Value>& other) const
198 {
199 return getUid1() == other.getUid1();
200 }
201 //to our success
202 SIMD_FORCE_INLINE unsigned int getHash() const
203 {
204 unsigned int key = m_uid;
205 // Thomas Wang's hash
206 key += ~(key << 15);
207 key ^= (key >> 10);
208 key += (key << 3);
209 key ^= (key >> 6);
210 key += ~(key << 11);
211 key ^= (key >> 16);
212 return key;
213 }
214};
215
218template <class Key, class Value>
220{
221protected:
224
227
228 void growTables(const Key& /*key*/)
229 {
230 int newCapacity = m_valueArray.capacity();
231
232 if (m_hashTable.size() < newCapacity)
233 {
234 //grow hashtable and next table
235 int curHashtableSize = m_hashTable.size();
236
237 m_hashTable.resize(newCapacity);
238 m_next.resize(newCapacity);
239
240 int i;
241
242 for (i = 0; i < newCapacity; ++i)
243 {
245 }
246 for (i = 0; i < newCapacity; ++i)
247 {
248 m_next[i] = BT_HASH_NULL;
249 }
250
251 for (i = 0; i < curHashtableSize; i++)
252 {
253 //const Value& value = m_valueArray[i];
254 //const Key& key = m_keyArray[i];
255
256 int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1); // New hash value with new mask
257 m_next[i] = m_hashTable[hashValue];
258 m_hashTable[hashValue] = i;
259 }
260 }
261 }
262
263public:
264 void insert(const Key& key, const Value& value)
265 {
266 int hash = key.getHash() & (m_valueArray.capacity() - 1);
267
268 //replace value if the key is already there
269 int index = findIndex(key);
270 if (index != BT_HASH_NULL)
271 {
272 m_valueArray[index] = value;
273 return;
274 }
275
276 int count = m_valueArray.size();
277 int oldCapacity = m_valueArray.capacity();
278 m_valueArray.push_back(value);
280
281 int newCapacity = m_valueArray.capacity();
282 if (oldCapacity < newCapacity)
283 {
284 growTables(key);
285 //hash with new capacity
286 hash = key.getHash() & (m_valueArray.capacity() - 1);
287 }
288 m_next[count] = m_hashTable[hash];
289 m_hashTable[hash] = count;
290 }
291
292 void remove(const Key& key)
293 {
294 int hash = key.getHash() & (m_valueArray.capacity() - 1);
295
296 int pairIndex = findIndex(key);
297
298 if (pairIndex == BT_HASH_NULL)
299 {
300 return;
301 }
302
303 // Remove the pair from the hash table.
304 int index = m_hashTable[hash];
305 btAssert(index != BT_HASH_NULL);
306
307 int previous = BT_HASH_NULL;
308 while (index != pairIndex)
309 {
310 previous = index;
311 index = m_next[index];
312 }
313
314 if (previous != BT_HASH_NULL)
315 {
316 btAssert(m_next[previous] == pairIndex);
317 m_next[previous] = m_next[pairIndex];
318 }
319 else
320 {
321 m_hashTable[hash] = m_next[pairIndex];
322 }
323
324 // We now move the last pair into spot of the
325 // pair being removed. We need to fix the hash
326 // table indices to support the move.
327
328 int lastPairIndex = m_valueArray.size() - 1;
329
330 // If the removed pair is the last pair, we are done.
331 if (lastPairIndex == pairIndex)
332 {
335 return;
336 }
337
338 // Remove the last pair from the hash table.
339 int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
340
341 index = m_hashTable[lastHash];
342 btAssert(index != BT_HASH_NULL);
343
344 previous = BT_HASH_NULL;
345 while (index != lastPairIndex)
346 {
347 previous = index;
348 index = m_next[index];
349 }
350
351 if (previous != BT_HASH_NULL)
352 {
353 btAssert(m_next[previous] == lastPairIndex);
354 m_next[previous] = m_next[lastPairIndex];
355 }
356 else
357 {
358 m_hashTable[lastHash] = m_next[lastPairIndex];
359 }
360
361 // Copy the last pair into the remove pair's spot.
362 m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
363 m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
364
365 // Insert the last pair into the hash table
366 m_next[pairIndex] = m_hashTable[lastHash];
367 m_hashTable[lastHash] = pairIndex;
368
371 }
372
373 int size() const
374 {
375 return m_valueArray.size();
376 }
377
378 const Value* getAtIndex(int index) const
379 {
380 btAssert(index < m_valueArray.size());
381 btAssert(index >= 0);
382 if (index >= 0 && index < m_valueArray.size())
383 {
384 return &m_valueArray[index];
385 }
386 return 0;
387 }
388
389 Value* getAtIndex(int index)
390 {
391 btAssert(index < m_valueArray.size());
392 btAssert(index >= 0);
393 if (index >= 0 && index < m_valueArray.size())
394 {
395 return &m_valueArray[index];
396 }
397 return 0;
398 }
399
400 Key getKeyAtIndex(int index)
401 {
402 btAssert(index < m_keyArray.size());
403 btAssert(index >= 0);
404 return m_keyArray[index];
405 }
406
407 const Key getKeyAtIndex(int index) const
408 {
409 btAssert(index < m_keyArray.size());
410 btAssert(index >= 0);
411 return m_keyArray[index];
412 }
413
414 Value* operator[](const Key& key)
415 {
416 return find(key);
417 }
418
419 const Value* operator[](const Key& key) const
420 {
421 return find(key);
422 }
423
424 const Value* find(const Key& key) const
425 {
426 int index = findIndex(key);
427 if (index == BT_HASH_NULL)
428 {
429 return NULL;
430 }
431 return &m_valueArray[index];
432 }
433
434 Value* find(const Key& key)
435 {
436 int index = findIndex(key);
437 if (index == BT_HASH_NULL)
438 {
439 return NULL;
440 }
441 return &m_valueArray[index];
442 }
443
444 int findIndex(const Key& key) const
445 {
446 unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
447
448 if (hash >= (unsigned int)m_hashTable.size())
449 {
450 return BT_HASH_NULL;
451 }
452
453 int index = m_hashTable[hash];
454 while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
455 {
456 index = m_next[index];
457 }
458 return index;
459 }
460
461 void clear()
462 {
464 m_next.clear();
467 }
468};
469
470#endif //BT_HASH_MAP_H
const int BT_HASH_NULL
Definition: btHashMap.h:62
#define SIMD_FORCE_INLINE
Definition: btScalar.h:98
#define btAssert(x)
Definition: btScalar.h:153
int size() const
return the number of elements in the array
void resize(int newsize, const T &fillData=T())
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
void push_back(const T &_Val)
int capacity() const
return the pre-allocated (reserved) elements, this is at least as large as the total number of elemen...
void setUid1(int uid)
Definition: btHashMap.h:82
btHashInt()
Definition: btHashMap.h:69
unsigned int getHash() const
Definition: btHashMap.h:92
btHashInt(int uid)
Definition: btHashMap.h:73
int m_uid
Definition: btHashMap.h:66
int getUid1() const
Definition: btHashMap.h:77
bool equals(const btHashInt &other) const
Definition: btHashMap.h:87
btHashKeyPtr(int uid)
Definition: btHashMap.h:153
bool equals(const btHashKeyPtr< Value > &other) const
Definition: btHashMap.h:162
int getUid1() const
Definition: btHashMap.h:157
unsigned int getHash() const
Definition: btHashMap.h:168
unsigned int getHash() const
Definition: btHashMap.h:202
btHashKey(int uid)
Definition: btHashMap.h:188
bool equals(const btHashKey< Value > &other) const
Definition: btHashMap.h:197
int m_uid
Definition: btHashMap.h:185
int getUid1() const
Definition: btHashMap.h:192
The btHashMap template class implements a generic and lightweight hashmap.
Definition: btHashMap.h:220
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:264
Key getKeyAtIndex(int index)
Definition: btHashMap.h:400
void clear()
Definition: btHashMap.h:461
int size() const
Definition: btHashMap.h:373
void growTables(const Key &)
Definition: btHashMap.h:228
Value * operator[](const Key &key)
Definition: btHashMap.h:414
int findIndex(const Key &key) const
Definition: btHashMap.h:444
const Key getKeyAtIndex(int index) const
Definition: btHashMap.h:407
Value * find(const Key &key)
Definition: btHashMap.h:434
void remove(const Key &key)
Definition: btHashMap.h:292
btAlignedObjectArray< int > m_hashTable
Definition: btHashMap.h:222
btAlignedObjectArray< int > m_next
Definition: btHashMap.h:223
const Value * getAtIndex(int index) const
Definition: btHashMap.h:378
btAlignedObjectArray< Key > m_keyArray
Definition: btHashMap.h:226
btAlignedObjectArray< Value > m_valueArray
Definition: btHashMap.h:225
const Value * find(const Key &key) const
Definition: btHashMap.h:424
Value * getAtIndex(int index)
Definition: btHashMap.h:389
const Value * operator[](const Key &key) const
Definition: btHashMap.h:419
const void * getPointer() const
Definition: btHashMap.h:120
btHashPtr(const void *ptr)
Definition: btHashMap.h:115
const void * m_pointer
Definition: btHashMap.h:110
bool equals(const btHashPtr &other) const
Definition: btHashMap.h:125
unsigned int getHash() const
Definition: btHashMap.h:131
unsigned int m_hashValues[2]
Definition: btHashMap.h:111
const bool VOID_IS_8
Definition: bChunk.h:81
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:24
bool equals(const btHashString &other) const
Definition: btHashMap.h:56
std::string m_string1
Definition: btHashMap.h:25
unsigned int getHash() const
Definition: btHashMap.h:28
btHashString(const char *name)
Definition: btHashMap.h:38
unsigned int m_hash
Definition: btHashMap.h:26