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