Bullet 2.85 update
[Torque-3d.git] / Engine / lib / bullet / src / LinearMath / btHashMap.h
blobca6f326b4430f32382c9eb5dfd016a5ad0c20371
1 /*
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.
17 #ifndef BT_HASH_MAP_H
18 #define BT_HASH_MAP_H
20 #include "btAlignedObjectArray.h"
22 ///very basic hashable string implementation, compatible with btHashMap
23 struct btHashString
25 const char* m_string;
26 unsigned int m_hash;
28 SIMD_FORCE_INLINE unsigned int getHash()const
30 return m_hash;
33 btHashString(const char* name)
34 :m_string(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 */
48 m_hash = hash;
51 int portableStringCompare(const char* src, const char* dst) const
53 int ret = 0 ;
55 while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
56 ++src, ++dst;
58 if ( ret < 0 )
59 ret = -1 ;
60 else if ( ret > 0 )
61 ret = 1 ;
63 return( ret );
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;
78 class btHashInt
80 int m_uid;
81 public:
82 btHashInt(int uid) :m_uid(uid)
86 int getUid1() const
88 return m_uid;
91 void setUid1(int uid)
93 m_uid = uid;
96 bool equals(const btHashInt& other) const
98 return getUid1() == other.getUid1();
100 //to our success
101 SIMD_FORCE_INLINE unsigned int getHash()const
103 int key = m_uid;
104 // Thomas Wang's hash
105 key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
106 return key;
112 class btHashPtr
115 union
117 const void* m_pointer;
118 int m_hashValues[2];
121 public:
123 btHashPtr(const void* ptr)
124 :m_pointer(ptr)
128 const void* getPointer() const
130 return m_pointer;
133 bool equals(const btHashPtr& other) const
135 return getPointer() == other.getPointer();
138 //to our success
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);
147 return key;
154 template <class Value>
155 class btHashKeyPtr
157 int m_uid;
158 public:
160 btHashKeyPtr(int uid) :m_uid(uid)
164 int getUid1() const
166 return m_uid;
169 bool equals(const btHashKeyPtr<Value>& other) const
171 return getUid1() == other.getUid1();
174 //to our success
175 SIMD_FORCE_INLINE unsigned int getHash()const
177 int key = m_uid;
178 // Thomas Wang's hash
179 key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
180 return key;
187 template <class Value>
188 class btHashKey
190 int m_uid;
191 public:
193 btHashKey(int uid) :m_uid(uid)
197 int getUid1() const
199 return m_uid;
202 bool equals(const btHashKey<Value>& other) const
204 return getUid1() == other.getUid1();
206 //to our success
207 SIMD_FORCE_INLINE unsigned int getHash()const
209 int key = m_uid;
210 // Thomas Wang's hash
211 key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
212 return key;
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>
220 class btHashMap
223 protected:
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);
242 int i;
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;
267 public:
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;
277 return;
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)
288 growTables(key);
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)
304 return;
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)
314 previous = index;
315 index = m_next[index];
318 if (previous != BT_HASH_NULL)
320 btAssert(m_next[previous] == pairIndex);
321 m_next[previous] = m_next[pairIndex];
323 else
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();
339 return;
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)
351 previous = index;
352 index = m_next[index];
355 if (previous != BT_HASH_NULL)
357 btAssert(m_next[previous] == lastPairIndex);
358 m_next[previous] = m_next[lastPairIndex];
360 else
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();
379 int size() const
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 Key getKeyAtIndex(int index)
400 btAssert(index < m_keyArray.size());
401 return m_keyArray[index];
404 const Key getKeyAtIndex(int index) const
406 btAssert(index < m_keyArray.size());
407 return m_keyArray[index];
411 Value* operator[](const Key& key) {
412 return find(key);
415 const Value* operator[](const Key& key) const {
416 return find(key);
419 const Value* find(const Key& key) const
421 int index = findIndex(key);
422 if (index == BT_HASH_NULL)
424 return NULL;
426 return &m_valueArray[index];
429 Value* find(const Key& key)
431 int index = findIndex(key);
432 if (index == BT_HASH_NULL)
434 return NULL;
436 return &m_valueArray[index];
440 int findIndex(const Key& key) const
442 unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
444 if (hash >= (unsigned int)m_hashTable.size())
446 return BT_HASH_NULL;
449 int index = m_hashTable[hash];
450 while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
452 index = m_next[index];
454 return index;
457 void clear()
459 m_hashTable.clear();
460 m_next.clear();
461 m_valueArray.clear();
462 m_keyArray.clear();
467 #endif //BT_HASH_MAP_H