AGX Dynamics 2.41.2.0
Loading...
Searching...
No Matches
HashVector.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#ifndef AGX_HASHVECTOR_H
18#define AGX_HASHVECTOR_H
19
20
21#include <agx/Vector.h>
22#include <agx/HashTable.h>
23
24namespace agx
25{
26
39 template <typename KeyT, typename DataT=KeyT, typename HashT = agx::HashFn<KeyT> >
41 {
42 public:
43
44 typedef DataT value_type;
46
49
50 private:
51
52 VectorType m_vector;
53 HashType m_hash;
54
55 public:
56
58 {
59 SHRINK_BUFFER=VectorType::SHRINK_BUFFER, // Buffer is deallocated and replaced by an empty buffer
60 SHRINK_BUFFER_AVERAGED=VectorType::SHRINK_BUFFER_AVERAGED, // Buffer is shrunk if a smoothing average (which is updated each clear call) goes below a threshold
61 MAINTAIN_BUFFER=VectorType::MAINTAIN_BUFFER // Buffer is maintained
62 };
63
66
67
70 {}
71
73 HashVector(const ContainerType& other) : m_vector( other.m_vector ), m_hash( other.m_hash )
74 {
75 this->clear(SHRINK_BUFFER);
76 *this = other;
77 }
78
81 {
82 if ( this == &other ) {
83 return *this;
84 }
85
86 m_vector = other.m_vector;
87 m_hash = other.m_hash;
88 return *this;
89 }
90
91
94 {
95 // don't change buffer, will be dealloc'ed soon anyway
97 }
98
99 const VectorType& vector() const
100 {
101 return m_vector;
102 }
103
104 const HashType& table() const
105 {
106 return m_hash;
107 }
108
112 size_t size() const
113 {
114 agxAssert( checkSize() );
115
116 return m_vector.size();
117 }
118
122 bool empty() const
123 {
124 return m_vector.empty();
125 }
126
141 template<typename T>
142 iterator push_back(const KeyT& key, T&& data)
143 {
144 agxAssert( checkSize() );
145
146 typename HashType::iterator it = m_hash.find(key);
147 if (it != m_hash.end())
148 {
149 // Replace the already existing data value with the new
150 m_vector[it->second].second = std::forward<T>(data);
151 return &m_vector[it->second];
152 }
153
154 // Key did not exist, insert at the end of the vector
155 m_vector.push_back(std::make_pair(key, std::forward<T>(data)));
156
157 // Hash on data, index is data value
158 m_hash.insert(key, m_vector.size()-1);
159
160 return end()-1; // Return iterator to the newly inserted element.
161 }
162
174 template<typename T>
175 iterator insert(const KeyT& key, T&& data)
176 {
177 agxAssert( checkSize() );
178
179 return push_back(key, std::forward<T>(data));
180 }
181
192 iterator replace( const KeyT& oldKey, const KeyT& newKey, const DataT& data )
193 {
194 agxAssert( checkSize() );
195 auto oldIt = m_hash.find( oldKey );
196 if ( oldIt == m_hash.end() )
197 return end();
198
199 size_t index = oldIt->second;
200 m_vector[ index ] = std::make_pair( newKey, data );
201 m_hash.erase( oldIt );
202 m_hash.insert( newKey, index );
203
204 return begin() + index;
205 }
206
215 bool contains(const KeyT& key) const
216 {
217 agxAssert( checkSize() );
218
219 return m_hash.contains( key );
220 }
221
230 iterator find(const KeyT& key)
231 {
232 agxAssert( checkSize() );
233
234 typename HashType::iterator it = m_hash.find( key );
235 if (it == m_hash.end())
236 return end();
237
238 return &m_vector[it->second];
239 }
240
248 const_iterator find(const KeyT& key) const
249 {
250 agxAssert( checkSize() );
251
252 typename HashType::const_iterator it = m_hash.find( key );
253 if (it == m_hash.end())
254 return end();
255
256 // Return index to the element in the vector
257 return &m_vector[it->second];
258
259 }
260
261
266 {
267 agxAssert( checkSize() );
268
269
270 return m_vector.begin(); }
271
276 {
277 agxAssert( checkSize() );
278 return m_vector.begin();
279 }
280
281
286 {
287 agxAssert( checkSize() );
288 return m_vector.end();
289 }
290
295 {
296 agxAssert( checkSize() );
297 return m_vector.end();
298 }
299
303 DataT& front()
304 {
305 agxAssert( checkSize() );
306 return m_vector[0].second;
307 }
308
312 const DataT& front() const
313 {
314 agxAssert( checkSize() );
315 return m_vector[0].second;
316 }
317
321 DataT& back()
322 {
323 agxAssert( checkSize() );
324 return m_vector[m_vector.size()-1].second;
325 }
326
330 const DataT& back() const
331 {
332 agxAssert( checkSize() );
333 return m_vector[m_vector.size()-1].second;
334 }
335
336
337
347 bool erase(const KeyT& key)
348 {
349
350 agxAssert( checkSize() );
351
352 typename HashType::iterator it = m_hash.find( key );
353 if (it == m_hash.end())
354 return false;
355
356 erase( it );
357 return true;
358 }
359
376 {
377 agxAssert( checkSize() );
378
379 if (it == end())
380 return it;
381
382 KeyT& key = it->first;
383 typename HashType::iterator hashIt = m_hash.find( key );
384
385 agxAssert ( hashIt != m_hash.end() );
386
387 hashIt = erase( hashIt );
388
389 if ( hashIt == m_hash.end() )
390 return end();
391
392 return &m_vector[ hashIt->second ];
393 }
394
400 {
401 agxAssert( checkSize() );
402
403 m_hash.clear( (typename HashType::ClearPolicy)policy );
404 m_vector.clear( (typename VectorType::ClearPolicy)policy );
405 }
406
411 DataT& operator[](size_t i )
412 {
413 agxAssert( checkSize() );
414
415 agxAssert(i < m_vector.size());
416 return m_vector[i].second;
417 }
418
423 const DataT& operator[](size_t i ) const
424 {
425 agxAssert( checkSize() );
426
427 agxAssert(i < m_vector.size());
428 return m_vector[i].second;
429 }
430
435 void reserve(size_t size)
436 {
437 agxAssert( checkSize() );
438
439 m_vector.reserve( size );
440 m_hash.reserve( size );
441 }
442
449 DataT& getOrCreate( const KeyT& key )
450 {
451 iterator it = find( key );
452 if ( it == end() )
453 it = insert( key, value_type() );
454 return it->second;
455 }
456
482 template<typename T>
483 size_t purge(T purger)
484 {
485 if (empty()) // Nothing to do
486 return 0;
487
488#if 0 // Slow version
489 VectorType savedElements; // Elements to keep
490 savedElements.reserve( m_vector.size());
491 VectorType::const_iterator it = m_vector.begin();
492 for(; it != m_vector.end(); ++it)
493 {
494 // Should we keep it?
495 if (!purger(it->first, it->second))
496 savedElements.push_back( std::make_pair(it->first, it->second)); // store all elements that should remain
497 }
500
501 // Make sure we can fit all the saved elements
502 m_vector.reserve( savedElements.size() );
503 m_hash.reserve( savedElements.size() );
504
505 for(VectorType::const_iterator it = savedElements.begin(); it != savedElements.end(); ++it)
506 {
507 m_vector.push_back( *it );
508 // Hash on data, index is data value
509 m_hash.insert( it->first, m_vector.size()-1 );
510 }
511#else // Faster version (2x)
512 typename agx::Vector<typename VectorType::value_type *> removeElements; //PointerVector ; // Safe to use pointers?
513 removeElements.reserve( m_vector.size());
514 for(typename VectorType::iterator it = m_vector.begin(); it != m_vector.end(); ++it)
515 {
516 // Should we keep it?
517 if (!purger((*it).first, (*it).second ))
518 removeElements.push_back(&(*it)); // store all elements that should remain
519 }
520
521 for(typename agx::Vector<typename VectorType::value_type *>::const_iterator it = removeElements.begin(); it != removeElements.end(); ++it)
522 {
523 this->erase( (**it).first );
524 }
525
526 return removeElements.size();
527#endif
528 }
529
530 private:
531
532 // Return true if size of vector and hash is equal
533 bool checkSize() const {
534 return m_vector.size() == m_hash.size();
535 }
536
537 typename HashType::iterator erase( typename HashType::iterator it )
538 {
539 size_t idx = it->second;
540
541 typename HashType::iterator retIt = m_hash.erase( it ); // remove from hash
542
543 // Remove from vector too:
544 if (m_vector.size() > 1 && idx != (m_vector.size()-1))
545 {
546 // Get the last element
547 typename VectorType::value_type lastElement = m_vector.back();
548
549 // Put it where we have removed an element
550 m_vector[idx] = lastElement;
551
552 // remove the last now
553 m_vector.pop_back();
554
555 // Rehash the moved one with the new index
556 retIt = m_hash.insert( lastElement.first, idx );
557 }
558 else
559 // Only one element, OR its the last we are removing: just remove it
560 m_vector.pop_back();
561
562 agxAssert( checkSize() );
563
564 return retIt;
565 }
566
567
568 };
569
570}
571
572
573#endif /* AGX_HASHVECTOR_H */
bool empty() const
Definition: Container.h:136
ClearPolicy
agxData::Values from this enumeration is passed to the subclasses' 'clear' method in order to control...
Definition: Container.h:43
@ SHRINK_BUFFER
Buffer is deallocated and replaced by an newly allocated empty buffer.
Definition: Container.h:44
@ MAINTAIN_BUFFER
Buffer is maintained (normal stl behavior).
Definition: Container.h:46
@ SHRINK_BUFFER_AVERAGED
Buffer is shrunk if a smoothing average (which is updated each clear call) goes below a threshold.
Definition: Container.h:45
size_t size() const
Definition: Container.h:134
This class is a combined container which has the find complexity of a HashTable, deterministic iterat...
Definition: HashVector.h:41
Vector< std::pair< KeyT, DataT > > VectorType
Definition: HashVector.h:47
const DataT & back() const
Definition: HashVector.h:330
const HashType & table() const
Definition: HashVector.h:104
iterator end()
Definition: HashVector.h:285
HashVector(const ContainerType &other)
Copy constructor.
Definition: HashVector.h:73
const VectorType & vector() const
Definition: HashVector.h:99
VectorType::const_iterator const_iterator
Definition: HashVector.h:65
const_iterator end() const
Definition: HashVector.h:294
size_t size() const
Return the number of inserted elements.
Definition: HashVector.h:112
DataT value_type
Definition: HashVector.h:44
const_iterator find(const KeyT &key) const
Perform a hash search for a given key.
Definition: HashVector.h:248
@ SHRINK_BUFFER_AVERAGED
Definition: HashVector.h:60
DataT & operator[](size_t i)
Access an element in the vector using an index.
Definition: HashVector.h:411
const DataT & operator[](size_t i) const
Access an element in the vector using an index.
Definition: HashVector.h:423
HashVector()
Constructor.
Definition: HashVector.h:69
void reserve(size_t size)
Reserve capacity in the hash table.
Definition: HashVector.h:435
HashVector< KeyT, DataT, HashT > ContainerType
Definition: HashVector.h:45
iterator push_back(const KeyT &key, T &&data)
Insert a key,data pair in to the end of the container.
Definition: HashVector.h:142
iterator insert(const KeyT &key, T &&data)
Insert a key,data pair in to the end of the container.
Definition: HashVector.h:175
bool empty() const
Return true if the container is empty.
Definition: HashVector.h:122
void clear(ClearPolicy policy=SHRINK_BUFFER_AVERAGED)
Remove all elements.
Definition: HashVector.h:399
~HashVector()
Destructor.
Definition: HashVector.h:93
bool erase(const KeyT &key)
Erase an element from the container.
Definition: HashVector.h:347
DataT & front()
Definition: HashVector.h:303
iterator find(const KeyT &key)
Perform a hash search for a given key.
Definition: HashVector.h:230
size_t purge(T purger)
Purge the hash set.
Definition: HashVector.h:483
iterator replace(const KeyT &oldKey, const KeyT &newKey, const DataT &data)
Replace data in hash vector.
Definition: HashVector.h:192
bool contains(const KeyT &key) const
Hash search for the key in the container.
Definition: HashVector.h:215
const DataT & front() const
Definition: HashVector.h:312
const_iterator begin() const
Definition: HashVector.h:275
VectorType::iterator iterator
Definition: HashVector.h:64
iterator erase(const iterator &it)
Erase an element using an iterator.
Definition: HashVector.h:375
DataT & back()
Definition: HashVector.h:321
DataT & getOrCreate(const KeyT &key)
Returns value given key.
Definition: HashVector.h:449
HashTable< KeyT, size_t, HashT > HashType
Definition: HashVector.h:48
iterator begin()
Definition: HashVector.h:265
HashVector< KeyT, DataT, HashT > & operator=(const ContainerType &other)
Assignment operator.
Definition: HashVector.h:80
iterator insert(const KeyT &key, const ValueT value)
Insert a key/value pair into the hash table.
bool contains(const KeyT &k) const
Check if the hash table contains a key/value pair for the given key.
iterator end()
Iterator marking end of hash table.
bool erase(const KeyT &key)
Erase an element from the hash table.
void clear(int policy=SHRINK_BUFFER_AVERAGED)
Remove all elements.
void reserve(size_t num_elems)
Make room for this many elements in the hash table.
iterator find(const KeyT &key)
Find a key/value pair in the hash table given a key.
Inheritance with partial specialization due to bug with ref_ptr containers.
Templated vector class.
Definition: agx/Vector.h:53
void clear(ClearPolicy policy=SHRINK_BUFFER_AVERAGED)
Remove all elements, optionally with maintained buffer allocation.
Definition: agx/Vector.h:491
iterator end()
Definition: agx/Vector.h:1044
const T * const_iterator
Definition: agx/Vector.h:63
iterator begin()
Definition: agx/Vector.h:1041
T & back() const
Definition: agx/Vector.h:707
void reserve(size_t size)
Reserve capacity in the vector.
Definition: agx/Vector.h:583
T * iterator
Definition: agx/Vector.h:62
void pop_back()
Definition: agx/Vector.h:754
void push_back(const T2 &value)
Definition: agx/Vector.h:715
#define agxAssert(expr)
Definition: debug.h:143
The agx namespace contains the dynamics/math part of the AGX Dynamics API.