Simpatico  v1.10
GArray.h
1 #ifndef UTIL_G_ARRAY_H
2 #define UTIL_G_ARRAY_H
3 
4 /*
5 * Util Package - C++ Utilities for Scientific Computation
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include <util/containers/ArrayIterator.h>
12 #include <util/containers/ConstArrayIterator.h>
13 #include <util/misc/Memory.h>
14 #include <util/global.h>
15 
16 namespace Util
17 {
18 
32  template <typename Data>
33  class GArray
34  {
35 
36  public:
37 
41  GArray();
42 
50  GArray(const GArray<Data>& other);
51 
57  GArray<Data>& operator = (const GArray<Data>& other);
58 
65  virtual ~GArray();
66 
76  void reserve(int capacity);
77 
83  void deallocate();
84 
91  void clear();
92 
99  template <class Archive>
100  void serialize(Archive& ar, const unsigned int version);
101 
107  void begin(ArrayIterator<Data> &iterator);
108 
114  void begin(ConstArrayIterator<Data> &iterator) const;
115 
123  void append(const Data& data);
124 
139  void resize(int n);
140 
147  Data& operator[] (int i);
148 
155  const Data& operator[] (int i) const;
156 
160  int capacity() const;
161 
165  int size() const;
166 
170  bool isAllocated() const;
171 
172  private:
173 
175  Data *data_;
176 
178  int size_;
179 
181  int capacity_;
182 
183  }; // class GArray
184 
185  // Method definitions
186 
187  /*
188  * Default constructor.
189  */
190  template <typename Data>
192  : data_(0),
193  size_(0),
194  capacity_(0)
195  {}
196 
197  /*
198  * Copy constructor, copies array elements.
199  *
200  * Allocates a new C-array and copies all elements.
201  */
202  template <typename Data>
204  : data_(0),
205  size_(0),
206  capacity_(0)
207  {
208  assert(other.size_ <= other.capacity_);
209  if (other.isAllocated()) {
210  assert(other.capacity_ > 0);
211  // Allocate new array
212  Memory::allocate<Data>(data_, other.capacity_);
213  capacity_ = other.capacity_;
214  // Copy objects
215  for (int i = 0; i < other.size_; ++i) {
216  data_[i] = other.data_[i];
217  ++size_;
218  }
219  }
220  }
221 
222  /*
223  * Destructor.
224  */
225  template <typename Data>
227  {
228  size_ = 0;
229  if (isAllocated()) {
230  Memory::deallocate<Data>(data_, capacity_);
231  capacity_ = 0;
232  }
233  }
234 
235  /*
236  * Assignment, element by element.
237  */
238  template <typename Data>
240  {
241  // Check for self assignment
242  if (this == &other) return *this;
243 
244  clear();
245  for (int i = 0; i < other.size_; ++i) {
246  append(other[i]);
247  }
248  return *this;
249  }
250 
251  /*
252  * Reserve space for the underlying array.
253  */
254  template <typename Data>
256  {
257  if (capacity <= 0) {
258  UTIL_THROW("Cannot reserve with capacity <=0");
259  }
260  if (!isAllocated()) {
261  assert(capacity_ == 0);
262  assert(size_ == 0);
263  Memory::allocate<Data>(data_, capacity);
264  capacity_ = capacity;
265  size_ = 0;
266  } else if (capacity > capacity_) {
267  assert(capacity_ > 0);
268  assert(capacity_ >= size_);
269  Data* newPtr = 0;
270  Memory::allocate<Data>(newPtr, capacity);
271  if (size_ > 0) {
272  for (int i = 0; i < size_; ++i) {
273  newPtr[i] = data_[i];
274  }
275  }
276  Memory::deallocate<Data>(data_, capacity_);
277  data_ = newPtr;
278  capacity_ = capacity;
279  }
280  }
281 
282  /*
283  * Delete associated C array.
284  */
285  template <typename Data>
287  {
288  size_ = 0;
289  if (isAllocated()) {
290  Memory::deallocate<Data>(data_, capacity_);
291  capacity_ = 0;
292  }
293  }
294 
295  /*
296  * Reset to empty state, without deallocating.
297  */
298  template <typename Data>
300  { size_ = 0; }
301 
302  /*
303  * Append an element to the end of the Array.
304  */
305  template <typename Data>
306  void GArray<Data>::append(const Data& data)
307  {
308  assert(size_ <= capacity_);
309  if (size_ == capacity_) {
310  if (capacity_ == 0) {
311  assert(data_ == 0);
312  Memory::allocate<Data>(data_, 64);
313  capacity_ = 64;
314  } else {
315  assert(data_);
316  assert(capacity_ > 0);
317  Data* newPtr = 0;
318  Memory::allocate<Data>(newPtr, 2*capacity_);
319  if (size_ > 0) {
320  for (int i = 0; i < size_; ++i) {
321  newPtr[i] = data_[i];
322  }
323  }
324  Memory::deallocate<Data>(data_, capacity_);
325  data_ = newPtr;
326  capacity_ = 2*capacity_;
327  }
328  }
329  // Append new element
330  data_[size_] = data;
331  ++size_;
332  assert(size_ <= capacity_);
333  }
334 
335  /*
336  * Resize the array.
337  */
338  template <typename Data>
339  void GArray<Data>::resize(int n)
340  {
341  if (n < 0) {
342  UTIL_THROW("Cannot resize to n < 0");
343  }
344  assert(capacity_ >= size_);
345  if (n > size_) {
346  if (n > capacity_) {
347  int m = capacity_;
348  if (m == 0) {
349  m = n;
350  } else {
351  while (n > m) {
352  m *= 2;
353  }
354  }
355  Data* newPtr = 0;
356  Memory::allocate<Data>(newPtr, m);
357  if (data_) {
358  assert(capacity_ > 0);
359  for (int i = 0; i < size_; ++i) {
360  newPtr[i] = data_[i];
361  }
362  Memory::deallocate<Data>(data_, capacity_);
363  }
364  data_ = newPtr;
365  capacity_ = m;
366  }
367  // Initialize added elements, using placement new
368  for (int i = size_; i < n; ++i) {
369  new(data_ + i) Data();
370  }
371  }
372  size_ = n;
373  }
374 
375  /*
376  * Serialize a GArray to/from an Archive.
377  */
378  template <class Data>
379  template <class Archive>
380  void GArray<Data>::serialize(Archive& ar, const unsigned int version)
381  {
382  int capacity;
383  int size;
384  if (Archive::is_saving()) {
385  capacity = capacity_;
386  size = size_;
387  }
388  ar & capacity;
389  ar & size;
390  if (Archive::is_loading()) {
391  size_ = 0;
392  reserve(capacity);
393  size_ = size;
394  }
395  for (int i = 0; i < size_; ++i) {
396  ar & data_[i];
397  }
398  }
399 
400  /*
401  * Set an ArrayIterator to the beginning of this Array.
402  */
403  template <class Data>
404  inline
406  {
407  iterator.setCurrent(data_);
408  iterator.setEnd(data_ + size_);
409  }
410 
411  /*
412  * Set a ConstArrayIterator to the beginning of this Array.
413  */
414  template <class Data>
415  inline
417  {
418  iterator.setCurrent(data_);
419  iterator.setEnd(data_ + size_);
420  }
421 
422  /*
423  * Mimic C array subscripting.
424  */
425  template <class Data>
426  inline Data& GArray<Data>::operator[] (int i)
427  {
428  assert(i >= 0);
429  assert(i < size_);
430  return data_[i];
431  }
432 
433  /*
434  * Mimic C array subscripting.
435  */
436  template <class Data>
437  inline const Data& GArray<Data>::operator[] (int i) const
438  {
439  assert(i >= 0);
440  assert(i < size_);
441  return data_[i];
442  }
443 
444  /*
445  * Return physical capacity of array.
446  */
447  template <class Data>
448  inline int GArray<Data>::capacity() const
449  { return capacity_; }
450 
451  /*
452  * Return logical size of this array (i.e., number of elements).
453  */
454  template <class Data>
455  inline int GArray<Data>::size() const
456  { return size_; }
457 
458  /*
459  * Is this array allocated?
460  */
461  template <class Data>
462  inline bool GArray<Data>::isAllocated() const
463  { return (bool)data_; }
464 
465 }
466 #endif
int capacity() const
Return physical capacity of array.
Definition: GArray.h:448
An automatically growable array, analogous to a std::vector.
Definition: GArray.h:33
GArray()
Constructor.
Definition: GArray.h:191
void append(const Data &data)
Append an element to the end of the sequence.
Definition: GArray.h:306
void clear()
Reset to empty state.
Definition: GArray.h:299
void reserve(int capacity)
Reserve memory for specified number of elements.
Definition: GArray.h:255
void setCurrent(Data *ptr)
Set the current pointer value.
Definition: ArrayIterator.h:59
int size() const
Return logical size of this array (i.e., current number of elements).
Definition: GArray.h:455
void deallocate()
Deallocate (delete) underlying array of pointers.
Definition: GArray.h:286
File containing preprocessor macros for error handling.
Forward const iterator for an Array or a C array.
void setEnd(Data *ptr)
Set the value of the end pointer.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
void begin(ArrayIterator< Data > &iterator)
Set an ArrayIterator to the beginning of this Array.
Definition: GArray.h:405
bool isAllocated() const
Is this array allocated?
Definition: GArray.h:462
Utility classes for scientific computation.
Definition: accumulators.mod:1
virtual ~GArray()
Destructor.
Definition: GArray.h:226
Forward iterator for an Array or a C array.
Definition: ArrayIterator.h:39
Data & operator[](int i)
Mimic C array subscripting.
Definition: GArray.h:426
void setEnd(Data *ptr)
Set the value of the end pointer.
Definition: ArrayIterator.h:67
void setCurrent(Data *ptr)
Set the current pointer value.
void serialize(Archive &ar, const unsigned int version)
Serialize a GArray to/from an Archive.
Definition: GArray.h:380
void resize(int n)
Resizes array so that it contains n elements.
Definition: GArray.h:339
GArray< Data > & operator=(const GArray< Data > &other)
Assignment, element by element.
Definition: GArray.h:239