AGX Dynamics 2.41.2.0
Loading...
Searching...
No Matches
SetVector.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#pragma once
18
19
20#include <agx/Vector.h>
21#include <agx/HashTable.h>
22
23namespace agx
24{
25
36 template <typename DataT, typename HashT = HashFn<DataT> >
38 {
39 public:
40
41 typedef DataT value_type;
42 typedef const DataT& const_reference;
43 typedef size_t size_type;
47
48 private:
49 VectorType m_vector;
50 HashType m_hash;
51
52 public:
53#ifndef SWIG
55 {
56 SHRINK_BUFFER=VectorType::SHRINK_BUFFER, // Buffer is deallocated and replaced by an empty buffer
57 SHRINK_BUFFER_AVERAGED=VectorType::SHRINK_BUFFER_AVERAGED, // Buffer is shrunk if a smoothing average (which is updated each clear call) goes below a threshold
58 MAINTAIN_BUFFER=VectorType::MAINTAIN_BUFFER // Buffer is maintained
59 };
60#endif
61
66
67
70 {}
71
73 SetVector(const ContainerType& other) : m_vector( other.m_vector ), m_hash( other.m_hash )
74 {
75 this->clear(SHRINK_BUFFER);
76 *this = other;
77 }
78
80 ContainerType& operator= (const ContainerType& other) // NOLINT clang-tidy-7 doesn't realize that ContainerType is a SetVector.
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
102 const VectorType& vector() const
103 {
104 return m_vector;
105 }
106
110 const HashType& table() const
111 {
112 return m_hash;
113 }
114
118 inline size_t size() const
119 {
120 agxAssert( checkSize() );
121
122 return m_vector.size();
123 }
124
128 inline bool empty() const
129 {
130 return m_vector.empty();
131 }
132
147 template< typename T2 >
148 inline iterator push_back(const T2& data)
149 {
150 agxAssert( checkSize() );
151
152 typename HashType::iterator it = m_hash.find(data);
153 if (it != m_hash.end())
154 {
155 // Replace the already existing data value with the new
156 m_vector[it->second] = data;
157 return &m_vector[it->second];
158 }
159
160 // Key did not exist, insert at the end of the vector
161 m_vector.push_back( data );
162
163 // Hash on data, index is data value
164 m_hash.insert( data, m_vector.size()-1 );
165
166 return end()-1; // Return iterator to the newly inserted element.
167 }
168
181 template< typename T2 >
182 inline iterator insert(const T2& data)
183 {
184 agxAssert( checkSize() );
185
186 return push_back(data);
187 }
188
199 template< typename OldDataT, typename NewDataT >
200 iterator replace( const OldDataT& oldData, const NewDataT& newData )
201 {
202 agxAssert( checkSize() );
203
204 auto oldIt = m_hash.find( oldData );
205 if ( oldIt == m_hash.end() )
206 return end();
207
208 size_t index = oldIt->second;
209 m_vector[ index ] = newData;
210 m_hash.erase( oldIt );
211 m_hash.insert( newData, index );
212
213 return begin() + index;
214 }
215
224 template< typename T2 >
225 inline bool contains(const T2& key) const
226 {
227 agxAssert( checkSize() );
228
229 return m_hash.contains( key );
230 }
231
240 template< typename T2 >
241 iterator find(const T2& key)
242 {
243 agxAssert( checkSize() );
244
245 typename HashType::iterator it = m_hash.find( key );
246 if (it == m_hash.end())
247 return end();
248
249 return &m_vector[it->second];
250 }
251
259 template< typename T2 >
260 const_iterator find(const T2& key) const
261 {
262 agxAssert( checkSize() );
263
264 typename HashType::const_iterator it = m_hash.find( key );
265 if (it == m_hash.end())
266 return end();
267
268 // Return index to the element in the vector
269 return &m_vector[it->second];
270 }
271
272#ifndef SWIG
277 {
278 agxAssert( checkSize() );
279
280 return m_vector.begin();
281 }
282
286 inline const_iterator begin() const
287 {
288 agxAssert( checkSize() );
289
290 return m_vector.begin();
291 }
292
297 {
298 agxAssert( checkSize() );
299
300 return m_vector.rbegin();
301 }
302
307 {
308 agxAssert( checkSize() );
309
310 return m_vector.rbegin();
311 }
312
316 inline iterator end()
317 {
318 agxAssert( checkSize() );
319
320 return m_vector.end();
321 }
322
326 inline const_iterator end() const
327 {
328 agxAssert( checkSize() );
329 return m_vector.end();
330 }
331
336 {
337 agxAssert( checkSize() );
338
339 return m_vector.rend(); }
340
345 {
346 agxAssert( checkSize() );
347 return m_vector.rend();
348 }
349#endif
353 inline DataT& front()
354 {
355 agxAssert( checkSize() );
356 return m_vector[0];
357 }
358
362 inline const DataT& front() const
363 {
364 agxAssert( checkSize() );
365 return m_vector[0];
366 }
367
371 inline DataT& back()
372 {
373 agxAssert( checkSize() );
374 return m_vector[m_vector.size()-1];
375 }
376
380 inline const DataT& back() const
381 {
382 agxAssert( checkSize() );
383 return m_vector[m_vector.size()-1];
384 }
385
386
396 template< typename T2 >
397 bool erase(const T2& key)
398 {
399 agxAssert( checkSize() );
400
401 typename HashType::iterator it = m_hash.find( key );
402 if (it == m_hash.end())
403 return false;
404
405 erase( it );
406 return true;
407 }
408
422 bool erase(const iterator& it)
423 {
424
425 agxAssert( checkSize() );
426
427 if (it == end())
428 return false;
429 agxAssert( it != end() );
430
431 DataT& key = *it;
432 typename HashType::iterator hashIt = m_hash.find( key );
433
434 agxAssert ( hashIt != m_hash.end() );
435
436 erase( hashIt );
437
438 return true;
439 }
440
445#ifndef SWIG
447#else
448 void clear()
449#endif
450 {
451
452 agxAssert( checkSize() );
453
454 m_hash.clear( (typename HashType::ClearPolicy)policy );
455 m_vector.clear( (typename VectorType::ClearPolicy)policy );
456 }
457
462 inline DataT& operator[](size_t i )
463 {
464 agxAssert( checkSize() );
465
466 agxAssert(i < m_vector.size());
467 return m_vector[i];
468 }
469
474 inline const DataT& operator[](size_t i ) const
475 {
476 agxAssert( checkSize() );
477
478 agxAssert(i < m_vector.size());
479 return m_vector[i];
480 }
481
482
488 inline const DataT& at(size_t index) const
489 {
490 return m_vector.at(index);
491 }
492
493
499 inline DataT& at(size_t index)
500 {
501 return m_vector.at(index);
502 }
503
504
509 void reserve(size_t size)
510 {
511 agxAssert( checkSize() );
512
513 m_vector.reserve( size );
514 m_hash.reserve( size );
515 }
516
517
518
544 template<typename T>
545 size_t purge(T purger)
546 {
547 if (empty()) // Nothing to do
548 return 0;
549
550#if 0 // Slower implementation
551 typename VectorType savedElements; // Elements to keep
552 savedElements.reserve( m_vector.size());
553 typename VectorType::const_iterator it = m_vector.begin();
554 for(; it != m_vector.end(); ++it)
555 {
556 // Should we keep it?
557 if (!purger(*it))
558 savedElements.push_back(*it); // store all elements that should remain
559 }
562
563 // Make sure we can fit all the saved elements
564 m_vector.reserve( savedElements.size() );
565 m_hash.reserve( savedElements.size() );
566
567 for(typename VectorType::const_iterator it = savedElements.begin(); it != savedElements.end(); ++it)
568 {
569 m_vector.push_back( *it );
570 // Hash on data, index is data value
571 m_hash.insert( *it, m_vector.size()-1 );
572 }
573#else // Faster implementation
574 typename agx::Vector<typename VectorType::value_type *> removeElements; // Safe to use pointers?
575 removeElements.reserve( m_vector.size());
576 for(typename VectorType::iterator it = m_vector.begin(); it != m_vector.end(); ++it)
577 {
578 // Should we keep it?
579 if (!purger(*it))
580 removeElements.push_back(&(*it)); // store all elements that should remain
581 }
582
583 for(typename agx::Vector<typename VectorType::value_type *>::const_iterator it = removeElements.begin(); it != removeElements.end(); ++it)
584 {
585 this->erase( **it );
586 }
587
588 return removeElements.size();
589#endif
590 }
591
592 private:
593
594 // Return true if size of vector and hash is equal
595 AGX_FORCE_INLINE bool checkSize() const {
596 return m_vector.size() == m_hash.size();
597 }
598
599 void erase( typename HashType::iterator it )
600 {
601 size_t idx = it->second;
602
603 m_hash.erase( it ); // remove from hash
604
605 // Remove from vector too:
606 if (m_vector.size() > 1 && idx != (m_vector.size()-1))
607 {
608 // Get the last element
609 typename VectorType::value_type lastElement = m_vector.back();
610
611 // Put it where we have removed an element
612 m_vector[idx] = lastElement;
613
614 // remove the last now
615 m_vector.pop_back();
616
617 // Rehash the moved one with the new index
618 m_hash.insert( lastElement, idx );
619 }
620 else
621 // Only one element, OR its the last we are removing: just remove it
622 m_vector.pop_back();
623
624 agxAssert( checkSize() );
625 }
626
627
628 };
629
630}
631
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
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.
This class is a combined container which has the find complexity of a HashTable, deterministic iterat...
Definition: SetVector.h:38
const DataT & back() const
Definition: SetVector.h:380
DataT & front()
Definition: SetVector.h:353
void reserve(size_t size)
Reserve capacity in the hash table.
Definition: SetVector.h:509
DataT & operator[](size_t i)
Access an element in the vector using an index.
Definition: SetVector.h:462
size_t purge(T purger)
Purge the hash set.
Definition: SetVector.h:545
bool contains(const T2 &key) const
Hash search for the data in the container.
Definition: SetVector.h:225
const VectorType & vector() const
Definition: SetVector.h:102
DataT & at(size_t index)
Access an element in the vector using an index.
Definition: SetVector.h:499
VectorType::const_reverse_iterator const_reverse_iterator
Definition: SetVector.h:65
const_iterator end() const
Definition: SetVector.h:326
iterator find(const T2 &key)
Perform a hash search for a given key.
Definition: SetVector.h:241
HashTable< DataT, size_t, HashT > HashType
Definition: SetVector.h:46
iterator begin()
Definition: SetVector.h:276
@ SHRINK_BUFFER_AVERAGED
Definition: SetVector.h:57
const_iterator find(const T2 &key) const
Perform a hash search for a given key.
Definition: SetVector.h:260
void clear(ClearPolicy policy=SHRINK_BUFFER_AVERAGED)
Remove all elements.
Definition: SetVector.h:446
VectorType::reverse_iterator reverse_iterator
Definition: SetVector.h:64
iterator end()
Definition: SetVector.h:316
const_iterator begin() const
Definition: SetVector.h:286
const_reverse_iterator rbegin() const
Definition: SetVector.h:306
bool erase(const iterator &it)
Erase an element using an iterator.
Definition: SetVector.h:422
reverse_iterator rbegin()
Definition: SetVector.h:296
SetVector()
Constructor.
Definition: SetVector.h:69
SetVector(const ContainerType &other)
Copy constructor.
Definition: SetVector.h:73
iterator push_back(const T2 &data)
Insert a data element in to the end of the container.
Definition: SetVector.h:148
bool empty() const
Return true if the container is empty.
Definition: SetVector.h:128
const DataT & front() const
Definition: SetVector.h:362
iterator insert(const T2 &data)
Insert a data element in to the end of the container.
Definition: SetVector.h:182
const HashType & table() const
Definition: SetVector.h:110
size_t size() const
Return the number of inserted elements.
Definition: SetVector.h:118
Vector< DataT > VectorType
Definition: SetVector.h:45
iterator replace(const OldDataT &oldData, const NewDataT &newData)
Replace data in set vector.
Definition: SetVector.h:200
reverse_iterator rend()
Definition: SetVector.h:335
ContainerType & operator=(const ContainerType &other)
Assignment operator.
Definition: SetVector.h:80
VectorType::const_iterator const_iterator
Definition: SetVector.h:63
const DataT & const_reference
Definition: SetVector.h:42
bool erase(const T2 &key)
Erase an element from the container.
Definition: SetVector.h:397
const DataT & operator[](size_t i) const
Access an element in the vector using an index.
Definition: SetVector.h:474
SetVector< DataT, HashT > ContainerType
Definition: SetVector.h:44
DataT value_type
Definition: SetVector.h:41
VectorType::iterator iterator
Definition: SetVector.h:62
size_t size_type
Definition: SetVector.h:43
const DataT & at(size_t index) const
Access an element in the vector using an index.
Definition: SetVector.h:488
DataT & back()
Definition: SetVector.h:371
~SetVector()
Destructor.
Definition: SetVector.h:93
const_reverse_iterator rend() const
Definition: SetVector.h:344
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
reverse_iterator rbegin()
Definition: agx/Vector.h:1053
iterator end()
Definition: agx/Vector.h:1044
T & at(size_t index) const
Definition: agx/Vector.h:691
const DataT * 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
void pop_back()
Definition: agx/Vector.h:754
void push_back(const T2 &value)
Definition: agx/Vector.h:715
std::reverse_iterator< iterator > reverse_iterator
Definition: agx/Vector.h:137
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: agx/Vector.h:138
reverse_iterator rend()
Definition: agx/Vector.h:1056
#define agxAssert(expr)
Definition: debug.h:143
#define AGX_FORCE_INLINE
Definition: macros.h:58
The agx namespace contains the dynamics/math part of the AGX Dynamics API.