PSCF v1.1
DSArray.h
1#ifndef UTIL_DS_ARRAY_H
2#define UTIL_DS_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
29 template <typename Data>
30 class DSArray
31 {
32
33 public:
34
38 DSArray();
39
45 DSArray(DSArray< Data > const & other);
46
55
59 virtual ~DSArray();
60
69 void allocate(int capacity);
70
76 void append(Data const & data);
77
90 void resize(int size);
91
95 void clear();
96
103 template <class Archive>
104 void serialize(Archive& ar, const unsigned int version);
105
111 void begin(ArrayIterator<Data> &iterator);
112
118 void begin(ConstArrayIterator<Data> &iterator) const;
119
126 Data& operator[] (int i);
127
134 Data const & operator[] (int i) const;
135
139 int capacity() const;
140
144 int size() const;
145
149 bool isAllocated() const;
150
151 protected:
152
154 Data *data_;
155
157 int size_;
158
161
162 };
163
164 // Method definitions
165
166 /*
167 * Constructor.
168 */
169 template <class Data>
171 : data_(0),
172 size_(0),
173 capacity_(0)
174 {}
175
176 /*
177 * Copy constructor.
178 */
179 template <class Data>
181 : data_(0),
182 size_(0),
183 capacity_(0)
184 {
185 // Precondition
186 if (!other.isAllocated()) {
187 UTIL_THROW("Other DSArray must be allocated.");
188 }
189
190 Memory::allocate<Data>(data_, other.capacity_);
191 capacity_ = other.capacity_;
192 size_ = other.size_;
193 for (int i = 0; i < size_; ++i) {
194 data_[i] = other.data_[i];
195 }
196 }
197
198 /*
199 * Assignment, element by element.
200 *
201 * Capacity of LHS DSArray must be zero or == capacity of RHS DSArray.
202 */
203 template <class Data>
205 {
206 // Check for self assignment
207 if (this == &other) return *this;
208
209 // Precondition
210 if (!other.isAllocated()) {
211 UTIL_THROW("Other DSArray must be allocated.");
212 }
213
214 if (!isAllocated()) {
215 allocate(other.capacity_);
216 } else if (capacity_ != other.capacity_) {
217 UTIL_THROW("Cannot assign DSArrays of unequal capacity");
218 }
219
220 // Copy elements and set size
221 for (int i = 0; i < other.size_; ++i) {
222 data_[i] = other[i];
223 }
224 size_ = other.size_;
225
226 return *this;
227 }
228
229 /*
230 * Destructor.
231 */
232 template <class Data>
234 {
235 size_ = 0;
236 if (isAllocated()) {
237 assert(capacity_);
238 Memory::deallocate<Data>(data_, capacity_);
239 capacity_ = 0;
240 }
241 }
242
243 /*
244 * Allocates the underlying C array.
245 */
246 template <class Data>
247 void DSArray<Data>::allocate(int capacity)
248 {
249 if (isAllocated()) {
250 UTIL_THROW("Cannot re-allocate a DSArray");
251 }
252 if (capacity <= 0) {
253 UTIL_THROW("Cannot allocate a DSArray with capacity <= 0");
254 }
255 Memory::allocate<Data>(data_, capacity);
256 capacity_ = capacity;
257 size_ = 0;
258 }
259
260 /*
261 * Serialize a DSArray to/from an Archive.
262 */
263 template <class Data>
264 template <class Archive>
265 void DSArray<Data>::serialize(Archive& ar, const unsigned int version)
266 {
267 int capacity;
268 if (Archive::is_saving()) {
269 if (!isAllocated()) {
270 UTIL_THROW("Cannot save unallocated DSArray");
271 }
272 capacity = capacity_;
273 }
274 ar & capacity;
275 ar & size_;
276 if (Archive::is_loading()) {
277 if (capacity <= 0) {
278 UTIL_THROW("Invalid DSArray input capacity on load, capacity <= 0");
279 }
280 if (size_ < 0) {
281 UTIL_THROW("Invalid DSArray input size on load, size < 0");
282 }
283 if (!isAllocated()) {
284 allocate(capacity);
285 }
286 if (size_ > capacity_) {
287 UTIL_THROW("Inconsistent DSArray size and capacity on load");
288 }
289 }
290 for (int i = 0; i < size_; ++i) {
291 ar & data_[i];
292 }
293 }
294
300 template <class Data>
301 inline
303 {
304 iterator.setCurrent(data_);
305 iterator.setEnd(data_ + size_);
306 }
307
308 /*
309 * Set a ConstArrayIterator to the beginning of this Array.
310 */
311 template <class Data>
312 inline
314 {
315 iterator.setCurrent(data_);
316 iterator.setEnd(data_ + size_);
317 }
318
319 /*
320 * Mimic C array subscripting.
321 */
322 template <class Data>
323 inline Data& DSArray<Data>::operator[] (int i)
324 {
325 assert(i < size_);
326 assert(i >= 0);
327 return data_[i];
328 }
329
330 /*
331 * Mimic C array subscripting.
332 */
333 template <class Data>
334 inline Data const & DSArray<Data>::operator[] (int i) const
335 {
336 assert(i < size_);
337 assert(i >= 0 );
338 return data_[i];
339 }
340
341 /*
342 * Append data to the end of the array.
343 */
344 template <class Data>
345 inline void DSArray<Data>::append(Data const & data)
346 {
347 if (size_ == capacity_) {
348 UTIL_THROW("Attempt to add to full DSArray");
349 }
350 data_[size_] = data;
351 ++size_;
352 }
353
354 /*
355 * Modify logical size without modifying data.
356 *
357 * The size parameter must be non-negative and may not exceed
358 * the capacity.
359 *
360 * This function simply changes the logical size of without
361 * modifying any elements of the underlying physical array.
362 * If the size increases, added elements are uninitialized.
363 */
364 template <class Data>
365 inline void DSArray<Data>::resize(int size)
366 { size_ = size; }
367
368 /*
369 * Set logical size to zero.
370 */
371 template <class Data>
373 { size_ = 0; }
374
375 /*
376 * Return physical capacity of array.
377 */
378 template <class Data>
379 inline int DSArray<Data>::capacity() const
380 { return capacity_; }
381
382 /*
383 * Return logical size of this array (i.e., number of elements).
384 */
385 template <class Data>
386 inline int DSArray<Data>::size() const
387 { return size_; }
388
389 /*
390 * Return true if the DSArray has been allocated, false otherwise.
391 */
392 template <class Data>
393 inline bool DSArray<Data>::isAllocated() const
394 { return (bool)data_; }
395
396}
397#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.
Dynamically allocated array with variable logical size.
Definition: DSArray.h:31
virtual ~DSArray()
Destructor.
Definition: DSArray.h:233
void serialize(Archive &ar, const unsigned int version)
Serialize a DSArray to/from an Archive.
Definition: DSArray.h:265
bool isAllocated() const
Return true if the DSArray has been allocated, false otherwise.
Definition: DSArray.h:393
void begin(ArrayIterator< Data > &iterator)
Set an ArrayIterator to the beginning of this Array.
Definition: DSArray.h:302
Data * data_
C array of Data elements.
Definition: DSArray.h:154
void clear()
Set logical size to zero.
Definition: DSArray.h:372
void resize(int size)
Modify logical size without modifying data.
Definition: DSArray.h:365
Data & operator[](int i)
Mimic C array subscripting.
Definition: DSArray.h:323
void append(Data const &data)
Append data to the end of the array.
Definition: DSArray.h:345
int size() const
Return logical size of this array (i.e., number of elements).
Definition: DSArray.h:386
int capacity() const
Return physical capacity of array.
Definition: DSArray.h:379
DSArray< Data > & operator=(DSArray< Data > const &other)
Assignment, element by element.
Definition: DSArray.h:204
int size_
Logical size of array (number of elements used).
Definition: DSArray.h:157
DSArray()
Constructor.
Definition: DSArray.h:170
void allocate(int capacity)
Allocates the underlying C array.
Definition: DSArray.h:247
int capacity_
Capacity (physical size) of underlying C array.
Definition: DSArray.h:160
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