Flow123d  jenkins-Flow123d-linux-release-multijob-198
sys_vector.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file
26  * @brief Vector classes to support both Iterator, index and Id access and creating co-located vectors.
27  *
28  * @todo Implement co-located vector class that takes reference of the original Vector and
29  * is of the same size. FullIterator should have method for accessing elements in the original vector.
30  */
31 #ifndef SYS_VECTOR_HH_
32 #define SYS_VECTOR_HH_
33 
34 #include <vector>
35 #include <map>
36 #include "global_defs.h"
37 #include "system.hh"
38 
39 // OPEN NAME SPACE "flow"
40 namespace flow {
41 
42 /**
43  * @brief Iterator that keeps also reference to its container. Safer and provides indexes.
44  *
45  * Full iterator into a Vector<T> container. It makes
46  * an envelop around std:vector<T>::iterator, but stores also reference of
47  * the container it points into. Consequently FullIter can return index.
48  * The container has to be provided when FullIterator is created and this container can not be changed
49  * during the life of the variable. This is intentional since more safe.
50  *
51  * This class is larger then normal pointer i.e. Iter type and therefore is questionable
52  * to use it in the large arrays. To this and you can use Iter and later convert it to FullIter
53  * providing the container It points into.
54  *
55  */
56 
57 template <class Cont>
59 {
60 public:
61  /// Constructor to make uninitialized FullIterator for a container.
62  FullIterator(Cont &cont_par)
63  : cont(cont_par),
64  iter(cont_par.storage.end()) {}
65 
66  /// Constructor to make FullIterator from container and its std::vector iterator.
67  /// Mainly for internal use.
68  FullIterator(const Cont &cont_par,const typename Cont::iterator it)
69  : cont(cont_par),
70  iter(it) {}
71 
72  /// Constructor to make FullIterator from container and Iter i.e. T*
73  FullIterator(Cont &cont_par,const typename Cont::Iter it)
74  : cont(cont_par)
75  {
76  if (it == NULL) iter = cont_par.storage.end();
77  else iter = cont_par.storage.begin() + cont.index(it);
78  }
79 
80  /// Check validity of FullIterator.
81  inline bool is_valid()
82  { return this->iter != this->cont.storage.end(); }
83 
84  /**
85  * Get index of FullIterator in its container.
86  * Return invalid index -1 for undefined iterator.
87  */
88  inline int index() const
89  { if (this->iter != this->cont.storage.end()) return this->iter - cont.storage.begin();
90  else return (-1);
91  }
92 
93  /// Get reference to the container of the FullIterator.
94  inline Cont &container()
95  { return cont; }
96 
97  /// Assign operator. In debugging version check that containers of both FullIterator match.
98  inline FullIterator & operator =(const FullIterator &orig)
99  {
100  // container.storage.begin() == orig.container.storage.begin()
101  ASSERT( (&(this->cont) == &(orig.cont)),"Can not change container of FulIter.\n");
102  this->iter=orig.iter;
103  return (*this);
104  }
105 
106  /// Type cast to Iter i.e. standard pointer.
107  inline operator typename Cont::Iter () const
108  { return &(*(this->iter)); }
109 
110  /// * dereference operator
111  inline typename Cont::ElementType & operator *() const
112  { return *(this->iter); }
113 
114  /// -> dereference operator
115  inline typename Cont::ElementType * operator ->() const
116  { return &(*(this->iter)); }
117 
118  inline FullIterator &operator += (const int shift)
119  { this->iter+=shift; return (*this); }
120 
121  inline FullIterator &operator -= (const int shift)
122  { this->iter-=shift; return (*this); }
123 
124  /// Comparison of two FullIterator.
125  inline bool operator == (const FullIterator &it) const
126  { return ( &(this->cont) == &(it.cont)) && (this->iter == it.iter); }
127 
128  inline bool operator != (const FullIterator &it) const
129  { return ( &(this->cont) != &(it.cont)) || (this->iter != it.iter) ; }
130 
131  /// Prefix. Advance operator.
133  {
134  ASSERT( iter != cont.storage.end(), "Can not advance iterator at the end.\n");
135  ++(this->iter); return *this;
136  }
137 
138  /// Postfix. Should not be used since involves iterator copy.
139  inline FullIterator operator ++ (int);
140 
141  /// Prefix. Advance to previous operator.
143  {
144  ASSERT( iter != cont.storage.begin(), "Can not advance iterator to previous of begin().\n");
145  this->iter--; return *this;
146  }
147 
148  /// Postfix. Should not be used since involves iterator copy.
149  inline FullIterator operator -- (int);
150 
151  // + - opeartors is better to define outside if we ever allow them.
152 protected:
153  /// We have here reference to the container of the iterator. So, an instance of this class can not change the container.
154  const Cont &cont;
155  // Conatainer iterator.
156  typename Cont :: iterator iter;
157 };
158 
159 /**
160  * Small extension of the class FullIterator<Cont>. Provides id() method to get id number of the iterator.
161  * In contrast to FullIterator<> this is templated only by the element type of the container which is always VectorId<T>.
162  */
163 template <class T>
164 class VectorId;
165 
166 template <class T>
167 class FullIteratorId : public FullIterator< VectorId<T> > {
168 public:
169  /// Constructor. Just call base class.
171  : FullIterator<VectorId<T> >(cont) {}
172  /// Constructor. Just call base class.
174  : FullIterator< VectorId<T> >(cont, it) {}
175  /// Constructor. Just call base class.
177  : FullIterator< VectorId<T> >(cont, it) {}
178  /// Returns id of the iterator. See VectorId documentation.
179  inline int id()
180  { return this->cont.id_storage[ this->index() ]; }
181 };
182 
183 
184 
185 /**
186  * @brief Envelop over std::vector, use enhanced iterators.
187  *
188  * Differences compared to std::vector.
189  *
190  * -# Implement only subset of std::vector methods.
191  *
192  * -# iterator Iter - which is nothing else then T *. This we use since it can be initializeted to NULL as universal "non valid value".
193  * for iterators one has to comapre to std::vector.end(), but the container is not always at hand.
194  * This should be used in complex mesh structures to save space.
195  *
196  * -# iterator FullIter - this is standard iterator which contains also reference to the containre it points to. Then it has more
197  * save "non valid value" method. Can be constructer from Iter and a container. You can get the index of this iterator.
198  * This is meant to be use as local variable.
199  * Using this instead of standard iterators It provides function to get index of an iterator
200  *
201  * -# Provides method to get index of a pointer i.e. Iter.
202  *
203  * -# add_item can be used to add a new element and get reference to it so that it can be initialized
204  * Useful even for T be class since when creating a new element the default constructor is called
205  * which can not fill it with values.
206  *
207  * <b> Developer note: </b>
208  *
209  * It appears very dangerous to combine reallocating std::vectors with iterators implemented as pointers.
210  * Indeed, when vector array is reallocated old pointers become invalid. One possibility is to strictly
211  * distinguish crating of the array and later creating references into it. Another is to implement iterators by indexes
212  * which means also to use only FullIterators.
213  */
214 
215 template <class T>
216 class Vector
217 {
218 public:
219  /// We have to export template type for FullIteraror.
220  typedef T ElementType;
221  /// Default iterator for this class.
222  typedef T * Iter;
223  /// For compatibility with std::algorithms we provide also standard iterators.
224  /// Theoretically it should work also with Iter. Test that if you need it.
227  /// Type of FullIterator that should be used to iterate through this container.
229 
230 
231  /// Construct with reserve the space. Includes default constructor.
232  Vector(unsigned int size = 0) : storage(0)
233  {this->reserve(size);}
234 
235  /**
236  * Add a new element into the container. Return iterator to it.
237  * Provides a way to add new element to the container and get an iterator to set its values.
238  * This way we need not copy a new element.
239  */
241  {
242  storage.resize( storage.size() + 1 );
243  return FullIter( *this, storage.begin() + storage.size() - 1 );
244  }
245 
246  /**
247  * For given pointer returns the index of the element in the Vector. The first element has zero index.
248  */
249  inline unsigned int index(Iter pointer) const
250  {
251  ASSERT( pointer >= &(storage.front()) && pointer <= &(storage.back()),
252  "Wrong pointer %d to obtain its index (%d, %d).\n",pointer, &(storage.front()), &(storage.back()));
253  return ( pointer - &(storage.front()) );
254  }
255 
256  /// Returns FullFullIterer of the first element.
257  inline FullIter begin()
258  { return FullIter( *this, storage.begin() ); }
259 
260  /// Returns FullFullIterer of the fictions past the end element.
261  inline FullIter end()
262  { return FullIter( *this, storage.end() ); }
263 
264  /// Returns size of the container. This is independent of the allocated space.
265  inline unsigned int size() const
266  { return storage.size(); }
267 
268  /// Returns size of the container. This is independent of the allocated space.
269  inline void resize(const unsigned int size)
270  { storage.resize(size); }
271 
272 
273  /// Gets reference to the element specified by index.
274  inline T & operator[](unsigned int idx)
275  {
276  ASSERT( idx < this->size(), "Index %d outside of Vector of size %d\n",idx, this->size());
277  return storage[idx];
278  }
279 
280  /// Gets reference to the element specified by index.
281  inline const T & operator[](unsigned int idx) const
282  {
283  ASSERT( idx < this->size(), "Index %d outside of Vector of size %d\n",idx, this->size());
284  return storage[idx];
285  }
286 
287 
288  /// Gets iterator of the element specified by index.
289  inline FullIter operator()(unsigned int idx)
290  {
291  ASSERT( idx < this->size(), "Index %d outside of Vector of size %d\n",idx, this->size());
292  return FullIter( *this, begin()+idx );
293  }
294 
295 
296  /// Reallocates the container space.
297  inline void reserve(unsigned int size)
298  {
299  ASSERT( size >= this->size(), "Vector can not be reallocated into space %d smaller then its size %d\n",size,this->size());
300  storage.reserve(size);
301  }
302 
303  /// Alternative way to make FullIterer form Iter. This way you need not write
304  /// the full FullIter type to call the constructor. Then the result can be assigned to
305  /// suitable local FullIter variable.
307  { return FullIter(*this, it); }
308 
309  /// Since storage is direct member it is deallocated by its own destructor.
310  virtual ~Vector() {}
311 
312 protected:
313  /// Underlying vector container.
315 
316  friend class FullIterator< Vector<T> >;
317 };
318 
319 
320 /**
321  * @brief Small extension of Vector<T> container with support to Id numbers.
322  *
323  * This stores Id numbers of added elements
324  * and can latter access elements by id. An Id can be any integer number that only has to be unique
325  * for every element in the container. In particular Id numbers are need not to be continuous neither keep the ordering of the elements.
326  * Main application is to keep Id numbers from input, which are only necessary to amke correct references during input and possibly to
327  * generate consistent output. Id numbers are useless for calculations.
328  *
329  * <b> Developer Note: </b>
330  *
331  * I have tried to make one common base class VectorBase which
332  * should have storage member and implements basic operations with it.
333  * But I can not make it to return FullIterator which has to be initialized
334  * with reference to the container so not VectorBase but some of its descendants.
335  * Only way seems to construct FullIterator by any pointer which could be type cast
336  * to the type of the container which is template parameter of FullIter.
337  * But such constructor should be used only by VectorXXX classes, but we can not make
338  * VectorBase<T, It> friend for any T and any It.
339  * However all this seems to be too complicated and ugly so I and up with lot of repetitive code
340  * in implementation of VectorXXX classes.
341  *
342  */
343 
344 
345 
346 template <class T>
347 class VectorId
348 {
349 public:
350  /// We have to export template type for FullIteraror.
351  typedef T ElementType;
352  /// Default iterator for this class.
353  typedef T * Iter;
354  /// For compatibility with std::algorithms we provide also standard iterators.
355  /// theoreticaly it should work also with Iter. Test that if you need it.
358  /// Type of FullIterator that should be used to iterate through this container.
360 
361  /// Construct with reserve the space. Includes default constructor.
362  VectorId(unsigned int size = 0) : storage(0), id_storage(0)
363  {this->reserve(size);}
364 
365  /**
366  * Adds a new element into the container. Return iterator to it to set vales of the new element.
367  * This way we need not copy a new element. You are forced to set the id when adding a new element.
368  */
370  {
371  ASSERT( id_map.find(id) == id_map.end(), "Can not add item with id number %d since it already exists.", id);
372  id_storage.push_back(id);
373  id_map[id]=this->size();
374 
375  this->storage.resize( this->storage.size() + 1 );
376  return FullIter( *this, this->storage.begin() + this->storage.size() - 1 );
377  }
378 
379 
380  /**
381  * For given pointer returns the index of the element in the Vector. The first element has zero index.
382  */
383  inline unsigned int index(const T * pointer) const
384  {
385  ASSERT( pointer >= &(storage.front()) && pointer <= &(storage.back()),
386  "Wrong pointer %p to obtain its index (%p, %p).\n",pointer, &(storage.front()), &(storage.back()));
387  return ( pointer - &(storage.front()) );
388  }
389 
390  /// Returns FullFullIterer of the first element.
391  /// Do not try to set these as const methods. Such has to produce const iterators
392  /// which requires const anlaogy of FullIter - really ugly
393  inline FullIter begin()
394  { return FullIter( *this, storage.begin() ); }
395 
396  /// Returns FullFullIterer of the fictions past the end element.
397  inline FullIter end()
398  { return FullIter( *this, storage.end() ); }
399 
400  /// Returns size of the container. This is independent of the allocated space.
401  inline unsigned int size() const
402  { return storage.size(); }
403 
404  /// Gets reference to the element specified by index.
405  inline T & operator[](unsigned int idx)
406  {
407  ASSERT( idx < this->size(), "Index %d outside of Vector of size %d\n",idx, this->size());
408  return storage[idx];
409  }
410 
411 
412  /// Gets reference to the element specified by index.
413  inline const T & operator[](unsigned int idx) const
414  {
415  ASSERT( idx < this->size(), "Index %d outside of Vector of size %d\n",idx, this->size());
416  return storage[idx];
417  }
418 
419 
420  /// Gets iterator of the element specified by index.
421  inline FullIter operator()(unsigned int idx)
422  {
423  ASSERT( idx < this->size(), "Index %d outside of Vector of size %d\n",idx, this->size());
424  return FullIter( *this, begin()+idx );
425  }
426 
427  /// Gets iterator of the element specified by index.
428  inline const Iter operator()(unsigned int idx) const
429  {
430  ASSERT( idx < this->size(), "Index %d outside of Vector of size %d\n",idx, this->size());
431  return Iter( &(storage[idx]) );
432  }
433 
434 
435  /// Alternative way to make FullFullIterer form FullIterer. This way you need not write
436  /// the full FullFullIterer typename to call the constructor. Then the result can be assigned to
437  /// suitable local FullFullIterer variable.
439  { return FullIter(*this, it); }
440 
441  /**
442  * Returns FullIter of the element with given id. This is implemented by std::map which use balanced trees and ensure access in O(nlog n) time.
443  */
444  inline FullIter find_id(const int id)
445  {
446  map<int,unsigned int>::iterator iter = id_map.find(id);
447  if ( iter == id_map.end() ) {
448  return FullIter(*this, this->storage.end());
449  } else
450  return FullIter(*this, this->storage.begin() + iter->second);
451  }
452 
453  /**
454  * Returns FullIter of the element with given id. This is implemented by std::map which use balanced trees and ensure access in O(nlog n) time.
455  */
456  inline const T * find_id(const int id) const
457  {
459  if ( iter == id_map.end() ) {
460  return &(*(this->storage.end()));
461  } else
462  return &(*(this->storage.begin() + iter->second));
463  }
464 
465  /** Returns Id of the element given by pointer i.e. Iter. FullIter i.e. FullIteratorId<T>
466  * provides its own method for the same.
467  */
468  inline int get_id(const T * it) const
469  {
470  return *(id_storage.begin() + this->index(it));
471  }
472 
473  inline int get_id(int idx) const
474  {
475  return *(id_storage.begin() + idx);
476  }
477 
478  /// Reallocates the container space.
479  inline void reserve(unsigned int size)
480  {
481  ASSERT( size >= this->size(), "Vector can not be reallocated into space %d smaller then its size %d\n",size,this->size());
482  storage.reserve(size);
483  id_storage.reserve(size);
484  }
485 
486  /// Since storage is direct member it is deallocated by its own destructor.
487  virtual ~VectorId() {}
488 
489 
490 private:
491  /// Underlying vector container.
493 
494  std::vector<int> id_storage; ///< Space to save id numbers.
495  std::map<int, unsigned int> id_map; ///< Maps id numbers to indexes into storage vector.
496 
497  friend class FullIterator< VectorId<T> >;
498  friend class FullIteratorId<T>;
499 };
500 
501 
502 
503 // CLOSE NAME SPACE "flow"
504 }
505 
506 
507 #endif /* SYS_VECTOR_HH_ */
FullIter begin()
Returns FullFullIterer of the first element.
Definition: sys_vector.hh:257
VectorId(unsigned int size=0)
Construct with reserve the space. Includes default constructor.
Definition: sys_vector.hh:362
unsigned int size() const
Returns size of the container. This is independent of the allocated space.
Definition: sys_vector.hh:265
std::vector< T >::const_iterator const_iterator
Definition: sys_vector.hh:357
T ElementType
We have to export template type for FullIteraror.
Definition: sys_vector.hh:220
FullIter operator()(unsigned int idx)
Gets iterator of the element specified by index.
Definition: sys_vector.hh:289
const T * find_id(const int id) const
Definition: sys_vector.hh:456
std::vector< T > storage
Underlying vector container.
Definition: sys_vector.hh:314
int get_id(const T *it) const
Definition: sys_vector.hh:468
Envelop over std::vector, use enhanced iterators.
Definition: sys_vector.hh:216
int get_id(int idx) const
Definition: sys_vector.hh:473
FullIterator & operator+=(const int shift)
Definition: sys_vector.hh:118
Cont::iterator iter
Definition: sys_vector.hh:156
bool operator!=(const FullIterator &it) const
Definition: sys_vector.hh:128
Small extension of Vector&lt;T&gt; container with support to Id numbers.
Definition: sys_vector.hh:164
T ElementType
We have to export template type for FullIteraror.
Definition: sys_vector.hh:351
void resize(const unsigned int size)
Returns size of the container. This is independent of the allocated space.
Definition: sys_vector.hh:269
FullIter end()
Returns FullFullIterer of the fictions past the end element.
Definition: sys_vector.hh:261
unsigned int index(Iter pointer) const
Definition: sys_vector.hh:249
Cont & container()
Get reference to the container of the FullIterator.
Definition: sys_vector.hh:94
const Cont & cont
We have here reference to the container of the iterator. So, an instance of this class can not change...
Definition: sys_vector.hh:154
int index() const
Definition: sys_vector.hh:88
void reserve(unsigned int size)
Reallocates the container space.
Definition: sys_vector.hh:479
FullIter add_item(int id)
Definition: sys_vector.hh:369
std::vector< T >::const_iterator const_iterator
Definition: sys_vector.hh:226
FullIter find_id(const int id)
Definition: sys_vector.hh:444
FullIterator & operator++()
Prefix. Advance operator.
Definition: sys_vector.hh:132
virtual ~VectorId()
Since storage is direct member it is deallocated by its own destructor.
Definition: sys_vector.hh:487
FullIteratorId(const VectorId< T > &cont, typename std::vector< T >::iterator it)
Constructor. Just call base class.
Definition: sys_vector.hh:173
FullIter full_iter(Iter it)
Definition: sys_vector.hh:306
int id()
Returns id of the iterator. See VectorId documentation.
Definition: sys_vector.hh:179
T & operator[](unsigned int idx)
Gets reference to the element specified by index.
Definition: sys_vector.hh:274
unsigned int size() const
Returns size of the container. This is independent of the allocated space.
Definition: sys_vector.hh:401
T * Iter
Default iterator for this class.
Definition: sys_vector.hh:353
void reserve(unsigned int size)
Reallocates the container space.
Definition: sys_vector.hh:297
FullIteratorId(VectorId< T > &cont)
Constructor. Just call base class.
Definition: sys_vector.hh:170
Global macros to enhance readability and debugging, general constants.
FullIteratorId< T > FullIter
Type of FullIterator that should be used to iterate through this container.
Definition: sys_vector.hh:359
#define ASSERT(...)
Definition: global_defs.h:121
std::map< int, unsigned int > id_map
Maps id numbers to indexes into storage vector.
Definition: sys_vector.hh:495
Iterator that keeps also reference to its container. Safer and provides indexes.
Definition: sys_vector.hh:58
std::vector< T >::iterator iterator
Definition: sys_vector.hh:225
bool is_valid()
Check validity of FullIterator.
Definition: sys_vector.hh:81
FullIter operator()(unsigned int idx)
Gets iterator of the element specified by index.
Definition: sys_vector.hh:421
Vector(unsigned int size=0)
Construct with reserve the space. Includes default constructor.
Definition: sys_vector.hh:232
unsigned int index(const T *pointer) const
Definition: sys_vector.hh:383
Cont::ElementType & operator*() const
Definition: sys_vector.hh:111
FullIter begin()
Definition: sys_vector.hh:393
bool operator==(const FullIterator &it) const
Comparison of two FullIterator.
Definition: sys_vector.hh:125
std::vector< T > storage
Underlying vector container.
Definition: sys_vector.hh:492
FullIterator< Vector< T > > FullIter
Type of FullIterator that should be used to iterate through this container.
Definition: sys_vector.hh:228
FullIterator & operator--()
Prefix. Advance to previous operator.
Definition: sys_vector.hh:142
FullIterator(const Cont &cont_par, const typename Cont::iterator it)
Definition: sys_vector.hh:68
std::vector< int > id_storage
Space to save id numbers.
Definition: sys_vector.hh:494
FullIterator(Cont &cont_par, const typename Cont::Iter it)
Constructor to make FullIterator from container and Iter i.e. T*.
Definition: sys_vector.hh:73
FullIterator & operator=(const FullIterator &orig)
Assign operator. In debugging version check that containers of both FullIterator match.
Definition: sys_vector.hh:98
T & operator[](unsigned int idx)
Gets reference to the element specified by index.
Definition: sys_vector.hh:405
FullIter full_iter(Iter it)
Definition: sys_vector.hh:438
FullIterator(Cont &cont_par)
Constructor to make uninitialized FullIterator for a container.
Definition: sys_vector.hh:62
const Iter operator()(unsigned int idx) const
Gets iterator of the element specified by index.
Definition: sys_vector.hh:428
const T & operator[](unsigned int idx) const
Gets reference to the element specified by index.
Definition: sys_vector.hh:281
FullIter add_item()
Definition: sys_vector.hh:240
T * Iter
Default iterator for this class.
Definition: sys_vector.hh:222
Cont::ElementType * operator->() const
-&gt; dereference operator
Definition: sys_vector.hh:115
FullIteratorId(VectorId< T > &cont, const typename VectorId< T >::Iter it)
Constructor. Just call base class.
Definition: sys_vector.hh:176
virtual ~Vector()
Since storage is direct member it is deallocated by its own destructor.
Definition: sys_vector.hh:310
FullIterator & operator-=(const int shift)
Definition: sys_vector.hh:121
FullIter end()
Returns FullFullIterer of the fictions past the end element.
Definition: sys_vector.hh:397
std::vector< T >::iterator iterator
Definition: sys_vector.hh:356
const T & operator[](unsigned int idx) const
Gets reference to the element specified by index.
Definition: sys_vector.hh:413