GemaCoreLib
The GeMA Core library
Loading...
Searching...
No Matches
gmDualVector.h
Go to the documentation of this file.
1/************************************************************************
2**
3** Copyright (C) 2014 by Carlos Augusto Teixera Mendes
4** All rights reserved.
5**
6** This file is part of the "GeMA" software. It's use should respect
7** the terms in the license agreement that can be found together
8** with this source code.
9** It is provided AS IS, with NO WARRANTY OF ANY KIND,
10** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
11** A PARTICULAR PURPOSE.
12**
13************************************************************************/
14
23#ifndef _GEMA_DUAL_VECTOR_H_
24#define _GEMA_DUAL_VECTOR_H_
25
26#include "gmPODVector.h"
27
41template <class T> class GmDualVector
42{
43public:
44 static_assert(!QTypeInfo<T>::isComplex, "Not a POD type");
45
47 typedef T DataType;
48
51
53 GmDualVector(size_t nvalues) { _fixedData = NULL; _fixedSize = 0; if(!addValues(nvalues)) throw(std::bad_alloc()); }
54
56 ~GmDualVector() { free(_fixedData); } // Plain C deallocation - see addValues()
57
59 bool isDual() const { return true; }
60
62 size_t size() const { return _fixedSize + _growData.size(); }
63
70 const T* iptr(size_t index) const
71 {
72 assert(index < size());
73 if(index < _fixedSize) //[[likely]]
74 return _fixedData + index;
75 else //[[unlikely]]
76 return _growData.data() + (index - _fixedSize);
77 }
78
80 T* iptr(size_t index)
81 {
82 assert(index < size());
83 if(index < _fixedSize) //[[likely]]
84 return _fixedData + index;
85 else //[[unlikely]]
86 return _growData.data() + (index - _fixedSize);
87 }
88
90 const T& operator[](size_t index) const { return *iptr(index); }
91
93 T& operator[](size_t index) { return *iptr(index); }
94
95 // -------------------
98 {
99 public:
100 using iterator_category = std::random_access_iterator_tag;
101 using value_type = T;
102 using difference_type = std::ptrdiff_t;
103 using pointer = T*;
104 using reference = T&;
105
106 iterator() : _vec(NULL), _index(0) {}
107 iterator(GmDualVector<T>* vec, size_t index) : _vec(vec), _index(index) {}
108
109 reference operator*() const { return (*_vec)[_index]; }
110 pointer operator->() const { return &(*_vec)[_index]; }
111 reference operator[](difference_type n) const { return (*_vec)[_index + n]; }
112
113 iterator& operator++() { ++_index; return *this; }
114 iterator operator++(int) { iterator tmp = *this; ++_index; return tmp; }
115 iterator& operator--() { --_index; return *this; }
116 iterator operator--(int) { iterator tmp = *this; --_index; return tmp; }
117 iterator& operator+=(difference_type n) { _index += n; return *this; }
118 iterator& operator-=(difference_type n) { _index -= n; return *this; }
119 iterator operator+ (difference_type n) const { return iterator(_vec, _index + n); }
120 iterator operator- (difference_type n) const { return iterator(_vec, _index - n); }
121 difference_type operator-(const iterator& other) const { assert(_vec == other._vec); return (difference_type)_index - (difference_type)other._index; }
122
123 bool operator==(const iterator& other) const { assert(_vec == other._vec); return _index == other._index; }
124 bool operator!=(const iterator& other) const { assert(_vec == other._vec); return _index != other._index; }
125 bool operator< (const iterator& other) const { assert(_vec == other._vec); return _index < other._index; }
126 bool operator> (const iterator& other) const { assert(_vec == other._vec); return _index > other._index; }
127 bool operator<=(const iterator& other) const { assert(_vec == other._vec); return _index <= other._index; }
128 bool operator>=(const iterator& other) const { assert(_vec == other._vec); return _index >= other._index; }
129
130 private:
132 size_t _index;
133 };
134
135 iterator begin() { return iterator(this, 0); }
136 iterator end() { return iterator(this, size()); }
137 // -------------------
138
146 bool addValues(size_t numAddedValues, bool tight = false)
147 {
148 S_TRACE();
149 if(numAddedValues == 0)
150 return true;
151
152 if(size() > std::numeric_limits<size_t>::max() - numAddedValues)
153 {
154 gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error adding %1 values. Vector size would surpass the maximum possible capacity.").arg(numAddedValues));
155 return false;
156 }
157
158 // If the fixed part is empty, lets use it to store the requested size
159 if(!_fixedData || (tight && !_growData.size()))
160 {
161 assert(_growData.size() == 0);
162 // We use realloc for the allocation to, hopefully, grow the vector without moving when tight is true
163 // We can do that since T is a POD type
164 T* newPtr = (T*)realloc(_fixedData, (_fixedSize + numAddedValues) * sizeof(T));
165 if(!newPtr)
166 {
167 if(!_fixedData)
168 gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error allocating a new vector with %1 entries of %2 bytes.")
169 .arg(_fixedSize + numAddedValues).arg(sizeof(T)));
170 else
171 gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error resizing a vector with %1 entries of %2 bytes to a vector with %3 entries.")
172 .arg(_fixedSize).arg(sizeof(T)).arg(_fixedSize + numAddedValues));
173 return false;
174 }
175 _fixedData = newPtr;
176 _fixedSize += numAddedValues;
177 return true;
178 }
179
180 // Fixed part already exists. Lets use the grow part of the vector
181 if(tight)
182 return _growData.resize(_growData.size() + numAddedValues, GmPODVectorTightGrow);
183 else
184 return _growData.resize(_growData.size() + numAddedValues);
185 }
186
190 void restoreSize(size_t oldNumValues)
191 {
192 S_TRACE();
193 assert(oldNumValues <= size());
194
195 if(oldNumValues > 0)
196 {
197 assert(oldNumValues >= _fixedSize);
198 _growData.resize(oldNumValues - _fixedSize);
199 }
200 else
201 clear();
202 }
203
205 void clear()
206 {
207 S_TRACE();
208 free(_fixedData);
209 _fixedData = NULL;
210 _fixedSize = 0;
211 _growData.clear();
212 }
213
215 void zero(size_t index = 0)
216 {
217 S_TRACE();
218
219 if(!_fixedSize)
220 return;
221 assert(index >= 0 && index < size());
222
223 if(index >= _fixedSize) // All the zeroed data belongs to the grow part
224 _growData.zero(index - _fixedSize);
225 else // Index starts at the fixed part
226 {
227 memset(_fixedData + index, 0, (_fixedSize - index) * sizeof(T));
228 _growData.zero();
229 }
230 }
231
237 size_t usedMemory() const { return (_fixedSize + _growData.capacity()) * sizeof(T); }
238
240 int numDumpBuffers() const { return 1 + (_growData.size() > 0); }
241
243 char* dumpBuffer(int i) const { assert(i >= 0 && i < numDumpBuffers()); return (char*)(i ? _growData.data() : _fixedData); }
244
246 size_t dumpBufferSize(int i) const { assert(i >= 0 && i < numDumpBuffers()); return (i ? _growData.size() : _fixedSize) * sizeof(T); }
247
248protected:
250 size_t _fixedSize;
251
253
254private:
255 Q_DISABLE_COPY(GmDualVector);
256};
257
258
259
263template <class T> class GmDualVectorR : public GmDualVector<T>
264{
265public:
268
270 GmDualVectorR(size_t nvalues) : GmDualVector(nvalues) { _size = nvalues; }
271
274
276 size_t size() const
277 {
278 assert(_size >= _fixedSize ? (_size == _fixedSize + _growData.size()) : (_growData.size() == 0));
279 return _size;
280 }
281
286 bool addValues(size_t numAddedValues, bool tight = false)
287 {
288 S_TRACE();
289
290 if(_size > std::numeric_limits<size_t>::max() - numAddedValues)
291 {
292 gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error adding %1 values. Vector size would surpass the maximum possible capacity.").arg(numAddedValues));
293 return false;
294 }
295
296 size_t nadd = numAddedValues;
297 if(_size < _fixedSize) // There are available entries in the fixed part
298 {
299 assert(_growData.size() == 0);
300 if(numAddedValues > _fixedSize - _size) // Carefull with negative values using size_t
301 nadd = numAddedValues - (_fixedSize - _size);
302 else
303 nadd = 0;
304 }
305
306 if(!GmDualVector<T>::addValues(nadd, tight))
307 return false;
308 _size += numAddedValues;
309 return true;
310 }
311
315 void restoreSize(size_t oldNumValues)
316 {
317 S_TRACE();
318 GmDualVector<T>::restoreSize(qMax(oldNumValues, _fixedSize));
319 _size = oldNumValues;
320 }
321
333 void removeValues(size_t index, size_t numValues)
334 {
335 S_TRACE();
336 assert(index + numValues <= _size);
337
338 if(index >= _fixedSize) // All the removed data belongs to the grow part
339 {
340 _growData.remove(index - _fixedSize, numValues);
341 _size -= numValues;
342 }
343 else
344 {
345 // At least one of the removed entries is in the fixed part
346 size_t fr = index + numValues; // The first index in the remaining part of the vector that should be moved to the left
347 size_t nr = _size - fr; // The size of the remaining part of the vector that should be moved to the left
348
349 // Move left all the remaining entries after the removed window
350 for(size_t i = 0; i < nr; i++)
351 *iptr(index+i) = *iptr(fr+i);
352
353 // Adjust the sizes
354 _size -= numValues;
355 if(_size > _fixedSize) // Carefull with negative results using size_t
356 _growData.resize(_size - _fixedSize);
357 else
358 _growData.clear();
359 }
360 }
361
363 void clear()
364 {
365 S_TRACE();
367 _size = 0;
368 }
369
371 size_t dumpBufferSize(int i) const
372 {
373 assert(i >= 0 && i < numDumpBuffers());
374 return (i ? _growData.size() : qMin(_size, _fixedSize)) * sizeof(T);
375 }
376
377private:
378 Q_DISABLE_COPY(GmDualVectorR);
379
380 size_t _size;
381};
382
383
384
385
386#endif
An iterator class to enable usage of the vector with standard algorithms such as std::sort.
Definition gmDualVector.h:98
size_t _index
Our internal index inside the vector.
Definition gmDualVector.h:132
GmDualVector< T > * _vec
The vector.
Definition gmDualVector.h:131
A vector tailored for storing mesh related data for the common scenario where elements are added to t...
Definition gmDualVector.h:42
int numDumpBuffers() const
Returns the number of internal buffers used by this implementation.
Definition gmDualVector.h:240
bool addValues(size_t numAddedValues, bool tight=false)
Adds numAddedValues to the set, without any initialization. Returns true on success,...
Definition gmDualVector.h:146
char * dumpBuffer(int i) const
Returns the i'th internal buffer, i from 0 to numDumpBuffers()-1.
Definition gmDualVector.h:243
void zero(size_t index=0)
Clears the vector area by setting to zero all entries starting at the given index.
Definition gmDualVector.h:215
size_t usedMemory() const
Returns an estimative of the memory used by the data set in bytes.
Definition gmDualVector.h:237
T & operator[](size_t index)
Non-const overload for the standard indexing operator.
Definition gmDualVector.h:93
T DataType
The stored data type.
Definition gmDualVector.h:47
const T & operator[](size_t index) const
Standard indexing operator.
Definition gmDualVector.h:90
GmDualVector(size_t nvalues)
The constructor initializing the "fixed" part size. The vector contents is NOT initialized.
Definition gmDualVector.h:53
void restoreSize(size_t oldNumValues)
Restores the size of the set to the previous size before the last call to addValues()....
Definition gmDualVector.h:190
size_t _fixedSize
The number of entries in _fixedData.
Definition gmDualVector.h:250
size_t dumpBufferSize(int i) const
Returns the size in bytes of the i'th internal buffer returned by dumpBuffer(i)
Definition gmDualVector.h:246
T * iptr(size_t index)
Non-const overload for iptr()
Definition gmDualVector.h:80
bool isDual() const
Returns true, since this IS a Dual vector.
Definition gmDualVector.h:59
GmPODVector< T > _growData
The variable part.
Definition gmDualVector.h:252
void clear()
Clears all stored data returning the object to a default constructed state.
Definition gmDualVector.h:205
T * _fixedData
The fixed part of the dual vector with _fixedSize entries.
Definition gmDualVector.h:249
~GmDualVector()
Destructor.
Definition gmDualVector.h:56
const T * iptr(size_t index) const
Returns a pointer to the index data inside the vector. By the very nature of this class,...
Definition gmDualVector.h:70
GmDualVector()
Default constructor.
Definition gmDualVector.h:50
size_t size() const
Returns the vector size.
Definition gmDualVector.h:62
A class very simmilar to GmDualVector with support for removing values. Removing values should be use...
Definition gmDualVector.h:264
void removeValues(size_t index, size_t numValues)
Removes numValues from the set, starting from (and including) index.
Definition gmDualVector.h:333
size_t _size
The total number of entries in the vector. Can be less than _fixedSize if entries where removed from ...
Definition gmDualVector.h:380
size_t dumpBufferSize(int i) const
Returns the size in bytes of the i'th internal buffer returned by dumpBuffer(i)
Definition gmDualVector.h:371
~GmDualVectorR()
Destructor.
Definition gmDualVector.h:273
bool addValues(size_t numAddedValues, bool tight=false)
Adds numAddedValues to the set, without any initialization. Returns true on success,...
Definition gmDualVector.h:286
GmDualVectorR()
Default constructor.
Definition gmDualVector.h:267
GmDualVectorR(size_t nvalues)
The constructor initializing the "fixed" part size. The vector contents is NOT initialized.
Definition gmDualVector.h:270
size_t size() const
Returns the vector size.
Definition gmDualVector.h:276
void restoreSize(size_t oldNumValues)
Restores the size of the set to the previous size before the last call to addValues()....
Definition gmDualVector.h:315
void clear()
Clears all stored data returning the object to a default constructed state.
Definition gmDualVector.h:363
A simple vector for Plain Old Data (POD) types with the control size variable type parameterized to a...
Definition gmPODVector.h:88
const GmLogCategory & GmPanicLogger()
Returns the global "panic" logger, usually used to report memory allocation fails deep inside class s...
Definition gmLog.cpp:647
Implementation of the GmPODVector template class.
size_t GmPODVectorTightGrow(size_t s, size_t a)
Vector growing to exactly the needed size.
Definition gmPODVector.h:72
#define S_TRACE()
Macro for run time stack tracking at release build.
Definition gmTrace.h:44
QString tr(const char *sourceText, const char *disambiguation, int n)