2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
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:
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.
20 #include "btAlignedObjectArray.h"
22 ///very basic hashable string implementation, compatible with btHashMap
28 SIMD_FORCE_INLINE
unsigned int getHash()const
33 btHashString(const char* name
)
36 /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
37 static const unsigned int InitialFNV
= 2166136261u;
38 static const unsigned int FNVMultiple
= 16777619u;
40 /* Fowler / Noll / Vo (FNV) Hash */
41 unsigned int hash
= InitialFNV
;
43 for(int i
= 0; m_string
[i
]; i
++)
45 hash
= hash
^ (m_string
[i
]); /* xor the low 8 bits */
46 hash
= hash
* FNVMultiple
; /* multiply by the magic number */
51 int portableStringCompare(const char* src
, const char* dst
) const
55 while( ! (ret
= *(unsigned char *)src
- *(unsigned char *)dst
) && *dst
)
66 bool equals(const btHashString
& other
) const
68 return (m_string
== other
.m_string
) ||
69 (0==portableStringCompare(m_string
,other
.m_string
));
75 const int BT_HASH_NULL
=0xffffffff;
82 btHashInt(int uid
) :m_uid(uid
)
96 bool equals(const btHashInt
& other
) const
98 return getUid1() == other
.getUid1();
101 SIMD_FORCE_INLINE
unsigned int getHash()const
104 // Thomas Wang's hash
105 key
+= ~(key
<< 15); key
^= (key
>> 10); key
+= (key
<< 3); key
^= (key
>> 6); key
+= ~(key
<< 11); key
^= (key
>> 16);
117 const void* m_pointer
;
123 btHashPtr(const void* ptr
)
128 const void* getPointer() const
133 bool equals(const btHashPtr
& other
) const
135 return getPointer() == other
.getPointer();
139 SIMD_FORCE_INLINE
unsigned int getHash()const
141 const bool VOID_IS_8
= ((sizeof(void*)==8));
143 int key
= VOID_IS_8
? m_hashValues
[0]+m_hashValues
[1] : m_hashValues
[0];
145 // Thomas Wang's hash
146 key
+= ~(key
<< 15); key
^= (key
>> 10); key
+= (key
<< 3); key
^= (key
>> 6); key
+= ~(key
<< 11); key
^= (key
>> 16);
154 template <class Value
>
160 btHashKeyPtr(int uid
) :m_uid(uid
)
169 bool equals(const btHashKeyPtr
<Value
>& other
) const
171 return getUid1() == other
.getUid1();
175 SIMD_FORCE_INLINE
unsigned int getHash()const
178 // Thomas Wang's hash
179 key
+= ~(key
<< 15); key
^= (key
>> 10); key
+= (key
<< 3); key
^= (key
>> 6); key
+= ~(key
<< 11); key
^= (key
>> 16);
187 template <class Value
>
193 btHashKey(int uid
) :m_uid(uid
)
202 bool equals(const btHashKey
<Value
>& other
) const
204 return getUid1() == other
.getUid1();
207 SIMD_FORCE_INLINE
unsigned int getHash()const
210 // Thomas Wang's hash
211 key
+= ~(key
<< 15); key
^= (key
>> 10); key
+= (key
<< 3); key
^= (key
>> 6); key
+= ~(key
<< 11); key
^= (key
>> 16);
217 ///The btHashMap template class implements a generic and lightweight hashmap.
218 ///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
219 template <class Key
, class Value
>
224 btAlignedObjectArray
<int> m_hashTable
;
225 btAlignedObjectArray
<int> m_next
;
227 btAlignedObjectArray
<Value
> m_valueArray
;
228 btAlignedObjectArray
<Key
> m_keyArray
;
230 void growTables(const Key
& /*key*/)
232 int newCapacity
= m_valueArray
.capacity();
234 if (m_hashTable
.size() < newCapacity
)
236 //grow hashtable and next table
237 int curHashtableSize
= m_hashTable
.size();
239 m_hashTable
.resize(newCapacity
);
240 m_next
.resize(newCapacity
);
244 for (i
= 0; i
< newCapacity
; ++i
)
246 m_hashTable
[i
] = BT_HASH_NULL
;
248 for (i
= 0; i
< newCapacity
; ++i
)
250 m_next
[i
] = BT_HASH_NULL
;
253 for(i
=0;i
<curHashtableSize
;i
++)
255 //const Value& value = m_valueArray[i];
256 //const Key& key = m_keyArray[i];
258 int hashValue
= m_keyArray
[i
].getHash() & (m_valueArray
.capacity()-1); // New hash value with new mask
259 m_next
[i
] = m_hashTable
[hashValue
];
260 m_hashTable
[hashValue
] = i
;
269 void insert(const Key
& key
, const Value
& value
) {
270 int hash
= key
.getHash() & (m_valueArray
.capacity()-1);
272 //replace value if the key is already there
273 int index
= findIndex(key
);
274 if (index
!= BT_HASH_NULL
)
276 m_valueArray
[index
]=value
;
280 int count
= m_valueArray
.size();
281 int oldCapacity
= m_valueArray
.capacity();
282 m_valueArray
.push_back(value
);
283 m_keyArray
.push_back(key
);
285 int newCapacity
= m_valueArray
.capacity();
286 if (oldCapacity
< newCapacity
)
289 //hash with new capacity
290 hash
= key
.getHash() & (m_valueArray
.capacity()-1);
292 m_next
[count
] = m_hashTable
[hash
];
293 m_hashTable
[hash
] = count
;
296 void remove(const Key
& key
) {
298 int hash
= key
.getHash() & (m_valueArray
.capacity()-1);
300 int pairIndex
= findIndex(key
);
302 if (pairIndex
==BT_HASH_NULL
)
307 // Remove the pair from the hash table.
308 int index
= m_hashTable
[hash
];
309 btAssert(index
!= BT_HASH_NULL
);
311 int previous
= BT_HASH_NULL
;
312 while (index
!= pairIndex
)
315 index
= m_next
[index
];
318 if (previous
!= BT_HASH_NULL
)
320 btAssert(m_next
[previous
] == pairIndex
);
321 m_next
[previous
] = m_next
[pairIndex
];
325 m_hashTable
[hash
] = m_next
[pairIndex
];
328 // We now move the last pair into spot of the
329 // pair being removed. We need to fix the hash
330 // table indices to support the move.
332 int lastPairIndex
= m_valueArray
.size() - 1;
334 // If the removed pair is the last pair, we are done.
335 if (lastPairIndex
== pairIndex
)
337 m_valueArray
.pop_back();
338 m_keyArray
.pop_back();
342 // Remove the last pair from the hash table.
343 int lastHash
= m_keyArray
[lastPairIndex
].getHash() & (m_valueArray
.capacity()-1);
345 index
= m_hashTable
[lastHash
];
346 btAssert(index
!= BT_HASH_NULL
);
348 previous
= BT_HASH_NULL
;
349 while (index
!= lastPairIndex
)
352 index
= m_next
[index
];
355 if (previous
!= BT_HASH_NULL
)
357 btAssert(m_next
[previous
] == lastPairIndex
);
358 m_next
[previous
] = m_next
[lastPairIndex
];
362 m_hashTable
[lastHash
] = m_next
[lastPairIndex
];
365 // Copy the last pair into the remove pair's spot.
366 m_valueArray
[pairIndex
] = m_valueArray
[lastPairIndex
];
367 m_keyArray
[pairIndex
] = m_keyArray
[lastPairIndex
];
369 // Insert the last pair into the hash table
370 m_next
[pairIndex
] = m_hashTable
[lastHash
];
371 m_hashTable
[lastHash
] = pairIndex
;
373 m_valueArray
.pop_back();
374 m_keyArray
.pop_back();
381 return m_valueArray
.size();
384 const Value
* getAtIndex(int index
) const
386 btAssert(index
< m_valueArray
.size());
388 return &m_valueArray
[index
];
391 Value
* getAtIndex(int index
)
393 btAssert(index
< m_valueArray
.size());
395 return &m_valueArray
[index
];
398 Key
getKeyAtIndex(int index
)
400 btAssert(index
< m_keyArray
.size());
401 return m_keyArray
[index
];
404 const Key
getKeyAtIndex(int index
) const
406 btAssert(index
< m_keyArray
.size());
407 return m_keyArray
[index
];
411 Value
* operator[](const Key
& key
) {
415 const Value
* operator[](const Key
& key
) const {
419 const Value
* find(const Key
& key
) const
421 int index
= findIndex(key
);
422 if (index
== BT_HASH_NULL
)
426 return &m_valueArray
[index
];
429 Value
* find(const Key
& key
)
431 int index
= findIndex(key
);
432 if (index
== BT_HASH_NULL
)
436 return &m_valueArray
[index
];
440 int findIndex(const Key
& key
) const
442 unsigned int hash
= key
.getHash() & (m_valueArray
.capacity()-1);
444 if (hash
>= (unsigned int)m_hashTable
.size())
449 int index
= m_hashTable
[hash
];
450 while ((index
!= BT_HASH_NULL
) && key
.equals(m_keyArray
[index
]) == false)
452 index
= m_next
[index
];
461 m_valueArray
.clear();
467 #endif //BT_HASH_MAP_H