Blender V2.61 - r43446
|
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 void setUid1(int uid) 00076 { 00077 m_uid = uid; 00078 } 00079 00080 bool equals(const btHashInt& other) const 00081 { 00082 return getUid1() == other.getUid1(); 00083 } 00084 //to our success 00085 SIMD_FORCE_INLINE unsigned int getHash()const 00086 { 00087 int key = m_uid; 00088 // Thomas Wang's hash 00089 key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); 00090 return key; 00091 } 00092 }; 00093 00094 00095 00096 class btHashPtr 00097 { 00098 00099 union 00100 { 00101 const void* m_pointer; 00102 int m_hashValues[2]; 00103 }; 00104 00105 public: 00106 00107 btHashPtr(const void* ptr) 00108 :m_pointer(ptr) 00109 { 00110 } 00111 00112 const void* getPointer() const 00113 { 00114 return m_pointer; 00115 } 00116 00117 bool equals(const btHashPtr& other) const 00118 { 00119 return getPointer() == other.getPointer(); 00120 } 00121 00122 //to our success 00123 SIMD_FORCE_INLINE unsigned int getHash()const 00124 { 00125 const bool VOID_IS_8 = ((sizeof(void*)==8)); 00126 00127 int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0]; 00128 00129 // Thomas Wang's hash 00130 key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); 00131 return key; 00132 } 00133 00134 00135 }; 00136 00137 00138 template <class Value> 00139 class btHashKeyPtr 00140 { 00141 int m_uid; 00142 public: 00143 00144 btHashKeyPtr(int uid) :m_uid(uid) 00145 { 00146 } 00147 00148 int getUid1() const 00149 { 00150 return m_uid; 00151 } 00152 00153 bool equals(const btHashKeyPtr<Value>& other) const 00154 { 00155 return getUid1() == other.getUid1(); 00156 } 00157 00158 //to our success 00159 SIMD_FORCE_INLINE unsigned int getHash()const 00160 { 00161 int key = m_uid; 00162 // Thomas Wang's hash 00163 key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); 00164 return key; 00165 } 00166 00167 00168 }; 00169 00170 00171 template <class Value> 00172 class btHashKey 00173 { 00174 int m_uid; 00175 public: 00176 00177 btHashKey(int uid) :m_uid(uid) 00178 { 00179 } 00180 00181 int getUid1() const 00182 { 00183 return m_uid; 00184 } 00185 00186 bool equals(const btHashKey<Value>& other) const 00187 { 00188 return getUid1() == other.getUid1(); 00189 } 00190 //to our success 00191 SIMD_FORCE_INLINE unsigned int getHash()const 00192 { 00193 int key = m_uid; 00194 // Thomas Wang's hash 00195 key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); 00196 return key; 00197 } 00198 }; 00199 00200 00203 template <class Key, class Value> 00204 class btHashMap 00205 { 00206 00207 protected: 00208 btAlignedObjectArray<int> m_hashTable; 00209 btAlignedObjectArray<int> m_next; 00210 00211 btAlignedObjectArray<Value> m_valueArray; 00212 btAlignedObjectArray<Key> m_keyArray; 00213 00214 void growTables(const Key& /*key*/) 00215 { 00216 int newCapacity = m_valueArray.capacity(); 00217 00218 if (m_hashTable.size() < newCapacity) 00219 { 00220 //grow hashtable and next table 00221 int curHashtableSize = m_hashTable.size(); 00222 00223 m_hashTable.resize(newCapacity); 00224 m_next.resize(newCapacity); 00225 00226 int i; 00227 00228 for (i= 0; i < newCapacity; ++i) 00229 { 00230 m_hashTable[i] = BT_HASH_NULL; 00231 } 00232 for (i = 0; i < newCapacity; ++i) 00233 { 00234 m_next[i] = BT_HASH_NULL; 00235 } 00236 00237 for(i=0;i<curHashtableSize;i++) 00238 { 00239 //const Value& value = m_valueArray[i]; 00240 //const Key& key = m_keyArray[i]; 00241 00242 int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask 00243 m_next[i] = m_hashTable[hashValue]; 00244 m_hashTable[hashValue] = i; 00245 } 00246 00247 00248 } 00249 } 00250 00251 public: 00252 00253 void insert(const Key& key, const Value& value) { 00254 int hash = key.getHash() & (m_valueArray.capacity()-1); 00255 00256 //replace value if the key is already there 00257 int index = findIndex(key); 00258 if (index != BT_HASH_NULL) 00259 { 00260 m_valueArray[index]=value; 00261 return; 00262 } 00263 00264 int count = m_valueArray.size(); 00265 int oldCapacity = m_valueArray.capacity(); 00266 m_valueArray.push_back(value); 00267 m_keyArray.push_back(key); 00268 00269 int newCapacity = m_valueArray.capacity(); 00270 if (oldCapacity < newCapacity) 00271 { 00272 growTables(key); 00273 //hash with new capacity 00274 hash = key.getHash() & (m_valueArray.capacity()-1); 00275 } 00276 m_next[count] = m_hashTable[hash]; 00277 m_hashTable[hash] = count; 00278 } 00279 00280 void remove(const Key& key) { 00281 00282 int hash = key.getHash() & (m_valueArray.capacity()-1); 00283 00284 int pairIndex = findIndex(key); 00285 00286 if (pairIndex ==BT_HASH_NULL) 00287 { 00288 return; 00289 } 00290 00291 // Remove the pair from the hash table. 00292 int index = m_hashTable[hash]; 00293 btAssert(index != BT_HASH_NULL); 00294 00295 int previous = BT_HASH_NULL; 00296 while (index != pairIndex) 00297 { 00298 previous = index; 00299 index = m_next[index]; 00300 } 00301 00302 if (previous != BT_HASH_NULL) 00303 { 00304 btAssert(m_next[previous] == pairIndex); 00305 m_next[previous] = m_next[pairIndex]; 00306 } 00307 else 00308 { 00309 m_hashTable[hash] = m_next[pairIndex]; 00310 } 00311 00312 // We now move the last pair into spot of the 00313 // pair being removed. We need to fix the hash 00314 // table indices to support the move. 00315 00316 int lastPairIndex = m_valueArray.size() - 1; 00317 00318 // If the removed pair is the last pair, we are done. 00319 if (lastPairIndex == pairIndex) 00320 { 00321 m_valueArray.pop_back(); 00322 m_keyArray.pop_back(); 00323 return; 00324 } 00325 00326 // Remove the last pair from the hash table. 00327 int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1); 00328 00329 index = m_hashTable[lastHash]; 00330 btAssert(index != BT_HASH_NULL); 00331 00332 previous = BT_HASH_NULL; 00333 while (index != lastPairIndex) 00334 { 00335 previous = index; 00336 index = m_next[index]; 00337 } 00338 00339 if (previous != BT_HASH_NULL) 00340 { 00341 btAssert(m_next[previous] == lastPairIndex); 00342 m_next[previous] = m_next[lastPairIndex]; 00343 } 00344 else 00345 { 00346 m_hashTable[lastHash] = m_next[lastPairIndex]; 00347 } 00348 00349 // Copy the last pair into the remove pair's spot. 00350 m_valueArray[pairIndex] = m_valueArray[lastPairIndex]; 00351 m_keyArray[pairIndex] = m_keyArray[lastPairIndex]; 00352 00353 // Insert the last pair into the hash table 00354 m_next[pairIndex] = m_hashTable[lastHash]; 00355 m_hashTable[lastHash] = pairIndex; 00356 00357 m_valueArray.pop_back(); 00358 m_keyArray.pop_back(); 00359 00360 } 00361 00362 00363 int size() const 00364 { 00365 return m_valueArray.size(); 00366 } 00367 00368 const Value* getAtIndex(int index) const 00369 { 00370 btAssert(index < m_valueArray.size()); 00371 00372 return &m_valueArray[index]; 00373 } 00374 00375 Value* getAtIndex(int index) 00376 { 00377 btAssert(index < m_valueArray.size()); 00378 00379 return &m_valueArray[index]; 00380 } 00381 00382 Value* operator[](const Key& key) { 00383 return find(key); 00384 } 00385 00386 const Value* find(const Key& key) const 00387 { 00388 int index = findIndex(key); 00389 if (index == BT_HASH_NULL) 00390 { 00391 return NULL; 00392 } 00393 return &m_valueArray[index]; 00394 } 00395 00396 Value* find(const Key& key) 00397 { 00398 int index = findIndex(key); 00399 if (index == BT_HASH_NULL) 00400 { 00401 return NULL; 00402 } 00403 return &m_valueArray[index]; 00404 } 00405 00406 00407 int findIndex(const Key& key) const 00408 { 00409 unsigned int hash = key.getHash() & (m_valueArray.capacity()-1); 00410 00411 if (hash >= (unsigned int)m_hashTable.size()) 00412 { 00413 return BT_HASH_NULL; 00414 } 00415 00416 int index = m_hashTable[hash]; 00417 while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false) 00418 { 00419 index = m_next[index]; 00420 } 00421 return index; 00422 } 00423 00424 void clear() 00425 { 00426 m_hashTable.clear(); 00427 m_next.clear(); 00428 m_valueArray.clear(); 00429 m_keyArray.clear(); 00430 } 00431 00432 }; 00433 00434 #endif //BT_HASH_MAP_H