PSCF v1.1
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
16namespace Util
17{
18
32 template <typename Data>
33 class GArray
34 {
35
36 public:
37
42
50 GArray(GArray<Data> const & other);
51
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(Data const & data);
124
139 void resize(int n);
140
147 Data& operator[] (int i);
148
155 Data const & 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>
255 void GArray<Data>::reserve(int capacity)
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(Data const & 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>
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 Data const & 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
Forward iterator for an Array or a C array.
Definition: ArrayIterator.h:37
void setEnd(Data *ptr)
Set the value of the end pointer.
Definition: ArrayIterator.h:64
void setCurrent(Data *ptr)
Set the current pointer value.
Definition: ArrayIterator.h:56
Forward const iterator for an Array or a C array.
void setEnd(Data *ptr)
Set the value of the end pointer.
void setCurrent(Data *ptr)
Set the current pointer value.
An automatically growable array, analogous to a std::vector.
Definition: GArray.h:34
virtual ~GArray()
Destructor.
Definition: GArray.h:226
GArray()
Constructor.
Definition: GArray.h:191
GArray(GArray< Data > const &other)
Copy constructor, copy pointers.
Definition: GArray.h:203
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
Data & operator[](int i)
Mimic C array subscripting.
Definition: GArray.h:426
int size() const
Return logical size of this array (i.e., current number of elements).
Definition: GArray.h:455
bool isAllocated() const
Is this array allocated?
Definition: GArray.h:462
void deallocate()
Deallocate (delete) underlying array of pointers.
Definition: GArray.h:286
int capacity() const
Return physical capacity of array.
Definition: GArray.h:448
void reserve(int capacity)
Reserve memory for specified number of elements.
Definition: GArray.h:255
void begin(ArrayIterator< Data > &iterator)
Set an ArrayIterator to the beginning of this Array.
Definition: GArray.h:405
GArray< Data > & operator=(GArray< Data > const &other)
Assignment, element by element.
Definition: GArray.h:239
void clear()
Reset to empty state.
Definition: GArray.h:299
void begin(ConstArrayIterator< Data > &iterator) const
Set a ConstArrayIterator to the beginning of this Array.
Definition: GArray.h:416
void append(Data const &data)
Append an element to the end of the sequence.
Definition: GArray.h:306
File containing preprocessor macros for error handling.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
Utility classes for scientific computation.
Definition: accumulators.mod:1