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


bullet
Author(s): Erwin Coumans, ROS package maintained by Tully Foote
autogenerated on Wed Oct 31 2012 07:54:31