SoPlex
Loading...
Searching...
No Matches
classarray.h
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the class library */
4/* SoPlex --- the Sequential object-oriented simPlex. */
5/* */
6/* Copyright (c) 1996-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SoPlex; see the file LICENSE. If not email to soplex@zib.de. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file classarray.h
26 * @brief Save arrays of data objects.
27 */
28#ifndef _CLASSARRAY_H_
29#define _CLASSARRAY_H_
30
31#include <assert.h>
32#include <stddef.h>
33#include <string.h>
34#include <iostream>
35
36#include "soplex/spxdefines.h"
37#include "soplex/spxalloc.h"
38
39namespace soplex
40{
41/**@brief Safe arrays of class objects.
42 * @ingroup Elementary
43 *
44 * Class ClassArray provides safe arrays of general C++ objects (in contrast to data objects). The elements of an
45 * instance of ClassArray can be accessed just like ordinary C++ array elements by means of the index
46 * operator[](). Safety is provided by
47 *
48 * - automatic memory management in constructor and destructor preventing memory leaks
49 * - checking of array bounds when accessing elements with the indexing operator[]() when compiled without \c -DNDEBUG
50 *
51 * Moreover, #ClassArray%s may easily be extended by #insert%ing or #append%ing elements to the ClassArray or shrunken
52 * by \ref remove() "removing" elements. Method reSize(int n) resets the ClassArray%s length to \p n thereby possibly
53 * appending elements or truncating the ClassArray to the required size.
54 *
55 * A ClassArray may be used as arguments for standard C functions requiring pointers through the use of get_ptr() and
56 * get_const_ptr().
57 *
58 * Internally, a ClassArray object allocates a block of memory that fits up to max() elements, only size() of them are
59 * used. This makes extension and shrinking methods perform better.
60 *
61 * @see Array, \ref DataObjects "Data Objects"
62 */
63template < class T >
65{
66protected:
67 int thesize; ///< number of used elements in array data
68 int themax; ///< the length of array data and
69 T* data; ///< the array of elements
70
71protected:
72 /** When a ClassArray is reSize()%d to more than max() elements, the new value for max() is not just set to the new
73 * size but rather to \p memFactor * \p size. This makes #reSize%ing perform better in codes where a ClassArray is
74 * extended often by a small number of elements only.
75 */
76 double memFactor; ///< memory extension factor.
77
78public:
79
80 /// Reference to \p n 'th element.
81 T& operator[](int n)
82 {
83 assert(n >= 0);
84 assert(n < thesize);
85 return data[n];
86 }
87
88 /// Reference to \p n 'th const element.
89 const T& operator[](int n) const
90 {
91 assert(n >= 0);
92 assert(n < thesize);
93 return data[n];
94 }
95
96 /// Reference to last element.
97 T& last()
98 {
99 assert(thesize > 0);
100 return data[thesize - 1];
101 }
102
103 /// Reference to last const element.
104 const T& last() const
105 {
106 assert(thesize > 0);
107 return data[thesize - 1];
108 }
109
110 /// Gets a C pointer to the data.
112 {
113 return data;
114 }
115
116 /// Gets a const C pointer to the data.
117 const T* get_const_ptr() const
118 {
119 return data;
120 }
121
122 /// Appends element \p t.
123 void append(const T& t)
124 {
125 insert(thesize, 1, &t);
126 }
127
128 /// Appends \p n elements from \p t.
129 void append(int n, const T t[])
130 {
131 insert(thesize, n, t);
132 }
133
134 /// Appends all elements from \p t.
135 void append(const ClassArray<T>& t)
136 {
137 insert(thesize, t);
138 }
139
140 /// Inserts \p n uninitialized elements before \p i 'th element.
141 void insert(int i, int n)
142 {
143 assert(n >= 0);
144 assert(i >= 0);
145 assert(i <= thesize);
146
147 if(n > 0)
148 {
149 int j = thesize;
150
151 reSize(thesize + n);
152 assert(thesize == j + n);
153
154 /// move \p n elements in memory from insert position \p i to the back
155 while(j > i)
156 {
157 j--;
158 data[j + n] = data[j];
159 }
160 }
161 }
162
163 /// Inserts \p n elements from \p t before \p i 'the element.
164 void insert(int i, int n, const T t[])
165 {
166 if(n > 0)
167 {
168 insert(i, n);
169
170 for(int j = 0; j < n; j++)
171 data[i + j] = t[j];
172 }
173 }
174
175 /// Inserts all elements from \p t before \p i 'th element.
176 void insert(int i, const ClassArray<T>& t)
177 {
178 assert(this != &t);
179
180 if(t.size())
181 {
182 const int n = t.size();
183
184 insert(i, n);
185
186 for(int j = 0; j < n; ++j)
187 data[i + j] = t[j];
188 }
189 }
190
191 /// Removes \p m elements starting at \p n.
192 void remove(int n = 0, int m = 1)
193 {
194 const int s = size();
195 assert(n >= 0);
196 assert(n < s);
197 assert(m >= 0);
198 assert(n + m <= s);
199
200 for(int j = n + m; j < s; ++j)
201 data[j - m] = data[j];
202
203 thesize -= m;
204 }
205
206 /// Removes \p m last elements.
207 void removeLast(int m = 1)
208 {
209 assert(m >= 0);
210 assert(m <= size());
211
212 thesize -= m;
213 }
214
215 /// Removes all elements.
216 void clear()
217 {
218 thesize = 0;
219 }
220
221 /// Returns number of elements.
222 int size() const
223 {
224 return thesize;
225 }
226
227 /// Resets size to \p newsize.
228 /** Resizing a ClassArray to less than the previous size, involves discarding its last elements. Resizing to a larger
229 * value involves adding uninitialized elements (similar to append()). If neccessary, also memory will be
230 * reallocated.
231 */
232 void reSize(int newsize)
233 {
234 assert(memFactor >= 1);
235
236 if(newsize > themax)
237 reMax(int(memFactor * newsize), newsize);
238 else if(newsize < 0)
239 thesize = 0;
240 else
241 thesize = newsize;
242 }
243
244 /// Returns maximum number of elements.
245 /** Even though the ClassArray currently holds no more than size() elements, up to max() elements could be added
246 * without need to reallocated free store.
247 */
248 int max() const
249 {
250 return themax;
251 }
252
253 /// Resets maximum number of elements.
254 /** The value of max() is reset to \p newMax thereby setting size() to \p newSize. However, if \p newSize has a value
255 * \c < \c 0 (as the default argument does) size() remains unchanged and max() is set to MIN(size(), newMax). Hence,
256 * calling reMax() without the default arguments, will reduce the memory consumption to a minimum. In no instance
257 * max() will be set to a value less than 1 (even if specified).
258 *
259 * @return reMax returns the difference in bytes of the new and the old memory block, which can be used to update
260 * pointers pointing to elements of the memory block.
261 */
262 ptrdiff_t reMax(int newMax = 1, int newSize = -1)
263 {
264 /* process input */
265 if(newSize < 0)
266 newSize = size();
267
268 if(newMax < 1)
269 newMax = 1;
270
271 if(newMax < newSize)
272 newMax = newSize;
273
274 /* nothing to reallocate */
275 if(newMax == themax)
276 {
277 thesize = newSize;
278 return 0;
279 }
280
281 const int n = size();
282 T* newMem = nullptr;
283 int i;
284
285 /* allocate new memory */
286 spx_alloc(newMem, newMax);
287
288 /* call copy constructor for first elements */
289 for(i = 0; i < n && i < newSize; ++i)
290 new(&(newMem[i])) T(data[i]);
291
292 /* call default constructor for remaining elements */
293 for(; i < newMax; ++i)
294 new(&(newMem[i])) T();
295
296 /* compute pointer difference */
297 ptrdiff_t pshift = reinterpret_cast<char*>(newMem) - reinterpret_cast<char*>(data);
298
299 /* free old memory */
300 for(i = themax - 1; i >= 0; --i)
301 data[i].~T();
302
303 spx_free(data);
304
305 /* assign new memory */
306 data = newMem;
307 themax = newMax;
308 thesize = newSize;
309
310 return pshift;
311 }
312
313 /// Assignment operator.
315 {
316 if(this != &rhs)
317 {
318 const int n = rhs.size();
319
320 reSize(n);
321
322 for(int i = 0; i < n; ++i)
323 data[i] = rhs.data[i];
324
325 assert(isConsistent());
326 }
327
328 return *this;
329 }
330
331 /// Consistency check.
332 bool isConsistent() const
333 {
334#ifdef ENABLE_CONSISTENCY_CHECKS
335
336 if((data == 0)
337 || (themax < 1)
338 || (themax < thesize)
339 || (thesize < 0)
340 || (memFactor < 1.0))
341 return SPX_MSG_INCONSISTENT("ClassArray");
342
343#endif
344 return true;
345 }
346
347 /// Copy constructor.
349 : thesize(old.thesize)
350 , themax(old.themax)
351 , data(0)
352 , memFactor(old.memFactor)
353 {
354 const int n = size();
355 const int m = max();
356 int i;
357
358 /* allocate memory */
359 spx_alloc(data, m);
360
361 /* call copy constructor for first elements */
362 for(i = 0; i < n; ++i)
363 new(&(data[i])) T(old.data[i]);
364
365 /* call default constructor for remaining elements */
366 for(; i < m; ++i)
367 new(&(data[i])) T();
368
369 assert(isConsistent());
370 }
371
372 /// Default constructor.
373 /** The constructor allocates a ClassArray containing \p size uninitialized elements. The internal array is allocated
374 * to have \p max nonzeros, and the memory extension factor is set to \p fac.
375 *
376 * @param p_size number of unitialised elements.
377 * @param p_max maximum number of elements the array can hold.
378 * @param p_fac value for memFactor.
379 */
380 explicit ClassArray(int p_size = 0, int p_max = 0, double p_fac = 1.2)
381 : data(nullptr)
382 , memFactor(p_fac)
383 {
384 thesize = (p_size < 0) ? 0 : p_size;
385
386 if(p_max > thesize)
387 themax = p_max;
388 else
389 themax = (thesize == 0) ? 1 : thesize;
390
391 const int m = max();
392
393 spx_alloc(data, m);
394
395 /* call default constructor for each element */
396 for(int i = 0; i < m; ++i)
397 new(&(data[i])) T();
398
399 assert(isConsistent());
400 }
401
402 /// Destructor.
403 virtual ~ClassArray()
404 {
405 if(data)
406 {
407 for(int i = themax - 1; i >= 0; i--)
408 data[i].~T();
409
410 spx_free(data);
411 }
412 }
413};
414
415} // namespace soplex
416#endif // _CLASSARRAY_H_
bool isConsistent() const
Consistency check.
Definition classarray.h:332
T & operator[](int n)
Reference to n 'th element.
Definition classarray.h:81
ClassArray & operator=(const ClassArray &rhs)
Assignment operator.
Definition classarray.h:314
T * get_ptr()
Gets a C pointer to the data.
Definition classarray.h:111
void append(int n, const T t[])
Appends n elements from t.
Definition classarray.h:129
void insert(int i, const ClassArray< T > &t)
Inserts all elements from t before i 'th element.
Definition classarray.h:176
ClassArray(const ClassArray &old)
Copy constructor.
Definition classarray.h:348
void append(const ClassArray< T > &t)
Appends all elements from t.
Definition classarray.h:135
const T & last() const
Reference to last const element.
Definition classarray.h:104
int max() const
Returns maximum number of elements.
Definition classarray.h:248
const T * get_const_ptr() const
Gets a const C pointer to the data.
Definition classarray.h:117
void insert(int i, int n)
Inserts n uninitialized elements before i 'th element.
Definition classarray.h:141
ptrdiff_t reMax(int newMax=1, int newSize=-1)
Resets maximum number of elements.
Definition classarray.h:262
void reSize(int newsize)
Resets size to newsize.
Definition classarray.h:232
void removeLast(int m=1)
Removes m last elements.
Definition classarray.h:207
void append(const T &t)
Appends element t.
Definition classarray.h:123
void clear()
Removes all elements.
Definition classarray.h:216
const T & operator[](int n) const
Reference to n 'th const element.
Definition classarray.h:89
ClassArray(int p_size=0, int p_max=0, double p_fac=1.2)
Default constructor.
Definition classarray.h:380
void insert(int i, int n, const T t[])
Inserts n elements from t before i 'the element.
Definition classarray.h:164
void remove(int n=0, int m=1)
Removes m elements starting at n.
Definition classarray.h:192
virtual ~ClassArray()
Destructor.
Definition classarray.h:403
T & last()
Reference to last element.
Definition classarray.h:97
int size() const
Returns number of elements.
Definition classarray.h:222
Everything should be within this namespace.
void spx_alloc(T &p, size_t n=1)
Allocate memory.
Definition spxalloc.h:58
void spx_free(T &p)
Release memory.
Definition spxalloc.h:118
Memory allocation routines.
Debugging, floating point type and parameter definitions.
#define SPX_MSG_INCONSISTENT(name)
Definition spxdefines.h:175