PSCF v1.4.0
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
62 virtual ~GArray();
63
73 void reserve(int capacity);
74
80 void deallocate();
81
88 void clear();
89
96 template <class Archive>
97 void serialize(Archive& ar, const unsigned int version);
98
104 void begin(ArrayIterator<Data> &iterator);
105
111 void begin(ConstArrayIterator<Data> &iterator) const;
112
120 void append(Data const & data);
121
136 void resize(int n);
137
144 Data& operator[] (int i);
145
152 Data const & operator[] (int i) const;
153
157 int capacity() const;
158
162 int size() const;
163
167 bool isAllocated() const;
168
169 private:
170
172 Data *data_;
173
175 int size_;
176
178 int capacity_;
179
180 }; // class GArray
181
182 // Method definitions
183
184 /*
185 * Default constructor.
186 */
187 template <typename Data>
189 : data_(nullptr),
190 size_(0),
191 capacity_(0)
192 {}
193
194 /*
195 * Copy constructor, copies array elements.
196 *
197 * Allocates a new C-array and copies all elements.
198 */
199 template <typename Data>
201 : data_(nullptr),
202 size_(0),
203 capacity_(0)
204 {
205 assert(other.size_ <= other.capacity_);
206 if (other.isAllocated()) {
207 assert(other.capacity_ > 0);
208 // Allocate new array
209 Memory::allocate<Data>(data_, other.capacity_);
210 capacity_ = other.capacity_;
211 // Copy objects
212 for (int i = 0; i < other.size_; ++i) {
213 data_[i] = other.data_[i];
214 ++size_;
215 }
216 }
217 }
218
219 /*
220 * Destructor.
221 */
222 template <typename Data>
224 {
225 size_ = 0;
226 if (isAllocated()) {
227 Memory::deallocate<Data>(data_, capacity_);
228 capacity_ = 0;
229 }
230 }
231
232 /*
233 * Assignment, element by element.
234 */
235 template <typename Data>
237 {
238 // Check for self assignment
239 if (this == &other) return *this;
240
241 clear();
242 for (int i = 0; i < other.size_; ++i) {
243 append(other[i]);
244 }
245 return *this;
246 }
247
248 /*
249 * Reserve space for the underlying array.
250 */
251 template <typename Data>
253 {
254 if (capacity <= 0) {
255 UTIL_THROW("Cannot reserve with capacity <=0");
256 }
257 if (!isAllocated()) {
258 assert(capacity_ == 0);
259 assert(size_ == 0);
261 capacity_ = capacity;
262 size_ = 0;
263 } else if (capacity > capacity_) {
264 assert(capacity_ > 0);
265 assert(capacity_ >= size_);
266 Data* newPtr = nullptr;
268 if (size_ > 0) {
269 for (int i = 0; i < size_; ++i) {
270 newPtr[i] = data_[i];
271 }
272 }
273 Memory::deallocate<Data>(data_, capacity_);
274 data_ = newPtr;
275 capacity_ = capacity;
276 }
277 }
278
279 /*
280 * Delete associated C array.
281 */
282 template <typename Data>
284 {
285 size_ = 0;
286 if (isAllocated()) {
287 Memory::deallocate<Data>(data_, capacity_);
288 capacity_ = 0;
289 }
290 }
291
292 /*
293 * Reset to empty state, without deallocating.
294 */
295 template <typename Data>
297 { size_ = 0; }
298
299 /*
300 * Append an element to the end of the Array.
301 */
302 template <typename Data>
303 void GArray<Data>::append(Data const & data)
304 {
305 assert(size_ <= capacity_);
306 if (size_ == capacity_) {
307 if (capacity_ == 0) {
308 UTIL_CHECK(!data_);
309 Memory::allocate<Data>(data_, 64);
310 capacity_ = 64;
311 } else {
312 assert(data_);
313 assert(capacity_ > 0);
314 Data* newPtr = nullptr;
315 Memory::allocate<Data>(newPtr, 2*capacity_);
316 if (size_ > 0) {
317 for (int i = 0; i < size_; ++i) {
318 newPtr[i] = data_[i];
319 }
320 }
321 Memory::deallocate<Data>(data_, capacity_);
322 data_ = newPtr;
323 capacity_ = 2*capacity_;
324 }
325 }
326 // Append new element
327 data_[size_] = data;
328 ++size_;
329 assert(size_ <= capacity_);
330 }
331
332 /*
333 * Resize the array.
334 */
335 template <typename Data>
337 {
338 UTIL_CHECK(n > 0);
339 UTIL_CHECK(capacity_ >= size_);
340 if (n > size_) {
341 if (n > capacity_) {
342 int m = capacity_;
343 if (m == 0) {
344 m = n;
345 } else {
346 while (n > m) {
347 m *= 2;
348 }
349 }
350 Data* newPtr = nullptr;
351 Memory::allocate<Data>(newPtr, m);
352 if (data_) {
353 assert(capacity_ > 0);
354 for (int i = 0; i < size_; ++i) {
355 newPtr[i] = data_[i];
356 }
357 Memory::deallocate<Data>(data_, capacity_);
358 }
359 data_ = newPtr;
360 capacity_ = m;
361 }
362 // Initialize added elements, using placement new
363 for (int i = size_; i < n; ++i) {
364 new(data_ + i) Data();
365 }
366 }
367 size_ = n;
368 }
369
370 /*
371 * Serialize a GArray to/from an Archive.
372 */
373 template <typename Data>
374 template <class Archive>
375 void GArray<Data>::serialize(Archive& ar, const unsigned int version)
376 {
377 int capacity;
378 int size;
379 if (Archive::is_saving()) {
380 capacity = capacity_;
381 size = size_;
382 }
383 ar & capacity;
384 ar & size;
385 if (Archive::is_loading()) {
386 size_ = 0;
388 size_ = size;
389 }
390 for (int i = 0; i < size_; ++i) {
391 ar & data_[i];
392 }
393 }
394
395 /*
396 * Set an ArrayIterator to the beginning of this Array.
397 */
398 template <typename Data>
399 inline
401 {
402 iterator.setCurrent(data_);
403 iterator.setEnd(data_ + size_);
404 }
405
406 /*
407 * Set a ConstArrayIterator to the beginning of this Array.
408 */
409 template <typename Data>
410 inline
412 {
413 iterator.setCurrent(data_);
414 iterator.setEnd(data_ + size_);
415 }
416
417 /*
418 * Mimic C array subscripting.
419 */
420 template <typename Data>
421 inline Data& GArray<Data>::operator[] (int i)
422 {
423 assert(i >= 0);
424 assert(i < size_);
425 return data_[i];
426 }
427
428 /*
429 * Mimic C array subscripting.
430 */
431 template <typename Data>
432 inline Data const & GArray<Data>::operator[] (int i) const
433 {
434 assert(i >= 0);
435 assert(i < size_);
436 return data_[i];
437 }
438
439 /*
440 * Return physical capacity of array.
441 */
442 template <typename Data>
443 inline int GArray<Data>::capacity() const
444 { return capacity_; }
445
446 /*
447 * Return logical size of this array (i.e., number of elements).
448 */
449 template <typename Data>
450 inline int GArray<Data>::size() const
451 { return size_; }
452
453 /*
454 * Is this array allocated?
455 */
456 template <typename Data>
457 inline bool GArray<Data>::isAllocated() const
458 { return (bool)data_; }
459
460}
461#endif
Forward 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.
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.
virtual ~GArray()
Destructor.
Definition GArray.h:223
GArray()
Constructor.
Definition GArray.h:188
void serialize(Archive &ar, const unsigned int version)
Serialize a GArray to/from an Archive.
Definition GArray.h:375
void resize(int n)
Resizes array so that it contains n elements.
Definition GArray.h:336
Data & operator[](int i)
Mimic C array subscripting.
Definition GArray.h:421
int size() const
Return logical size of this array (i.e., current number of elements).
Definition GArray.h:450
bool isAllocated() const
Is this array allocated?
Definition GArray.h:457
void deallocate()
Deallocate (delete) underlying array of pointers.
Definition GArray.h:283
void reserve(int capacity)
Reserve memory for specified number of elements.
Definition GArray.h:252
void begin(ArrayIterator< Data > &iterator)
Set an ArrayIterator to the beginning of this Array.
Definition GArray.h:400
GArray< Data > & operator=(GArray< Data > const &other)
Assignment, element by element.
Definition GArray.h:236
void clear()
Reset to empty state.
Definition GArray.h:296
void append(Data const &data)
Append an element to the end of the sequence.
Definition GArray.h:303
static void deallocate(Data *&ptr, size_t size)
Deallocate a C++ array.
Definition Memory.h:157
static void allocate(Data *&ptr, size_t size)
Allocate a C++ array.
Definition Memory.h:136
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
Utility classes for scientific computation.