NeoPZ
pzmanvector.h
Go to the documentation of this file.
1 
5 #ifndef PZMANVECTOR_H
6 #define PZMANVECTOR_H
7 
8 #include "pzvec.h"
9 #include "pzerror.h"
10 
13 const int DEFAULTVEC_ALLOC = 10;
14 
29 template < class T, int NumExtAlloc = DEFAULTVEC_ALLOC >
30 class TPZManVector : public TPZVec< T > {
31 public:
39  TPZManVector(const int64_t size = 0);
40 
50  TPZManVector(const int64_t size, const T& copy);
51 
58 
59  TPZManVector(const TPZVec<T> & copy);
60 
65  TPZManVector(const std::initializer_list<T>& list);
66 
79 
85  TPZManVector< T, NumExtAlloc >& operator=(const std::initializer_list<T>& list);
86 
89  virtual ~TPZManVector();
90 
92  inline int NAlloc() const {
93  return fNAlloc;
94  }
95 
101  void Expand(const int64_t newsize);
102 
104  void Shrink();
105 
116  virtual void Resize(const int64_t newsize, const T& object);
117 
127  virtual void Resize(const int64_t newsize);
128 
129 private:
130 
140  int64_t ExpandSize(const int64_t proposed) const;
141 
143  int fNAlloc;
144 
146  T fExtAlloc[ NumExtAlloc ];
147 };
148 
149 //--| IMPLEMENTATION |----------------------------------------------------------
150 
151 template< class T, int NumExtAlloc >
153 TPZVec<T>(0) // There is always some static allocation.
154 {
155  /* If the size requested fits inside the size already provided
156  * statically, provides access to that space, by setting some
157  * TPZVec data.
158  */
159  if (size <= NumExtAlloc) {
160  // Needed to make TPZVec::operator[] work properly.
161  this->fStore = fExtAlloc;
162  this->fNElements = size;
163  // No memory was allocated by the constructor.
164  fNAlloc = 0;
165  } else // The size requested is bigger than the size already provided.
166  {
167  // Executes the allocation that would be done by TPZVec<T>(size).
168  this->fStore = new T[ size ];
169  this->fNElements = size;
170  fNAlloc = size;
171  }
172 }
173 
174 template< class T, int NumExtAlloc >
175 TPZManVector< T, NumExtAlloc >::TPZManVector(const int64_t size, const T& copy) :
176 TPZVec<T>(0)
177 //fNExtAlloc( NumExtAlloc ) // There is always some static allocation.
178 {
179  /* If the size requested fits inside the size already provided
180  * statically, provides access to that space, by setting some
181  * TPZVec data.
182  */
183  if (size <= NumExtAlloc) {
184  // Needed to make TPZVec::operator[] work properly.
185  this->fStore = fExtAlloc;
186  this->fNElements = size;
187  // No memory was allocated by the constructor.
188  fNAlloc = 0;
189  } else // The size requested is bigger than the size already provided.
190  {
191  // Executes the allocation that would be done by TPZVec<T>(size).
192  this->fStore = new T[ size ];
193  this->fNElements = size;
194  fNAlloc = size;
195  }
196 
197  for (int64_t i = 0; i < size; i++) {
198  this->fStore[i] = copy;
199  }
200 }
201 
202 template< class T, int NumExtAlloc>
204  const int64_t size = copy.NElements();
205 
206  /* If the size requested fits inside the size already provided
207  * statically, provides access to that space, by setting some
208  * TPZVec data.
209  */
210  if (size <= (int64_t) (sizeof (fExtAlloc) / sizeof (T))) {
211  // Needed to make TPZVec::operator[] work properly.
212  this->fStore = fExtAlloc;
213  this->fNElements = size;
214  // No memory was allocated by the constructor.
215  fNAlloc = 0;
216  } else // The size requested is bigger than the size already provided.
217  {
218  // Executes the allocation that would be done by TPZVec<T>(size).
219  this->fStore = new T[ size ];
220  this->fNElements = size;
221  fNAlloc = size;
222  }
223 
224  for (int64_t i = 0; i < size; i++) {
225  this->fStore[i] = copy.fStore[i];
226  }
227 }
228 
229 template< class T, int NumExtAlloc>
231  const TPZVec<T> & copy) {
232  const int64_t size = copy.NElements();
233 
234  /* If the size requested fits inside the size already provided
235  * statically, provides access to that space, by setting some
236  * TPZVec data.
237  */
238  if (size <= (int64_t) (sizeof (fExtAlloc) / sizeof (T))) {
239  // Needed to make TPZVec::operator[] work properly.
240  this->fStore = fExtAlloc;
241  this->fNElements = size;
242  // No memory was allocated by the constructor.
243  fNAlloc = 0;
244  } else // The size requested is bigger than the size already provided.
245  {
246  // Executes the allocation that would be done by TPZVec<T>(size).
247  this->fStore = new T[ size ];
248  this->fNElements = size;
249  fNAlloc = size;
250  }
251 
252  for (int64_t i = 0; i < size; i++) {
253  this->fStore[i] = copy[i];
254  }
255 }
256 
257 template< class T, int NumExtAlloc>
258 inline TPZManVector< T, NumExtAlloc >::TPZManVector(const std::initializer_list<T>& list)
259 {
260  int size = list.size();
261  std::cout << "init pzmanvec" << std::endl;
262  if (size <= (int64_t)(sizeof(fExtAlloc) / sizeof(T))) {
263  // Needed to make TPZVec::operator[] work properly.
264  this->fStore = fExtAlloc;
265  this->fNElements = size;
266  // No memory was allocated by the constructor.
267  fNAlloc = 0;
268  }
269  else // The size requested is bigger than the size already provided.
270  {
271  // Executes the allocation that would be done by TPZVec<T>(size).
272  this->fStore = new T[size];
273  this->fNElements = size;
274  fNAlloc = size;
275  }
276 
277  auto it_end = list.end();
278  T* aux = this->fStore;
279  for (auto it = list.begin(); it != it_end; it++, aux++)
280  *aux = *it;
281 }
282 
283 
284 template< class T, int NumExtAlloc >
286  // Checking auto assignment.
287  if (this == &copy) {
288  return *this;
289  }
290 
291  const int64_t nel = copy.NElements();
292 
293  if (nel > fNAlloc && this->fStore && this->fStore != fExtAlloc) {
294  delete [] this->fStore;
295  this->fStore = 0;
296  fNAlloc = 0;
297  }
298 
299  if (nel <= NumExtAlloc) {
300  if (this->fStore != fExtAlloc) {
301  delete []this->fStore;
302  }
303  this->fNAlloc = 0;
304  this->fStore = fExtAlloc;
305  this->fNElements = nel;
306  } else if (fNAlloc >= nel) {
307  this->fNElements = nel;
308  } else {
309  this->fStore = new T[ nel ];
310  fNAlloc = nel;
311  this->fNElements = nel;
312  }
313 
314  for (int64_t i = 0; i < nel; i++) {
315  this->fStore[i] = copy.fStore[i];
316  }
317 
318  return *this;
319 }
320 
321 template< class T, int NumExtAlloc >
323  size_t size = list.size();
324 
325  if (size > this->fNAlloc && this->fStore && this->fStore != this->fExtAlloc) {
326  delete[] this->fStore;
327  this->fStore = 0;
328  this->fNAlloc = 0;
329  }
330 
331  if (size <= NumExtAlloc) {
332  if (this->fStore != fExtAlloc) {
333  delete[]this->fStore;
334  }
335  this->fNAlloc = 0;
336  this->fStore = fExtAlloc;
337  this->fNElements = size;
338  }
339  else if (fNAlloc >= size) {
340  this->fNElements = size;
341  }
342  else {
343  this->fStore = new T[size];
344  fNAlloc = size;
345  this->fNElements = size;
346  }
347 
348  auto it_end = list.end();
349  T* aux = this->fStore;
350  for (auto it = list.begin(); it != it_end; it++, aux++)
351  *aux = *it;
352 
353  return *this;
354 }
355 
356 template< class T, int NumExtAlloc >
358  if (this->fStore == fExtAlloc) {
359  this->fStore = 0;
360  }
361 
362  // fNExtAlloc = 0;
363  fNAlloc = 0;
364 }
365 
366 template< class T, int NumExtAlloc >
367 void TPZManVector< T, NumExtAlloc >::Expand(const int64_t newsize) {
368  // If newsize is negative then return.
369  if (newsize <= fNAlloc || newsize <= NumExtAlloc) {
370  return;
371  } else {// the size is larger than the allocated memory
372  T* newstore = new T[ newsize ];
373 
374  for (int64_t i = 0L; i < this->fNElements; i++) {
375  newstore[i] = this->fStore[i];
376  }
377 
378  if (this->fStore != fExtAlloc) {
379  delete [] this->fStore;
380  }
381 
382  this->fStore = newstore;
383  fNAlloc = newsize;
384  }
385 }
386 
387 template< class T, int NumExtAlloc >
389  // Philippe : Porque NumExtAlloc <= fNAlloc????
390  // if(this->fNElements <= NumExtAlloc && NumExtAlloc <= fNAlloc) {
391  if (this->fNElements <= NumExtAlloc) {
392  if (this->fStore != fExtAlloc) {
393  for (int64_t i = 0; i < this->fNElements; i++)
394  fExtAlloc[i] = this->fStore[i];
395 
396  if (this->fStore)
397  delete [] this->fStore;
398 
399  this->fStore = fExtAlloc;
400  fNAlloc = NumExtAlloc;
401  }
402  } else if (fNAlloc != this->fNElements) { // then fExtAlloc != this->fStore because NumExtAlloc != fNAlloc
403  // Philippe : Memoria alocada externamente nao pode ser deletada
404  // if(fExtAlloc) delete[] fExtAlloc;
405  T *newstore = 0;
406 
407  if (this->fNElements)
408  newstore = new T[this->fNElements];
409 
410  for (int64_t i = 0; i < this->fNElements; i++)
411  newstore[i] = this->fStore[i];
412 
413  if (this->fStore)
414  delete[]this->fStore;
415 
416  this->fStore = newstore;
417  fNAlloc = this->fNElements;
418 
419  // Philippe Isto eh um absurdo
420  // fExtAlloc = this->fStore;
421  // NumExtAlloc = fNAlloc;
422  }
423 }
424 
425 template< class T, int NumExtAlloc >
426 void TPZManVector< T, NumExtAlloc >::Resize(const int64_t newsize, const T& object) {
427 #ifndef NODEBUG
428  if (newsize < 0) {
429  PZError << "TManVec::Resize. Bad parameter newsize." << std::endl;
430  PZError.flush();
431  return;
432  }
433  if (newsize == this->fNElements)
434  return;
435 #endif
436 
437  if (newsize <= fNAlloc) {
438  for (int64_t i = this->fNElements; i < newsize; i++)
439  this->fStore[i] = object;
440 
441  this->fNElements = newsize;
442  } else if (newsize <= NumExtAlloc) { // that is, fExtAlloc != this->fStore. Moreover : this->fNElements <= fNAlloc
443  // <= NumExtAlloc
444 
445  int64_t i;
446 
447  for (i = 0L; i < this->fNElements; i++) {
448  fExtAlloc[i] = this->fStore[i];
449  }
450 
451  for (; i < newsize; i++)
452  fExtAlloc[i] = object;
453 
454  if (this->fStore != fExtAlloc) delete [] this->fStore;
455 
456  this->fStore = fExtAlloc;
457  this->fNElements = newsize;
458  fNAlloc = NumExtAlloc;
459  } else { // the size is larger than the allocated memory, then this->fNElements
460  // is always lower than newsize because fNElemets <=fNAllocs
461  int64_t i, realsize = ExpandSize(newsize);
462 
463  T* newstore = new T[realsize];
464 
465  for (i = 0L; i < this->fNElements; i++) {
466  newstore[i] = this->fStore[i];
467  }
468 
469  for (; i < newsize; i++)
470  newstore[i] = object;
471 
472  if (this->fStore != fExtAlloc)
473  delete[]this->fStore;
474 
475  this->fStore = newstore;
476  this->fNElements = newsize;
477  fNAlloc = realsize;
478  }
479 }
480 
481 template< class T, int NumExtAlloc >
482 void TPZManVector< T, NumExtAlloc >::Resize(const int64_t newsize) {
483 #ifndef NODEBUG
484  if (newsize < 0) {
485  PZError << "TManVec::Resize. Bad parameter newsize." << std::endl;
486  PZError.flush();
487  return;
488  }
489 #endif
490 
491  if (newsize == this->fNElements)
492  return;
493 
494  if (newsize <= fNAlloc) {
495  this->fNElements = newsize;
496  } else if (newsize <= NumExtAlloc) { // that is, fExtAlloc != this->fStore
497  if (this->fStore != fExtAlloc) {
498  for (int64_t i = 0L; i < this->fNElements; i++) {
499  fExtAlloc[i] = this->fStore[i];
500  }
501  delete [] this->fStore;
502  this->fStore = fExtAlloc;
503  }
504 
505  this->fNElements = newsize;
506  fNAlloc = NumExtAlloc;
507  } else { // the size is larger than the allocated memory, then this->fNElements
508  // is always lower than newsize because fNElemets <=fNAllocs
509 
510  int64_t realsize = ExpandSize(newsize);
511  T *newstore = new T[realsize];
512 
513  for (int64_t i = 0L; i < this->fNElements; i++) {
514  newstore[i] = this->fStore[i];
515  }
516 
517  if (this->fStore != fExtAlloc)
518  delete [] this->fStore;
519 
520  this->fStore = newstore;
521  this->fNElements = newsize;
522  fNAlloc = realsize;
523  }
524 }
525 
526 template< class T, int NumExtAlloc >
527 int64_t TPZManVector < T, NumExtAlloc >::ExpandSize(const int64_t proposed) const {
528  return ( proposed > fNAlloc * 1.2 ? proposed :
529  static_cast<int64_t> (fNAlloc * 1.2));
530 }
531 
532 #endif
T fExtAlloc[NumExtAlloc]
Pointer to the externally allocated space.
Definition: pzmanvector.h:146
TPZManVector(const int64_t size=0)
Creates a vector of a given size.
Definition: pzmanvector.h:152
Implements a vector class which allows to use external storage provided by the user. Utility.
Definition: pzquad.h:16
int fNAlloc
Number of elements allocated for this object.
Definition: pzmanvector.h:143
Templated vector implementation.
Defines PZError.
This class implements a simple vector storage scheme for a templated class T. Utility.
Definition: pzgeopoint.h:19
int NAlloc() const
Returns number of elements allocated for this object.
Definition: pzmanvector.h:92
void Expand(const int64_t newsize)
Expands the allocated storage to fit the newsize parameter.
Definition: pzmanvector.h:367
virtual void Resize(const int64_t newsize, const T &object)
Resizes the vector object.
Definition: pzmanvector.h:426
virtual ~TPZManVector()
Destructor.
Definition: pzmanvector.h:357
int64_t size() const
Returns the number of elements of the vector.
Definition: pzvec.h:196
void Shrink()
It reallocates storage to fit the necessary storage exactly.
Definition: pzmanvector.h:388
int64_t ExpandSize(const int64_t proposed) const
Returns a suggested size for expanding the storage to fit the required storage.
Definition: pzmanvector.h:527
T * fStore
Allocated storage for the vector object.
Definition: pzvec.h:230
const int DEFAULTVEC_ALLOC
To allocate vector by default.
Definition: pzmanvector.h:13
int64_t fNElements
Number of elements of the vector object.
Definition: pzvec.h:233
int64_t NElements() const
Returns the number of elements of the vector.
Definition: pzvec.h:190
TPZManVector< T, NumExtAlloc > & operator=(const TPZManVector< T, NumExtAlloc > &copy)
Assignment operator.
Definition: pzmanvector.h:285
#define PZError
Defines the output device to error messages and the DebugStop() function.
Definition: pzerror.h:15