Bullet Collision Detection & Physics Library: btHashMap.h Source File

Bullet Collision Detection & Physics Library

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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>
20#include "btAlignedObjectArray.h"
21
23 struct btHashString
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
33 btHashString()
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
62 const int BT_HASH_NULL = 0xffffffff;
63
64 class btHashInt
65{
66 int m_uid;
67
68public:
69 btHashInt()
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
107 class btHashPtr
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>
148 class btHashKeyPtr
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>
183 class btHashKey
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>
219 class btHashMap
220{
221protected:
222 btAlignedObjectArray<int> m_hashTable;
223 btAlignedObjectArray<int> m_next;
224
225 btAlignedObjectArray<Value> m_valueArray;
226 btAlignedObjectArray<Key> m_keyArray;
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 {
244 m_hashTable[i] = BT_HASH_NULL;
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);
279 m_keyArray.push_back(key);
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 {
333 m_valueArray.pop_back();
334 m_keyArray.pop_back();
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
369 m_valueArray.pop_back();
370 m_keyArray.pop_back();
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 {
463 m_hashTable.clear();
464 m_next.clear();
465 m_valueArray.clear();
466 m_keyArray.clear();
467 }
468};
469
470#endif //BT_HASH_MAP_H
btAlignedObjectArray.h
BT_HASH_NULL
const int BT_HASH_NULL
Definition btHashMap.h:62
SIMD_FORCE_INLINE
#define SIMD_FORCE_INLINE
Definition btScalar.h:98
btAssert
#define btAssert(x)
Definition btScalar.h:153
btAlignedObjectArray
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
Definition btAlignedObjectArray.h:46
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition btAlignedObjectArray.h:142
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition btAlignedObjectArray.h:203
btAlignedObjectArray::clear
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
Definition btAlignedObjectArray.h:176
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition btAlignedObjectArray.h:257
btAlignedObjectArray::capacity
int capacity() const
return the pre-allocated (reserved) elements, this is at least as large as the total number of elemen...
Definition btAlignedObjectArray.h:275
btAlignedObjectArray::pop_back
void pop_back()
Definition btAlignedObjectArray.h:185
btHashInt
Definition btHashMap.h:65
btHashInt::setUid1
void setUid1(int uid)
Definition btHashMap.h:82
btHashInt::btHashInt
btHashInt()
Definition btHashMap.h:69
btHashInt::getHash
unsigned int getHash() const
Definition btHashMap.h:92
btHashInt::btHashInt
btHashInt(int uid)
Definition btHashMap.h:73
btHashInt::m_uid
int m_uid
Definition btHashMap.h:66
btHashInt::getUid1
int getUid1() const
Definition btHashMap.h:77
btHashInt::equals
bool equals(const btHashInt &other) const
Definition btHashMap.h:87
btHashKeyPtr
Definition btHashMap.h:149
btHashKeyPtr::m_uid
int m_uid
Definition btHashMap.h:150
btHashKeyPtr::btHashKeyPtr
btHashKeyPtr(int uid)
Definition btHashMap.h:153
btHashKeyPtr::equals
bool equals(const btHashKeyPtr< Value > &other) const
Definition btHashMap.h:162
btHashKeyPtr::getUid1
int getUid1() const
Definition btHashMap.h:157
btHashKeyPtr::getHash
unsigned int getHash() const
Definition btHashMap.h:168
btHashKey
Definition btHashMap.h:184
btHashKey::getHash
unsigned int getHash() const
Definition btHashMap.h:202
btHashKey::btHashKey
btHashKey(int uid)
Definition btHashMap.h:188
btHashKey::equals
bool equals(const btHashKey< Value > &other) const
Definition btHashMap.h:197
btHashKey::m_uid
int m_uid
Definition btHashMap.h:185
btHashKey::getUid1
int getUid1() const
Definition btHashMap.h:192
btHashMap
The btHashMap template class implements a generic and lightweight hashmap.
Definition btHashMap.h:220
btHashMap::insert
void insert(const Key &key, const Value &value)
Definition btHashMap.h:264
btHashMap::getKeyAtIndex
Key getKeyAtIndex(int index)
Definition btHashMap.h:400
btHashMap::clear
void clear()
Definition btHashMap.h:461
btHashMap::size
int size() const
Definition btHashMap.h:373
btHashMap::growTables
void growTables(const Key &)
Definition btHashMap.h:228
btHashMap::operator[]
Value * operator[](const Key &key)
Definition btHashMap.h:414
btHashMap::findIndex
int findIndex(const Key &key) const
Definition btHashMap.h:444
btHashMap::getKeyAtIndex
const Key getKeyAtIndex(int index) const
Definition btHashMap.h:407
btHashMap::find
Value * find(const Key &key)
Definition btHashMap.h:434
btHashMap::remove
void remove(const Key &key)
Definition btHashMap.h:292
btHashMap::m_hashTable
btAlignedObjectArray< int > m_hashTable
Definition btHashMap.h:222
btHashMap::m_next
btAlignedObjectArray< int > m_next
Definition btHashMap.h:223
btHashMap::getAtIndex
const Value * getAtIndex(int index) const
Definition btHashMap.h:378
btHashMap::m_keyArray
btAlignedObjectArray< Key > m_keyArray
Definition btHashMap.h:226
btHashMap::m_valueArray
btAlignedObjectArray< Value > m_valueArray
Definition btHashMap.h:225
btHashMap::find
const Value * find(const Key &key) const
Definition btHashMap.h:424
btHashMap::getAtIndex
Value * getAtIndex(int index)
Definition btHashMap.h:389
btHashMap::operator[]
const Value * operator[](const Key &key) const
Definition btHashMap.h:419
btHashPtr
Definition btHashMap.h:108
btHashPtr::getPointer
const void * getPointer() const
Definition btHashMap.h:120
btHashPtr::btHashPtr
btHashPtr(const void *ptr)
Definition btHashMap.h:115
btHashPtr::m_pointer
const void * m_pointer
Definition btHashMap.h:110
btHashPtr::equals
bool equals(const btHashPtr &other) const
Definition btHashMap.h:125
btHashPtr::getHash
unsigned int getHash() const
Definition btHashMap.h:131
btHashPtr::m_hashValues
unsigned int m_hashValues[2]
Definition btHashMap.h:111
btHashString
very basic hashable string implementation, compatible with btHashMap
Definition btHashMap.h:24
btHashString::equals
bool equals(const btHashString &other) const
Definition btHashMap.h:56
btHashString::m_string1
std::string m_string1
Definition btHashMap.h:25
btHashString::getHash
unsigned int getHash() const
Definition btHashMap.h:28
btHashString::btHashString
btHashString()
Definition btHashMap.h:33
btHashString::btHashString
btHashString(const char *name)
Definition btHashMap.h:38
btHashString::m_hash
unsigned int m_hash
Definition btHashMap.h:26