Bullet Collision Detection & Physics Library
btHashMap.h
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4 
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:
10 
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.
14 */
15 
16 #ifndef BT_HASH_MAP_H
17 #define BT_HASH_MAP_H
18 
19 #include <string>
20 #include "btAlignedObjectArray.h"
21 
24 {
25  std::string m_string1;
26  unsigned int m_hash;
27 
28  SIMD_FORCE_INLINE unsigned int getHash() const
29  {
30  return m_hash;
31  }
32 
34  {
35  m_string1 = "";
36  m_hash = 0;
37  }
38  btHashString(const char* name)
39  : m_string1(name)
40  {
41  /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
42  static const unsigned int InitialFNV = 2166136261u;
43  static const unsigned int FNVMultiple = 16777619u;
44 
45  /* Fowler / Noll / Vo (FNV) Hash */
46  unsigned int hash = InitialFNV;
47 
48  for (int i = 0; m_string1.c_str()[i]; i++)
49  {
50  hash = hash ^ (m_string1.c_str()[i]); /* xor the low 8 bits */
51  hash = hash * FNVMultiple; /* multiply by the magic number */
52  }
53  m_hash = hash;
54  }
55 
56  bool equals(const btHashString& other) const
57  {
58  return (m_string1 == other.m_string1);
59  }
60 };
61 
62 const int BT_HASH_NULL = 0xffffffff;
63 
64 class btHashInt
65 {
66  int m_uid;
67 
68 public:
70  {
71  }
72 
73  btHashInt(int uid) : m_uid(uid)
74  {
75  }
76 
77  int getUid1() const
78  {
79  return m_uid;
80  }
81 
82  void setUid1(int uid)
83  {
84  m_uid = uid;
85  }
86 
87  bool equals(const btHashInt& other) const
88  {
89  return getUid1() == other.getUid1();
90  }
91  //to our success
92  SIMD_FORCE_INLINE unsigned int getHash() const
93  {
94  unsigned int key = m_uid;
95  // Thomas Wang's hash
96  key += ~(key << 15);
97  key ^= (key >> 10);
98  key += (key << 3);
99  key ^= (key >> 6);
100  key += ~(key << 11);
101  key ^= (key >> 16);
102 
103  return key;
104  }
105 };
106 
108 {
109  union {
110  const void* m_pointer;
111  unsigned int m_hashValues[2];
112  };
113 
114 public:
115  btHashPtr(const void* ptr)
116  : m_pointer(ptr)
117  {
118  }
119 
120  const void* getPointer() const
121  {
122  return m_pointer;
123  }
124 
125  bool equals(const btHashPtr& other) const
126  {
127  return getPointer() == other.getPointer();
128  }
129 
130  //to our success
131  SIMD_FORCE_INLINE unsigned int getHash() const
132  {
133  const bool VOID_IS_8 = ((sizeof(void*) == 8));
134 
135  unsigned int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
136  // Thomas Wang's hash
137  key += ~(key << 15);
138  key ^= (key >> 10);
139  key += (key << 3);
140  key ^= (key >> 6);
141  key += ~(key << 11);
142  key ^= (key >> 16);
143  return key;
144  }
145 };
146 
147 template <class Value>
149 {
150  int m_uid;
151 
152 public:
153  btHashKeyPtr(int uid) : m_uid(uid)
154  {
155  }
156 
157  int getUid1() const
158  {
159  return m_uid;
160  }
161 
162  bool equals(const btHashKeyPtr<Value>& other) const
163  {
164  return getUid1() == other.getUid1();
165  }
166 
167  //to our success
168  SIMD_FORCE_INLINE unsigned int getHash() const
169  {
170  unsigned int key = m_uid;
171  // Thomas Wang's hash
172  key += ~(key << 15);
173  key ^= (key >> 10);
174  key += (key << 3);
175  key ^= (key >> 6);
176  key += ~(key << 11);
177  key ^= (key >> 16);
178  return key;
179  }
180 };
181 
182 template <class Value>
184 {
185  int m_uid;
186 
187 public:
188  btHashKey(int uid) : m_uid(uid)
189  {
190  }
191 
192  int getUid1() const
193  {
194  return m_uid;
195  }
196 
197  bool equals(const btHashKey<Value>& other) const
198  {
199  return getUid1() == other.getUid1();
200  }
201  //to our success
202  SIMD_FORCE_INLINE unsigned int getHash() const
203  {
204  unsigned int key = m_uid;
205  // Thomas Wang's hash
206  key += ~(key << 15);
207  key ^= (key >> 10);
208  key += (key << 3);
209  key ^= (key >> 6);
210  key += ~(key << 11);
211  key ^= (key >> 16);
212  return key;
213  }
214 };
215 
218 template <class Key, class Value>
220 {
221 protected:
224 
227 
228  void growTables(const Key& /*key*/)
229  {
230  int newCapacity = m_valueArray.capacity();
231 
232  if (m_hashTable.size() < newCapacity)
233  {
234  //grow hashtable and next table
235  int curHashtableSize = m_hashTable.size();
236 
237  m_hashTable.resize(newCapacity);
238  m_next.resize(newCapacity);
239 
240  int i;
241 
242  for (i = 0; i < newCapacity; ++i)
243  {
245  }
246  for (i = 0; i < newCapacity; ++i)
247  {
248  m_next[i] = BT_HASH_NULL;
249  }
250 
251  for (i = 0; i < curHashtableSize; i++)
252  {
253  //const Value& value = m_valueArray[i];
254  //const Key& key = m_keyArray[i];
255 
256  int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1); // New hash value with new mask
257  m_next[i] = m_hashTable[hashValue];
258  m_hashTable[hashValue] = i;
259  }
260  }
261  }
262 
263 public:
264  void insert(const Key& key, const Value& value)
265  {
266  int hash = key.getHash() & (m_valueArray.capacity() - 1);
267 
268  //replace value if the key is already there
269  int index = findIndex(key);
270  if (index != BT_HASH_NULL)
271  {
272  m_valueArray[index] = value;
273  return;
274  }
275 
276  int count = m_valueArray.size();
277  int oldCapacity = m_valueArray.capacity();
278  m_valueArray.push_back(value);
279  m_keyArray.push_back(key);
280 
281  int newCapacity = m_valueArray.capacity();
282  if (oldCapacity < newCapacity)
283  {
284  growTables(key);
285  //hash with new capacity
286  hash = key.getHash() & (m_valueArray.capacity() - 1);
287  }
288  m_next[count] = m_hashTable[hash];
289  m_hashTable[hash] = count;
290  }
291 
292  void remove(const Key& key)
293  {
294  int hash = key.getHash() & (m_valueArray.capacity() - 1);
295 
296  int pairIndex = findIndex(key);
297 
298  if (pairIndex == BT_HASH_NULL)
299  {
300  return;
301  }
302 
303  // Remove the pair from the hash table.
304  int index = m_hashTable[hash];
305  btAssert(index != BT_HASH_NULL);
306 
307  int previous = BT_HASH_NULL;
308  while (index != pairIndex)
309  {
310  previous = index;
311  index = m_next[index];
312  }
313 
314  if (previous != BT_HASH_NULL)
315  {
316  btAssert(m_next[previous] == pairIndex);
317  m_next[previous] = m_next[pairIndex];
318  }
319  else
320  {
321  m_hashTable[hash] = m_next[pairIndex];
322  }
323 
324  // We now move the last pair into spot of the
325  // pair being removed. We need to fix the hash
326  // table indices to support the move.
327 
328  int lastPairIndex = m_valueArray.size() - 1;
329 
330  // If the removed pair is the last pair, we are done.
331  if (lastPairIndex == pairIndex)
332  {
335  return;
336  }
337 
338  // Remove the last pair from the hash table.
339  int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
340 
341  index = m_hashTable[lastHash];
342  btAssert(index != BT_HASH_NULL);
343 
344  previous = BT_HASH_NULL;
345  while (index != lastPairIndex)
346  {
347  previous = index;
348  index = m_next[index];
349  }
350 
351  if (previous != BT_HASH_NULL)
352  {
353  btAssert(m_next[previous] == lastPairIndex);
354  m_next[previous] = m_next[lastPairIndex];
355  }
356  else
357  {
358  m_hashTable[lastHash] = m_next[lastPairIndex];
359  }
360 
361  // Copy the last pair into the remove pair's spot.
362  m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
363  m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
364 
365  // Insert the last pair into the hash table
366  m_next[pairIndex] = m_hashTable[lastHash];
367  m_hashTable[lastHash] = pairIndex;
368 
371  }
372 
373  int size() const
374  {
375  return m_valueArray.size();
376  }
377 
378  const Value* getAtIndex(int index) const
379  {
380  btAssert(index < m_valueArray.size());
381  btAssert(index >= 0);
382  if (index >= 0 && index < m_valueArray.size())
383  {
384  return &m_valueArray[index];
385  }
386  return 0;
387  }
388 
389  Value* getAtIndex(int index)
390  {
391  btAssert(index < m_valueArray.size());
392  btAssert(index >= 0);
393  if (index >= 0 && index < m_valueArray.size())
394  {
395  return &m_valueArray[index];
396  }
397  return 0;
398  }
399 
400  Key getKeyAtIndex(int index)
401  {
402  btAssert(index < m_keyArray.size());
403  btAssert(index >= 0);
404  return m_keyArray[index];
405  }
406 
407  const Key getKeyAtIndex(int index) const
408  {
409  btAssert(index < m_keyArray.size());
410  btAssert(index >= 0);
411  return m_keyArray[index];
412  }
413 
414  Value* operator[](const Key& key)
415  {
416  return find(key);
417  }
418 
419  const Value* operator[](const Key& key) const
420  {
421  return find(key);
422  }
423 
424  const Value* find(const Key& key) const
425  {
426  int index = findIndex(key);
427  if (index == BT_HASH_NULL)
428  {
429  return NULL;
430  }
431  return &m_valueArray[index];
432  }
433 
434  Value* find(const Key& key)
435  {
436  int index = findIndex(key);
437  if (index == BT_HASH_NULL)
438  {
439  return NULL;
440  }
441  return &m_valueArray[index];
442  }
443 
444  int findIndex(const Key& key) const
445  {
446  unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
447 
448  if (hash >= (unsigned int)m_hashTable.size())
449  {
450  return BT_HASH_NULL;
451  }
452 
453  int index = m_hashTable[hash];
454  while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
455  {
456  index = m_next[index];
457  }
458  return index;
459  }
460 
461  void clear()
462  {
463  m_hashTable.clear();
464  m_next.clear();
466  m_keyArray.clear();
467  }
468 };
469 
470 #endif //BT_HASH_MAP_H
btHashInt::setUid1
void setUid1(int uid)
Definition: btHashMap.h:82
btHashKeyPtr::getUid1
int getUid1() const
Definition: btHashMap.h:157
btHashPtr::getHash
unsigned int getHash() const
Definition: btHashMap.h:131
btHashKey::getHash
unsigned int getHash() const
Definition: btHashMap.h:202
btHashMap::m_hashTable
btAlignedObjectArray< int > m_hashTable
Definition: btHashMap.h:222
btHashKey
Definition: btHashMap.h:183
btHashKey::getUid1
int getUid1() const
Definition: btHashMap.h:192
btHashKey::m_uid
int m_uid
Definition: btHashMap.h:185
btHashPtr::getPointer
const void * getPointer() const
Definition: btHashMap.h:120
btHashMap::getAtIndex
const Value * getAtIndex(int index) const
Definition: btHashMap.h:378
btHashInt::btHashInt
btHashInt(int uid)
Definition: btHashMap.h:73
btAlignedObjectArray::clear
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
Definition: btAlignedObjectArray.h:176
btHashKey::btHashKey
btHashKey(int uid)
Definition: btHashMap.h:188
btHashPtr
Definition: btHashMap.h:107
btHashString
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:23
btHashMap::clear
void clear()
Definition: btHashMap.h:461
btHashKeyPtr::m_uid
int m_uid
Definition: btHashMap.h:150
btHashMap::remove
void remove(const Key &key)
Definition: btHashMap.h:292
btHashPtr::equals
bool equals(const btHashPtr &other) const
Definition: btHashMap.h:125
btHashInt::getUid1
int getUid1() const
Definition: btHashMap.h:77
btHashMap::m_valueArray
btAlignedObjectArray< Value > m_valueArray
Definition: btHashMap.h:225
btHashString::getHash
unsigned int getHash() const
Definition: btHashMap.h:28
btAssert
#define btAssert(x)
Definition: btScalar.h:153
btHashMap
The btHashMap template class implements a generic and lightweight hashmap.
Definition: btHashMap.h:219
btHashMap::size
int size() const
Definition: btHashMap.h:373
btHashMap::find
Value * find(const Key &key)
Definition: btHashMap.h:434
btHashMap::findIndex
int findIndex(const Key &key) const
Definition: btHashMap.h:444
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition: btAlignedObjectArray.h:203
btHashInt
Definition: btHashMap.h:64
btAlignedObjectArray::pop_back
void pop_back()
Definition: btAlignedObjectArray.h:185
btHashPtr::m_hashValues
unsigned int m_hashValues[2]
Definition: btHashMap.h:111
btHashMap::m_keyArray
btAlignedObjectArray< Key > m_keyArray
Definition: btHashMap.h:226
btHashString::btHashString
btHashString(const char *name)
Definition: btHashMap.h:38
bParse::VOID_IS_8
const bool VOID_IS_8
Definition: bChunk.h:81
btHashInt::equals
bool equals(const btHashInt &other) const
Definition: btHashMap.h:87
btHashString::m_string1
std::string m_string1
Definition: btHashMap.h:25
btHashString::equals
bool equals(const btHashString &other) const
Definition: btHashMap.h:56
btHashInt::m_uid
int m_uid
Definition: btHashMap.h:66
btHashKeyPtr::getHash
unsigned int getHash() const
Definition: btHashMap.h:168
btHashMap::getAtIndex
Value * getAtIndex(int index)
Definition: btHashMap.h:389
btHashMap::growTables
void growTables(const Key &)
Definition: btHashMap.h:228
btHashKeyPtr::btHashKeyPtr
btHashKeyPtr(int uid)
Definition: btHashMap.h:153
btAlignedObjectArray< int >
btHashString::m_hash
unsigned int m_hash
Definition: btHashMap.h:26
btHashKeyPtr
Definition: btHashMap.h:148
btHashInt::getHash
unsigned int getHash() const
Definition: btHashMap.h:92
btHashMap::find
const Value * find(const Key &key) const
Definition: btHashMap.h:424
btHashInt::btHashInt
btHashInt()
Definition: btHashMap.h:69
SIMD_FORCE_INLINE
#define SIMD_FORCE_INLINE
Definition: btScalar.h:98
btHashString::btHashString
btHashString()
Definition: btHashMap.h:33
btHashMap::getKeyAtIndex
const Key getKeyAtIndex(int index) const
Definition: btHashMap.h:407
btHashKeyPtr::equals
bool equals(const btHashKeyPtr< Value > &other) const
Definition: btHashMap.h:162
btHashMap::getKeyAtIndex
Key getKeyAtIndex(int index)
Definition: btHashMap.h:400
btHashPtr::btHashPtr
btHashPtr(const void *ptr)
Definition: btHashMap.h:115
btAlignedObjectArray::capacity
int capacity() const
return the pre-allocated (reserved) elements, this is at least as large as the total number of elemen...
Definition: btAlignedObjectArray.h:275
btHashMap::insert
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:264
BT_HASH_NULL
const int BT_HASH_NULL
Definition: btHashMap.h:62
btHashMap::operator[]
Value * operator[](const Key &key)
Definition: btHashMap.h:414
btHashKey::equals
bool equals(const btHashKey< Value > &other) const
Definition: btHashMap.h:197
btHashMap::operator[]
const Value * operator[](const Key &key) const
Definition: btHashMap.h:419
btAlignedObjectArray.h
btHashMap::m_next
btAlignedObjectArray< int > m_next
Definition: btHashMap.h:223
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:257
btHashPtr::m_pointer
const void * m_pointer
Definition: btHashMap.h:110
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:142