btHashMap.h

Go to the documentation of this file.
00001 #ifndef BT_HASH_MAP_H
00002 #define BT_HASH_MAP_H
00003 
00004 #include "btAlignedObjectArray.h"
00005 
00007 struct btHashString
00008 {
00009         const char* m_string;
00010         unsigned int    m_hash;
00011 
00012         SIMD_FORCE_INLINE       unsigned int getHash()const
00013         {
00014                 return m_hash;
00015         }
00016 
00017         btHashString(const char* name)
00018                 :m_string(name)
00019         {
00020                 /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
00021                 static const unsigned int  InitialFNV = 2166136261u;
00022                 static const unsigned int FNVMultiple = 16777619u;
00023 
00024                 /* Fowler / Noll / Vo (FNV) Hash */
00025                 unsigned int hash = InitialFNV;
00026                 
00027                 for(int i = 0; m_string[i]; i++)
00028                 {
00029                         hash = hash ^ (m_string[i]);       /* xor  the low 8 bits */
00030                         hash = hash * FNVMultiple;  /* multiply by the magic number */
00031                 }
00032                 m_hash = hash;
00033         }
00034 
00035         int portableStringCompare(const char* src,      const char* dst) const
00036         {
00037                         int ret = 0 ;
00038 
00039                         while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
00040                                         ++src, ++dst;
00041 
00042                         if ( ret < 0 )
00043                                         ret = -1 ;
00044                         else if ( ret > 0 )
00045                                         ret = 1 ;
00046 
00047                         return( ret );
00048         }
00049 
00050         bool equals(const btHashString& other) const
00051         {
00052                 return (m_string == other.m_string) ||
00053                         (0==portableStringCompare(m_string,other.m_string));
00054 
00055         }
00056 
00057 };
00058 
00059 const int BT_HASH_NULL=0xffffffff;
00060 
00061 
00062 class btHashInt
00063 {
00064         int     m_uid;
00065 public:
00066         btHashInt(int uid)      :m_uid(uid)
00067         {
00068         }
00069 
00070         int     getUid1() const
00071         {
00072                 return m_uid;
00073         }
00074 
00075         bool equals(const btHashInt& other) const
00076         {
00077                 return getUid1() == other.getUid1();
00078         }
00079         //to our success
00080         SIMD_FORCE_INLINE       unsigned int getHash()const
00081         {
00082                 int key = m_uid;
00083                 // Thomas Wang's hash
00084                 key += ~(key << 15);    key ^=  (key >> 10);    key +=  (key << 3);     key ^=  (key >> 6);     key += ~(key << 11);    key ^=  (key >> 16);
00085                 return key;
00086         }
00087 };
00088 
00089 
00090 
00091 class btHashPtr
00092 {
00093 
00094         union
00095         {
00096                 const void*     m_pointer;
00097                 int     m_hashValues[2];
00098         };
00099 
00100 public:
00101 
00102         btHashPtr(const void* ptr)
00103                 :m_pointer(ptr)
00104         {
00105         }
00106 
00107         const void*     getPointer() const
00108         {
00109                 return m_pointer;
00110         }
00111 
00112         bool equals(const btHashPtr& other) const
00113         {
00114                 return getPointer() == other.getPointer();
00115         }
00116 
00117         //to our success
00118         SIMD_FORCE_INLINE       unsigned int getHash()const
00119         {
00120                 const bool VOID_IS_8 = ((sizeof(void*)==8));
00121                 
00122                 int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
00123         
00124                 // Thomas Wang's hash
00125                 key += ~(key << 15);    key ^=  (key >> 10);    key +=  (key << 3);     key ^=  (key >> 6);     key += ~(key << 11);    key ^=  (key >> 16);
00126                 return key;
00127         }
00128 
00129         
00130 };
00131 
00132 
00133 template <class Value>
00134 class btHashKeyPtr
00135 {
00136         int     m_uid;
00137 public:
00138 
00139         btHashKeyPtr(int uid)    :m_uid(uid)
00140         {
00141         }
00142 
00143         int     getUid1() const
00144         {
00145                 return m_uid;
00146         }
00147 
00148         bool equals(const btHashKeyPtr<Value>& other) const
00149         {
00150                 return getUid1() == other.getUid1();
00151         }
00152 
00153         //to our success
00154         SIMD_FORCE_INLINE       unsigned int getHash()const
00155         {
00156                 int key = m_uid;
00157                 // Thomas Wang's hash
00158                 key += ~(key << 15);    key ^=  (key >> 10);    key +=  (key << 3);     key ^=  (key >> 6);     key += ~(key << 11);    key ^=  (key >> 16);
00159                 return key;
00160         }
00161 
00162         
00163 };
00164 
00165 
00166 template <class Value>
00167 class btHashKey
00168 {
00169         int     m_uid;
00170 public:
00171 
00172         btHashKey(int uid)      :m_uid(uid)
00173         {
00174         }
00175 
00176         int     getUid1() const
00177         {
00178                 return m_uid;
00179         }
00180 
00181         bool equals(const btHashKey<Value>& other) const
00182         {
00183                 return getUid1() == other.getUid1();
00184         }
00185         //to our success
00186         SIMD_FORCE_INLINE       unsigned int getHash()const
00187         {
00188                 int key = m_uid;
00189                 // Thomas Wang's hash
00190                 key += ~(key << 15);    key ^=  (key >> 10);    key +=  (key << 3);     key ^=  (key >> 6);     key += ~(key << 11);    key ^=  (key >> 16);
00191                 return key;
00192         }
00193 };
00194 
00195 
00198 template <class Key, class Value>
00199 class btHashMap
00200 {
00201 
00202         btAlignedObjectArray<int>               m_hashTable;
00203         btAlignedObjectArray<int>               m_next;
00204         
00205         btAlignedObjectArray<Value>             m_valueArray;
00206         btAlignedObjectArray<Key>               m_keyArray;
00207 
00208         void    growTables(const Key& key)
00209         {
00210                 int newCapacity = m_valueArray.capacity();
00211 
00212                 if (m_hashTable.size() < newCapacity)
00213                 {
00214                         //grow hashtable and next table
00215                         int curHashtableSize = m_hashTable.size();
00216 
00217                         m_hashTable.resize(newCapacity);
00218                         m_next.resize(newCapacity);
00219 
00220                         int i;
00221 
00222                         for (i= 0; i < newCapacity; ++i)
00223                         {
00224                                 m_hashTable[i] = BT_HASH_NULL;
00225                         }
00226                         for (i = 0; i < newCapacity; ++i)
00227                         {
00228                                 m_next[i] = BT_HASH_NULL;
00229                         }
00230 
00231                         for(i=0;i<curHashtableSize;i++)
00232                         {
00233                                 //const Value& value = m_valueArray[i];
00234                                 //const Key& key = m_keyArray[i];
00235 
00236                                 int     hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1);      // New hash value with new mask
00237                                 m_next[i] = m_hashTable[hashValue];
00238                                 m_hashTable[hashValue] = i;
00239                         }
00240 
00241 
00242                 }
00243         }
00244 
00245         public:
00246 
00247         void insert(const Key& key, const Value& value) {
00248                 int hash = key.getHash() & (m_valueArray.capacity()-1);
00249 
00250                 //replace value if the key is already there
00251                 int index = findIndex(key);
00252                 if (index != BT_HASH_NULL)
00253                 {
00254                         m_valueArray[index]=value;
00255                         return;
00256                 }
00257 
00258                 int count = m_valueArray.size();
00259                 int oldCapacity = m_valueArray.capacity();
00260                 m_valueArray.push_back(value);
00261                 m_keyArray.push_back(key);
00262 
00263                 int newCapacity = m_valueArray.capacity();
00264                 if (oldCapacity < newCapacity)
00265                 {
00266                         growTables(key);
00267                         //hash with new capacity
00268                         hash = key.getHash() & (m_valueArray.capacity()-1);
00269                 }
00270                 m_next[count] = m_hashTable[hash];
00271                 m_hashTable[hash] = count;
00272         }
00273 
00274         void remove(const Key& key) {
00275 
00276                 int hash = key.getHash() & (m_valueArray.capacity()-1);
00277 
00278                 int pairIndex = findIndex(key);
00279                 
00280                 if (pairIndex ==BT_HASH_NULL)
00281                 {
00282                         return;
00283                 }
00284 
00285                 // Remove the pair from the hash table.
00286                 int index = m_hashTable[hash];
00287                 btAssert(index != BT_HASH_NULL);
00288 
00289                 int previous = BT_HASH_NULL;
00290                 while (index != pairIndex)
00291                 {
00292                         previous = index;
00293                         index = m_next[index];
00294                 }
00295 
00296                 if (previous != BT_HASH_NULL)
00297                 {
00298                         btAssert(m_next[previous] == pairIndex);
00299                         m_next[previous] = m_next[pairIndex];
00300                 }
00301                 else
00302                 {
00303                         m_hashTable[hash] = m_next[pairIndex];
00304                 }
00305 
00306                 // We now move the last pair into spot of the
00307                 // pair being removed. We need to fix the hash
00308                 // table indices to support the move.
00309 
00310                 int lastPairIndex = m_valueArray.size() - 1;
00311 
00312                 // If the removed pair is the last pair, we are done.
00313                 if (lastPairIndex == pairIndex)
00314                 {
00315                         m_valueArray.pop_back();
00316                         m_keyArray.pop_back();
00317                         return;
00318                 }
00319 
00320                 // Remove the last pair from the hash table.
00321                 int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
00322 
00323                 index = m_hashTable[lastHash];
00324                 btAssert(index != BT_HASH_NULL);
00325 
00326                 previous = BT_HASH_NULL;
00327                 while (index != lastPairIndex)
00328                 {
00329                         previous = index;
00330                         index = m_next[index];
00331                 }
00332 
00333                 if (previous != BT_HASH_NULL)
00334                 {
00335                         btAssert(m_next[previous] == lastPairIndex);
00336                         m_next[previous] = m_next[lastPairIndex];
00337                 }
00338                 else
00339                 {
00340                         m_hashTable[lastHash] = m_next[lastPairIndex];
00341                 }
00342 
00343                 // Copy the last pair into the remove pair's spot.
00344                 m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
00345                 m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
00346 
00347                 // Insert the last pair into the hash table
00348                 m_next[pairIndex] = m_hashTable[lastHash];
00349                 m_hashTable[lastHash] = pairIndex;
00350 
00351                 m_valueArray.pop_back();
00352                 m_keyArray.pop_back();
00353 
00354         }
00355 
00356 
00357         int size() const
00358         {
00359                 return m_valueArray.size();
00360         }
00361 
00362         const Value* getAtIndex(int index) const
00363         {
00364                 btAssert(index < m_valueArray.size());
00365 
00366                 return &m_valueArray[index];
00367         }
00368 
00369         Value* getAtIndex(int index)
00370         {
00371                 btAssert(index < m_valueArray.size());
00372 
00373                 return &m_valueArray[index];
00374         }
00375 
00376         Value* operator[](const Key& key) {
00377                 return find(key);
00378         }
00379 
00380         const Value*    find(const Key& key) const
00381         {
00382                 int index = findIndex(key);
00383                 if (index == BT_HASH_NULL)
00384                 {
00385                         return NULL;
00386                 }
00387                 return &m_valueArray[index];
00388         }
00389 
00390         Value*  find(const Key& key)
00391         {
00392                 int index = findIndex(key);
00393                 if (index == BT_HASH_NULL)
00394                 {
00395                         return NULL;
00396                 }
00397                 return &m_valueArray[index];
00398         }
00399 
00400 
00401         int     findIndex(const Key& key) const
00402         {
00403                 unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
00404 
00405                 if (hash >= (unsigned int)m_hashTable.size())
00406                 {
00407                         return BT_HASH_NULL;
00408                 }
00409 
00410                 int index = m_hashTable[hash];
00411                 while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
00412                 {
00413                         index = m_next[index];
00414                 }
00415                 return index;
00416         }
00417 
00418         void    clear()
00419         {
00420                 m_hashTable.clear();
00421                 m_next.clear();
00422                 m_valueArray.clear();
00423                 m_keyArray.clear();
00424         }
00425 
00426 };
00427 
00428 #endif //BT_HASH_MAP_H

Generated on Mon Feb 15 22:17:04 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1