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
28
SIMD_FORCE_INLINE unsigned int getHash()const
33
btHashString(const char* name)
36
/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
37
static const unsigned int InitialFNV = 2166136261u;
38
static const unsigned int FNVMultiple = 16777619u;
40
/* Fowler / Noll / Vo (FNV) Hash */
41
unsigned int hash = InitialFNV;
43
for(int i = 0; m_string[i]; i++)
45
hash = hash ^ (m_string[i]); /* xor the low 8 bits */
46
hash = hash * FNVMultiple; /* multiply by the magic number */
51
int portableStringCompare(const char* src, const char* dst) const
55
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
66
bool equals(const btHashString& other) const
68
return (m_string == other.m_string) ||
69
(0==portableStringCompare(m_string,other.m_string));
75
const int BT_HASH_NULL=0xffffffff;
82
btHashInt(int uid) :m_uid(uid)
96
bool equals(const btHashInt& other) const
98
return getUid1() == other.getUid1();
101
SIMD_FORCE_INLINE unsigned int getHash()const
104
// Thomas Wang's hash
105
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
117
const void* m_pointer;
123
btHashPtr(const void* ptr)
128
const void* getPointer() const
133
bool equals(const btHashPtr& other) const
135
return getPointer() == other.getPointer();
139
SIMD_FORCE_INLINE unsigned int getHash()const
141
const bool VOID_IS_8 = ((sizeof(void*)==8));
143
int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
145
// Thomas Wang's hash
146
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
154
template <class Value>
160
btHashKeyPtr(int uid) :m_uid(uid)
169
bool equals(const btHashKeyPtr<Value>& other) const
171
return getUid1() == other.getUid1();
175
SIMD_FORCE_INLINE unsigned int getHash()const
178
// Thomas Wang's hash
179
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
187
template <class Value>
193
btHashKey(int uid) :m_uid(uid)
202
bool equals(const btHashKey<Value>& other) const
204
return getUid1() == other.getUid1();
207
SIMD_FORCE_INLINE unsigned int getHash()const
210
// Thomas Wang's hash
211
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
217
///The btHashMap template class implements a generic and lightweight hashmap.
218
///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
219
template <class Key, class Value>
224
btAlignedObjectArray<int> m_hashTable;
225
btAlignedObjectArray<int> m_next;
227
btAlignedObjectArray<Value> m_valueArray;
228
btAlignedObjectArray<Key> m_keyArray;
230
void growTables(const Key& /*key*/)
232
int newCapacity = m_valueArray.capacity();
234
if (m_hashTable.size() < newCapacity)
236
//grow hashtable and next table
237
int curHashtableSize = m_hashTable.size();
239
m_hashTable.resize(newCapacity);
240
m_next.resize(newCapacity);
244
for (i= 0; i < newCapacity; ++i)
246
m_hashTable[i] = BT_HASH_NULL;
248
for (i = 0; i < newCapacity; ++i)
250
m_next[i] = BT_HASH_NULL;
253
for(i=0;i<curHashtableSize;i++)
255
//const Value& value = m_valueArray[i];
256
//const Key& key = m_keyArray[i];
258
int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
259
m_next[i] = m_hashTable[hashValue];
260
m_hashTable[hashValue] = i;
269
void insert(const Key& key, const Value& value) {
270
int hash = key.getHash() & (m_valueArray.capacity()-1);
272
//replace value if the key is already there
273
int index = findIndex(key);
274
if (index != BT_HASH_NULL)
276
m_valueArray[index]=value;
280
int count = m_valueArray.size();
281
int oldCapacity = m_valueArray.capacity();
282
m_valueArray.push_back(value);
283
m_keyArray.push_back(key);
285
int newCapacity = m_valueArray.capacity();
286
if (oldCapacity < newCapacity)
289
//hash with new capacity
290
hash = key.getHash() & (m_valueArray.capacity()-1);
292
m_next[count] = m_hashTable[hash];
293
m_hashTable[hash] = count;
296
void remove(const Key& key) {
298
int hash = key.getHash() & (m_valueArray.capacity()-1);
300
int pairIndex = findIndex(key);
302
if (pairIndex ==BT_HASH_NULL)
307
// Remove the pair from the hash table.
308
int index = m_hashTable[hash];
309
btAssert(index != BT_HASH_NULL);
311
int previous = BT_HASH_NULL;
312
while (index != pairIndex)
315
index = m_next[index];
318
if (previous != BT_HASH_NULL)
320
btAssert(m_next[previous] == pairIndex);
321
m_next[previous] = m_next[pairIndex];
325
m_hashTable[hash] = m_next[pairIndex];
328
// We now move the last pair into spot of the
329
// pair being removed. We need to fix the hash
330
// table indices to support the move.
332
int lastPairIndex = m_valueArray.size() - 1;
334
// If the removed pair is the last pair, we are done.
335
if (lastPairIndex == pairIndex)
337
m_valueArray.pop_back();
338
m_keyArray.pop_back();
342
// Remove the last pair from the hash table.
343
int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
345
index = m_hashTable[lastHash];
346
btAssert(index != BT_HASH_NULL);
348
previous = BT_HASH_NULL;
349
while (index != lastPairIndex)
352
index = m_next[index];
355
if (previous != BT_HASH_NULL)
357
btAssert(m_next[previous] == lastPairIndex);
358
m_next[previous] = m_next[lastPairIndex];
362
m_hashTable[lastHash] = m_next[lastPairIndex];
365
// Copy the last pair into the remove pair's spot.
366
m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
367
m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
369
// Insert the last pair into the hash table
370
m_next[pairIndex] = m_hashTable[lastHash];
371
m_hashTable[lastHash] = pairIndex;
373
m_valueArray.pop_back();
374
m_keyArray.pop_back();
381
return m_valueArray.size();
384
const Value* getAtIndex(int index) const
386
btAssert(index < m_valueArray.size());
388
return &m_valueArray[index];
391
Value* getAtIndex(int index)
393
btAssert(index < m_valueArray.size());
395
return &m_valueArray[index];
398
Value* operator[](const Key& key) {
402
const Value* find(const Key& key) const
404
int index = findIndex(key);
405
if (index == BT_HASH_NULL)
409
return &m_valueArray[index];
412
Value* find(const Key& key)
414
int index = findIndex(key);
415
if (index == BT_HASH_NULL)
419
return &m_valueArray[index];
423
int findIndex(const Key& key) const
425
unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
427
if (hash >= (unsigned int)m_hashTable.size())
432
int index = m_hashTable[hash];
433
while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
435
index = m_next[index];
444
m_valueArray.clear();
450
#endif //BT_HASH_MAP_H