PSCF v1.1
GPArray.h
1#ifndef UTIL_G_P_ARRAY_H
2#define UTIL_G_P_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/PArray.h>
12#include <util/global.h>
13
14namespace Util
15{
16
27 template <typename Data>
28 class GPArray : public PArray<Data>
29 {
30
31 public:
32
36 GPArray();
37
45 GPArray(GPArray<Data> const & other);
46
57
64 virtual ~GPArray();
65
73 void append(Data& data);
74
84 void reserve(int capacity);
85
89 void deallocate();
90
94 void clear();
95
99 bool isAllocated() const;
100
101 protected:
102
103 using PArray<Data>::ptrs_;
104 using PArray<Data>::capacity_;
105 using PArray<Data>::size_;
106
107 };
108
109 /*
110 * Default constructor.
111 */
112 template <typename Data>
114 : PArray<Data>()
115 {}
116
117 /*
118 * Copy constructor, copy pointers.
119 *
120 * Allocates a new Data* array and copies all pointer values.
121 */
122 template <typename Data>
124 : PArray<Data>()
125 {
126 assert(other.capacity_ >= other.size_);
127 if (other.ptrs_ == 0) {
128 assert(other.capacity_ == 0);
129 assert(other.size_ == 0);
130 ptrs_ = 0;
131 capacity_ = 0;
132 size_ = 0;
133 } else {
134 assert(other.capacity_ > 0);
135 // Allocate array of Data* pointers
136 Memory::allocate<Data*>(ptrs_, other.capacity_);
137 capacity_ = other.capacity_;
138 size_ = other.size_;
139 // Copy pointers
140 if (size_ > 0) {
141 for (int i = 0; i < size_; ++i) {
142 ptrs_[i] = other.ptrs_[i];
143 }
144 }
145 // Nullify unused elements of ptrs_ array
146 if (capacity_ > size_) {
147 for (int i = size_; i < capacity_; ++i) {
148 ptrs_[i] = 0;
149 }
150 }
151 }
152 }
153
154 /*
155 * Assignment, element by element.
156 */
157 template <typename Data>
159 {
160 // Check for self assignment
161 if (this == &other) return *this;
162
163 clear();
164 for (int i = 0; i < other.size_; ++i) {
165 append(other[i]);
166 }
167 return *this;
168 }
169
170 /*
171 * Destructor.
172 */
173 template <typename Data>
175 {
176 size_ = 0;
177 if (isAllocated()) {
178 Memory::deallocate(ptrs_, capacity_);
179 capacity_ = 0;
180 }
181 }
182
183 /*
184 * Reserve space for the underlying array of Data* pointers.
185 */
186 template <typename Data>
187 void GPArray<Data>::reserve(int capacity)
188 {
189 if (capacity <= 0) {
190 UTIL_THROW("Cannot reserve with capacity <=0");
191 }
192 if (ptrs_ == 0) {
193 assert(capacity_ == 0);
194 assert(size_ == 0);
195 Memory::allocate<Data*>(ptrs_, capacity);
196 capacity_ = capacity;
197 size_ = 0;
198 } else if (capacity > capacity_) {
199 assert(capacity_ > 0);
200 assert(capacity_ >= size_);
201 assert(size_ >= 0);
202 Data** newPtr = 0;
203 Memory::allocate<Data*>(newPtr, capacity);
204 if (size_ > 0) {
205 for (int i = 0; i < size_; ++i) {
206 newPtr[i] = ptrs_[i];
207 }
208 }
209 Memory::deallocate<Data*>(ptrs_, capacity_);
210 ptrs_ = newPtr;
211 capacity_ = capacity;
212 }
213 }
214
215 /*
216 * Deallocate associated memory.
217 */
218 template <typename Data>
220 {
221 size_ = 0;
222 if (isAllocated()) {
223 assert(capacity_ > 0);
224 Memory::deallocate<Data*>(ptrs_, capacity_);
225 capacity_ = 0;
226 }
227 }
228
229 /*
230 * Append an element to the end of the PArray.
231 */
232 template <typename Data>
233 void GPArray<Data>::append(Data& data)
234 {
235 if (!isAllocated()) {
236 assert(capacity_ == 0);
237 Memory::allocate<Data*>(ptrs_, 64);
238 capacity_ = 64;
239 size_ = 0;
240 } else if (size_ == capacity_) {
241 assert(capacity_ > 0);
242 assert(capacity_ >= size_);
243 assert(size_ >= 0);
244 Data** newPtr = 0;
245 Memory::allocate<Data*>(newPtr, 2*capacity_);
246 if (size_ > 0) {
247 for (int i = 0; i < size_; ++i) {
248 newPtr[i] = ptrs_[i];
249 }
250 }
251 Memory::deallocate<Data*>(ptrs_, capacity_);
252 ptrs_ = newPtr;
253 capacity_ = 2*capacity_;
254 // size_ is unchanged
255 }
256 // Append new element
257 ptrs_[size_] = &data;
258 ++size_;
259 assert(size_ <= capacity_);
260 }
261
262 /*
263 * Reset to empty state, without deallocating.
264 */
265 template <typename Data>
267 { size_ = 0; }
268
269 /*
270 * Is this GPArray allocated?
271 */
272 template <class Data>
273 inline bool GPArray<Data>::isAllocated() const
274 { return (bool)ptrs_; }
275
276}
277#endif
An automatically growable PArray.
Definition: GPArray.h:29
void reserve(int capacity)
Reserve memory for specified number of elements.
Definition: GPArray.h:187
void clear()
Reset to empty state.
Definition: GPArray.h:266
bool isAllocated() const
Is this GPArray allocated?
Definition: GPArray.h:273
GPArray()
Constructor.
Definition: GPArray.h:113
void append(Data &data)
Append an element to the end of the sequence.
Definition: GPArray.h:233
GPArray< Data > & operator=(GPArray< Data > const &other)
Assignment, element by element.
Definition: GPArray.h:158
virtual ~GPArray()
Destructor.
Definition: GPArray.h:174
void deallocate()
Deallocate (delete) underlying array of pointers.
Definition: GPArray.h:219
static void deallocate(Data *&ptr, size_t size)
Deallocate a C++ array.
Definition: Memory.h:152
An array that only holds pointers to its elements.
Definition: PArray.h:37
int capacity_
Allocated size of ptrs_ array.
Definition: PArray.h:93
int capacity() const
Return allocated size.
Definition: PArray.h:133
int size_
Logical size (number of elements with initialized data).
Definition: PArray.h:96
Data ** ptrs_
PArray of of pointers to Data objects.
Definition: PArray.h:90
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