G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsSortedVector.h
Go to the documentation of this file.
1
15#pragma once
16
17//#include <vector>
18//#include <algorithm> // For lower_bound
19
20#ifndef TORCH_VERSION
21namespace std
22{
23
24template<typename T1, typename T2>
25std::ostream& operator << ( std::ostream& os,
26 const std::pair<T1,T2>& rhs )
27{
28 os << rhs.first << ", " << rhs.second;
29 return os;
30}
31
32}//namespace std
33#endif
34
35namespace gismo {
36
108template<class T, class _A = std::allocator<T> >
109class gsSortedVector : public std::vector<T, _A>
110{
111 typedef std::vector<T,_A> inherited;
112
113public:
114 typedef typename std::vector<T>::const_iterator const_iterator;
115 typedef typename std::vector<T>::iterator iterator;
116
117public:
118
119//
121 : std::vector<T, _A>( ), m_bSorted(true) { }
122
123 gsSortedVector( typename std::vector<T>::const_iterator start
124 , typename std::vector<T>::const_iterator end)
125 : std::vector<T, _A>(start,end), m_bSorted(0) { };
126
127
128//
129 //-------------------------------------------------------------------//
130 // SetSorted() //
131 //-------------------------------------------------------------------//
132 // I didn't want to override every constructor to set this
133 // member variable, so this function is publicly accessible.
134 // You should call SetSorted( true ) right after construction.
135 // TO DO: if you feel like it... derive all constructors to avoid
136 // the need for this. There are 4 last time I checked.
137 //-------------------------------------------------------------------//
138 void SetSorted( bool bSorted = true ) { m_bSorted = bSorted; }
139
140 //-------------------------------------------------------------------//
141 // sort() //
142 //-------------------------------------------------------------------//
143 // This function sorts the data as needed. Call it after repeated calls to
144 // push_unsorted(), or just let other members call it for you on next access.
145 // It calls std::sort(), which defaults to using operator<() for
146 // comparisons.
147 //-------------------------------------------------------------------//
148 void sort()
149 {
150 if ( !m_bSorted )
151 {
152 std::sort( inherited::begin(), inherited::end() );
153 SetSorted();
154 }
155 }
156
157 bool bContains( const T& t ) const
158 {
159 if ( !m_bSorted )
160 gsWarn<<"gsSortedVector is not sorted, bContains("<<t<<")"
161 << "is not guaranteed to be correct.\n";
162
163 return std::binary_search( inherited::begin(), inherited::end(), t );
164 }
165
166 typename std::vector<T>::iterator lower_bound_it( const T& key )
167 {
168 if ( !m_bSorted )
169 sort();
170
171 typename std::vector<T>::iterator it = std::lower_bound( inherited::begin(), inherited::end(), key );
172 return it;
173 }
174
175 /*const*/ T* lower_bound_ptr( const T& key )
176 {
177 typename std::vector<T>::iterator it = lower_bound_it( key );
178
179 if (it==inherited::end())
180 return 0;
181
182 /*const*/ T* t = &(*it);
183 return t;
184 }
185
186
187 //-------------------------------------------------------------------//
188 // find_it_or_fail() //
189 //-------------------------------------------------------------------//
190 // This function takes the given object and determines if there is
191 // a match in the vector. It returns an iterator to the actual
192 // object in the vector, if found. Otherwise returns std::vector::end().
193 //
194 // This is the function you want to use most of the time
195 // (or the predicate version if you are using object pointers).
196 //
197 // USAGE: it makes most sense to use this function if you have
198 // an object with a key, other member variables, and operator<()
199 // that uses the key to test for equality. You then set up a dummy
200 // "search" object with the key set to the search value, call the
201 // function, and use the result to extract the additional information
202 // from the object.
203 //-------------------------------------------------------------------//
204 typename std::vector<T>::iterator find_it_or_fail( const T& key )
205 {
206 typename std::vector<T>::iterator it = lower_bound_it( key );
207
208 if ( it != inherited::end() )
209
210 // lower_bound() does not necessarily indicate a successful search.
211 // The iterator points to the object where an insertion
212 // should take place. We check that result to see if we actually
213 // had an exact match.
214
215 // NOTE: This is how the STL determines equality using only operator()<.
216 // Two comparisons, ugg, but it is a nice little trick.
217 if( !((*it)<key) && !(key<(*it)) )
218
219 return it;
220
221 return inherited::end();
222 }
223
224 typename std::vector<T>::const_iterator find_it_or_fail( const T& key ) const
225 {
226 typename std::vector<T>::const_iterator it =
227 std::lower_bound( inherited::begin(), inherited::end(), key );
228
229 if ( it != inherited::end() )
230 if( !((*it)<key) && !(key<(*it)) )
231 return it;
232
233 return inherited::end();
234 }
235
236 //-------------------------------------------------------------------//
237 // find_ptr_or_fail() //
238 //-------------------------------------------------------------------//
239 // A variation of find_it_or_fail() that provides a pointer to result.
240 //-------------------------------------------------------------------//
241 T* find_ptr_or_fail( const T& key )
242 {
243 typename std::vector<T>::iterator it = find_it_or_fail( key );
244 if ( it != inherited::end() )
245 return &(*it);
246
247 return 0;
248 }
249
250 // Same as find_it_or_fail but return an index instead of an iterator
251 size_t getIndex(const T& key ) const
252 {
253 return find_it_or_fail(key) - inherited::begin();
254 }
255
256 //-------------------------------------------------------------------//
257 // push_sorted() //
258 //-------------------------------------------------------------------//
259 // This is used to insert into a vector that always remains sorted.
260 // Because we have a sorted vector, finding the insertion location
261 // with std::lower_bound() is relatively cheap.
262 //
263 // If you have multiple insertions, consider
264 // using push_unsorted() for each, then calling sort().
265 //-------------------------------------------------------------------//
266 void push_sorted( const T& t )
267 {
268 if ( !m_bSorted )
269 {
270 sort();
271 }
272
273 // Insert at "lower_bound" (the proper sorted location).
274 inherited::insert( std::lower_bound( inherited::begin(), inherited::end(), t ), t );
275 }
276
277 // Same as push_sorted but only inserts the element if it does not exist already
278 void push_sorted_unique( const T& t )
279 {
280 if ( !m_bSorted )
281 {
282 sort();
283 }
284
285 // iterator itr// Assumes sorted in ascending order
286 // = std::lower_bound(vec.begin(), vec.end(), e, std::greater<C>() );
287 iterator pos = std::lower_bound(inherited::begin(), inherited::end(), t );
288
289 if ( pos == inherited::end() || *pos != t )// If not found
290 inherited::insert(pos, t);
291
292 }
293
294 //-------------------------------------------------------------------//
295 // push_unsorted() //
296 //-------------------------------------------------------------------//
297 // This is similar to push_back(), but in addition, it sets the
298 // unsorted flag.
299 //-------------------------------------------------------------------//
300 void push_unsorted( const T& t )
301 {
302 SetSorted( false );
303 this->push_back(t);
304 }
305
306 size_t uniqueSize() const
307 {
308 if ( inherited::begin() == inherited::end() )
309 return 0;
310
311 if ( !m_bSorted )
312 gsWarn<<"gsSortedVector is not sorted, uniqueSize()"
313 << "is not guaranteed to be correct.\n";
314
315 size_t cnt = 1;
316 for (const_iterator it = inherited::begin()+1; it != inherited::end(); ++it)
317 if ( *(it-1) != *(it) ) ++cnt;
318
319 return cnt;
320 }
321
322 //-------------------------------------------------------------------//
323 // operator=() //
324 //-------------------------------------------------------------------//
325 // This allows us to set the gsSortedVector from a std::vector.
326 //-------------------------------------------------------------------//
327 gsSortedVector<T>& operator=(std::vector<T> v)
328 {
329 v.swap(*this);
330 sort();
331 return *this;
332 }
333
334 // CALLS WHERE YOU PROVIDE THE FUNCTOR OR FUNCTION POINTER
335 // If you need to use a predicate sort function, ALWAYS use these methods
336 // instead of the non-functor versions.
337 // NOTE: UPDATE THIS when C++0x polymorphic function wrappers are available.
338 template<class _Pr> inline
339 void sort( _Pr pr )
340 {
341 if ( !m_bSorted )
342 {
343 std::sort( inherited::begin(), inherited::end(), pr );
344 SetSorted();
345 }
346 }
347 template<class _Pr> inline
348 typename std::vector<T>::iterator lower_bound_it( const T& key, _Pr pr )
349 {
350 if ( !m_bSorted )
351 {
352 std::sort( inherited::begin(), inherited::end(), pr );
353 SetSorted();
354 }
355 typename std::vector<T>::iterator it = std::lower_bound( inherited::begin(), inherited::end(), key, pr );
356 return it;
357 }
358
359 template<class _Pr> inline
360 /*const*/ T* lower_bound_ptr( const T& key, _Pr pr )
361 {
362 typename std::vector<T>::iterator it = lower_bound_it( key, pr );
363
364 if (it==inherited::end())
365 return 0;
366
367 /*const*/ T* t = &(*it);
368 return t;
369 }
370
371 template<class _Pr> inline
372 void push_sorted( const T& t, _Pr pr )
373 {
374 if ( !m_bSorted )
375 {
376 std::sort( inherited::begin(), inherited::end(), pr );
377 SetSorted();
378 }
379
380 // Insert at "lower_bound" (the proper sorted location).
381 insert( std::lower_bound( inherited::begin(), inherited::end(), t, pr ), t );
382 }
383
384 template<class _Pr> inline
385 typename std::vector<T>::iterator find_it_or_fail( const T& key, _Pr pr )
386 {
387 typename std::vector<T>::iterator it = lower_bound_it( key, pr );
388
389 if ( it != inherited::end() )
390 // NOTE: We have to apply this using the predicate function, be careful...
391 if (!(pr((*it), key)) && !(pr(key,(*it))))
392 return it;
393
394 return inherited::end();
395 }
396
397 template<class _Pr> inline
398 T* find_ptr_or_fail( const T& key, _Pr pr )
399 {
400 typename std::vector<T>::iterator it = find_it_or_fail( key, pr );
401 if ( it != inherited::end() )
402 return &(*it);
403
404 return 0;
405 }
406
407protected:
408 bool m_bSorted;
409
410private:
411
412 // to do
413 //void push_back( const T& t);
414
415};
416
417
418} //namespace gismo
419
This class is derived from std::vector, and adds sort tracking.
Definition gsSortedVector.h:110
#define gsWarn
Definition gsDebug.h:50
The G+Smo namespace, containing all definitions for the library.