2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
20 #include "btAlignedObjectArray.h"
22 ///very basic hashable string implementation, compatible with btHashMap
25 std::string m_string1;
28 SIMD_FORCE_INLINE unsigned int getHash() const
38 btHashString(const char* name)
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;
45 /* Fowler / Noll / Vo (FNV) Hash */
46 unsigned int hash = InitialFNV;
48 for (int i = 0; m_string1.c_str()[i]; i++)
50 hash = hash ^ (m_string1.c_str()[i]); /* xor the low 8 bits */
51 hash = hash * FNVMultiple; /* multiply by the magic number */
56 bool equals(const btHashString& other) const
58 return (m_string1 == other.m_string1);
62 const int BT_HASH_NULL = 0xffffffff;
73 btHashInt(int uid) : m_uid(uid)
87 bool equals(const btHashInt& other) const
89 return getUid1() == other.getUid1();
92 SIMD_FORCE_INLINE unsigned int getHash() const
94 unsigned int key = m_uid;
110 const void* m_pointer;
111 unsigned int m_hashValues[2];
115 btHashPtr(const void* ptr)
120 const void* getPointer() const
125 bool equals(const btHashPtr& other) const
127 return getPointer() == other.getPointer();
131 SIMD_FORCE_INLINE unsigned int getHash() const
133 const bool VOID_IS_8 = ((sizeof(void*) == 8));
135 unsigned int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
136 // Thomas Wang's hash
147 template <class Value>
153 btHashKeyPtr(int uid) : m_uid(uid)
162 bool equals(const btHashKeyPtr<Value>& other) const
164 return getUid1() == other.getUid1();
168 SIMD_FORCE_INLINE unsigned int getHash() const
170 unsigned int key = m_uid;
171 // Thomas Wang's hash
182 template <class Value>
188 btHashKey(int uid) : m_uid(uid)
197 bool equals(const btHashKey<Value>& other) const
199 return getUid1() == other.getUid1();
202 SIMD_FORCE_INLINE unsigned int getHash() const
204 unsigned int key = m_uid;
205 // Thomas Wang's hash
216 ///The btHashMap template class implements a generic and lightweight hashmap.
217 ///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
218 template <class Key, class Value>
222 btAlignedObjectArray<int> m_hashTable;
223 btAlignedObjectArray<int> m_next;
225 btAlignedObjectArray<Value> m_valueArray;
226 btAlignedObjectArray<Key> m_keyArray;
228 void growTables(const Key& /*key*/)
230 int newCapacity = m_valueArray.capacity();
232 if (m_hashTable.size() < newCapacity)
234 //grow hashtable and next table
235 int curHashtableSize = m_hashTable.size();
237 m_hashTable.resize(newCapacity);
238 m_next.resize(newCapacity);
242 for (i = 0; i < newCapacity; ++i)
244 m_hashTable[i] = BT_HASH_NULL;
246 for (i = 0; i < newCapacity; ++i)
248 m_next[i] = BT_HASH_NULL;
251 for (i = 0; i < curHashtableSize; i++)
253 //const Value& value = m_valueArray[i];
254 //const Key& key = m_keyArray[i];
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;
264 void insert(const Key& key, const Value& value)
266 int hash = key.getHash() & (m_valueArray.capacity() - 1);
268 //replace value if the key is already there
269 int index = findIndex(key);
270 if (index != BT_HASH_NULL)
272 m_valueArray[index] = value;
276 int count = m_valueArray.size();
277 int oldCapacity = m_valueArray.capacity();
278 m_valueArray.push_back(value);
279 m_keyArray.push_back(key);
281 int newCapacity = m_valueArray.capacity();
282 if (oldCapacity < newCapacity)
285 //hash with new capacity
286 hash = key.getHash() & (m_valueArray.capacity() - 1);
288 m_next[count] = m_hashTable[hash];
289 m_hashTable[hash] = count;
292 void remove(const Key& key)
294 int hash = key.getHash() & (m_valueArray.capacity() - 1);
296 int pairIndex = findIndex(key);
298 if (pairIndex == BT_HASH_NULL)
303 // Remove the pair from the hash table.
304 int index = m_hashTable[hash];
305 btAssert(index != BT_HASH_NULL);
307 int previous = BT_HASH_NULL;
308 while (index != pairIndex)
311 index = m_next[index];
314 if (previous != BT_HASH_NULL)
316 btAssert(m_next[previous] == pairIndex);
317 m_next[previous] = m_next[pairIndex];
321 m_hashTable[hash] = m_next[pairIndex];
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.
328 int lastPairIndex = m_valueArray.size() - 1;
330 // If the removed pair is the last pair, we are done.
331 if (lastPairIndex == pairIndex)
333 m_valueArray.pop_back();
334 m_keyArray.pop_back();
338 // Remove the last pair from the hash table.
339 int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
341 index = m_hashTable[lastHash];
342 btAssert(index != BT_HASH_NULL);
344 previous = BT_HASH_NULL;
345 while (index != lastPairIndex)
348 index = m_next[index];
351 if (previous != BT_HASH_NULL)
353 btAssert(m_next[previous] == lastPairIndex);
354 m_next[previous] = m_next[lastPairIndex];
358 m_hashTable[lastHash] = m_next[lastPairIndex];
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];
365 // Insert the last pair into the hash table
366 m_next[pairIndex] = m_hashTable[lastHash];
367 m_hashTable[lastHash] = pairIndex;
369 m_valueArray.pop_back();
370 m_keyArray.pop_back();
375 return m_valueArray.size();
378 const Value* getAtIndex(int index) const
380 btAssert(index < m_valueArray.size());
381 btAssert(index >= 0);
382 if (index >= 0 && index < m_valueArray.size())
384 return &m_valueArray[index];
389 Value* getAtIndex(int index)
391 btAssert(index < m_valueArray.size());
392 btAssert(index >= 0);
393 if (index >= 0 && index < m_valueArray.size())
395 return &m_valueArray[index];
400 Key getKeyAtIndex(int index)
402 btAssert(index < m_keyArray.size());
403 btAssert(index >= 0);
404 return m_keyArray[index];
407 const Key getKeyAtIndex(int index) const
409 btAssert(index < m_keyArray.size());
410 btAssert(index >= 0);
411 return m_keyArray[index];
414 Value* operator[](const Key& key)
419 const Value* operator[](const Key& key) const
424 const Value* find(const Key& key) const
426 int index = findIndex(key);
427 if (index == BT_HASH_NULL)
431 return &m_valueArray[index];
434 Value* find(const Key& key)
436 int index = findIndex(key);
437 if (index == BT_HASH_NULL)
441 return &m_valueArray[index];
444 int findIndex(const Key& key) const
446 unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
448 if (hash >= (unsigned int)m_hashTable.size())
453 int index = m_hashTable[hash];
454 while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
456 index = m_next[index];
465 m_valueArray.clear();
470 #endif //BT_HASH_MAP_H