123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 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.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #ifndef BT_HASH_MAP_H
- #define BT_HASH_MAP_H
- #include "btAlignedObjectArray.h"
- ///very basic hashable string implementation, compatible with btHashMap
- struct btHashString
- {
- const char* m_string;
- unsigned int m_hash;
- SIMD_FORCE_INLINE unsigned int getHash()const
- {
- return m_hash;
- }
- btHashString(const char* name)
- :m_string(name)
- {
- /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
- static const unsigned int InitialFNV = 2166136261u;
- static const unsigned int FNVMultiple = 16777619u;
- /* Fowler / Noll / Vo (FNV) Hash */
- unsigned int hash = InitialFNV;
-
- for(int i = 0; m_string[i]; i++)
- {
- hash = hash ^ (m_string[i]); /* xor the low 8 bits */
- hash = hash * FNVMultiple; /* multiply by the magic number */
- }
- m_hash = hash;
- }
- int portableStringCompare(const char* src, const char* dst) const
- {
- int ret = 0 ;
- while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
- ++src, ++dst;
- if ( ret < 0 )
- ret = -1 ;
- else if ( ret > 0 )
- ret = 1 ;
- return( ret );
- }
- bool equals(const btHashString& other) const
- {
- return (m_string == other.m_string) ||
- (0==portableStringCompare(m_string,other.m_string));
- }
- };
- const int BT_HASH_NULL=0xffffffff;
- class btHashInt
- {
- int m_uid;
- public:
- btHashInt(int uid) :m_uid(uid)
- {
- }
- int getUid1() const
- {
- return m_uid;
- }
- void setUid1(int uid)
- {
- m_uid = uid;
- }
- bool equals(const btHashInt& other) const
- {
- return getUid1() == other.getUid1();
- }
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
- {
- int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
- return key;
- }
- };
- class btHashPtr
- {
- union
- {
- const void* m_pointer;
- int m_hashValues[2];
- };
- public:
- btHashPtr(const void* ptr)
- :m_pointer(ptr)
- {
- }
- const void* getPointer() const
- {
- return m_pointer;
- }
- bool equals(const btHashPtr& other) const
- {
- return getPointer() == other.getPointer();
- }
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
- {
- const bool VOID_IS_8 = ((sizeof(void*)==8));
-
- int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
-
- // Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
- return key;
- }
-
- };
- template <class Value>
- class btHashKeyPtr
- {
- int m_uid;
- public:
- btHashKeyPtr(int uid) :m_uid(uid)
- {
- }
- int getUid1() const
- {
- return m_uid;
- }
- bool equals(const btHashKeyPtr<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
- {
- int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
- return key;
- }
-
- };
- template <class Value>
- class btHashKey
- {
- int m_uid;
- public:
- btHashKey(int uid) :m_uid(uid)
- {
- }
- int getUid1() const
- {
- return m_uid;
- }
- bool equals(const btHashKey<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
- {
- int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
- return key;
- }
- };
- ///The btHashMap template class implements a generic and lightweight hashmap.
- ///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
- template <class Key, class Value>
- class btHashMap
- {
- protected:
- btAlignedObjectArray<int> m_hashTable;
- btAlignedObjectArray<int> m_next;
-
- btAlignedObjectArray<Value> m_valueArray;
- btAlignedObjectArray<Key> m_keyArray;
- void growTables(const Key& /*key*/)
- {
- int newCapacity = m_valueArray.capacity();
- if (m_hashTable.size() < newCapacity)
- {
- //grow hashtable and next table
- int curHashtableSize = m_hashTable.size();
- m_hashTable.resize(newCapacity);
- m_next.resize(newCapacity);
- int i;
- for (i= 0; i < newCapacity; ++i)
- {
- m_hashTable[i] = BT_HASH_NULL;
- }
- for (i = 0; i < newCapacity; ++i)
- {
- m_next[i] = BT_HASH_NULL;
- }
- for(i=0;i<curHashtableSize;i++)
- {
- //const Value& value = m_valueArray[i];
- //const Key& key = m_keyArray[i];
- int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
- m_next[i] = m_hashTable[hashValue];
- m_hashTable[hashValue] = i;
- }
- }
- }
- public:
- void insert(const Key& key, const Value& value) {
- int hash = key.getHash() & (m_valueArray.capacity()-1);
- //replace value if the key is already there
- int index = findIndex(key);
- if (index != BT_HASH_NULL)
- {
- m_valueArray[index]=value;
- return;
- }
- int count = m_valueArray.size();
- int oldCapacity = m_valueArray.capacity();
- m_valueArray.push_back(value);
- m_keyArray.push_back(key);
- int newCapacity = m_valueArray.capacity();
- if (oldCapacity < newCapacity)
- {
- growTables(key);
- //hash with new capacity
- hash = key.getHash() & (m_valueArray.capacity()-1);
- }
- m_next[count] = m_hashTable[hash];
- m_hashTable[hash] = count;
- }
- void remove(const Key& key) {
- int hash = key.getHash() & (m_valueArray.capacity()-1);
- int pairIndex = findIndex(key);
-
- if (pairIndex ==BT_HASH_NULL)
- {
- return;
- }
- // Remove the pair from the hash table.
- int index = m_hashTable[hash];
- btAssert(index != BT_HASH_NULL);
- int previous = BT_HASH_NULL;
- while (index != pairIndex)
- {
- previous = index;
- index = m_next[index];
- }
- if (previous != BT_HASH_NULL)
- {
- btAssert(m_next[previous] == pairIndex);
- m_next[previous] = m_next[pairIndex];
- }
- else
- {
- m_hashTable[hash] = m_next[pairIndex];
- }
- // We now move the last pair into spot of the
- // pair being removed. We need to fix the hash
- // table indices to support the move.
- int lastPairIndex = m_valueArray.size() - 1;
- // If the removed pair is the last pair, we are done.
- if (lastPairIndex == pairIndex)
- {
- m_valueArray.pop_back();
- m_keyArray.pop_back();
- return;
- }
- // Remove the last pair from the hash table.
- int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
- index = m_hashTable[lastHash];
- btAssert(index != BT_HASH_NULL);
- previous = BT_HASH_NULL;
- while (index != lastPairIndex)
- {
- previous = index;
- index = m_next[index];
- }
- if (previous != BT_HASH_NULL)
- {
- btAssert(m_next[previous] == lastPairIndex);
- m_next[previous] = m_next[lastPairIndex];
- }
- else
- {
- m_hashTable[lastHash] = m_next[lastPairIndex];
- }
- // Copy the last pair into the remove pair's spot.
- m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
- m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
- // Insert the last pair into the hash table
- m_next[pairIndex] = m_hashTable[lastHash];
- m_hashTable[lastHash] = pairIndex;
- m_valueArray.pop_back();
- m_keyArray.pop_back();
- }
- int size() const
- {
- return m_valueArray.size();
- }
- const Value* getAtIndex(int index) const
- {
- btAssert(index < m_valueArray.size());
- return &m_valueArray[index];
- }
- Value* getAtIndex(int index)
- {
- btAssert(index < m_valueArray.size());
- return &m_valueArray[index];
- }
- Value* operator[](const Key& key) {
- return find(key);
- }
- const Value* find(const Key& key) const
- {
- int index = findIndex(key);
- if (index == BT_HASH_NULL)
- {
- return NULL;
- }
- return &m_valueArray[index];
- }
- Value* find(const Key& key)
- {
- int index = findIndex(key);
- if (index == BT_HASH_NULL)
- {
- return NULL;
- }
- return &m_valueArray[index];
- }
- int findIndex(const Key& key) const
- {
- unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
- if (hash >= (unsigned int)m_hashTable.size())
- {
- return BT_HASH_NULL;
- }
- int index = m_hashTable[hash];
- while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
- {
- index = m_next[index];
- }
- return index;
- }
- void clear()
- {
- m_hashTable.clear();
- m_next.clear();
- m_valueArray.clear();
- m_keyArray.clear();
- }
- };
- #endif //BT_HASH_MAP_H
|