Loading...
Searching...
No Matches
CompactListList.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2019-2025 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "CompactListList.H"
30
31// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
32
33template<class T>
34void Foam::CompactListList<T>::reportOverflowAndExit
35(
36 const label idx,
37 const label prevOffset,
38 const label count
39)
40{
41 if (idx < 0)
42 {
43 // No overflow tagged
44 return;
45 }
46
48 << "Overflow : sum of sizes exceeds labelMax ("
49 << labelMax << ") after index " << idx;
50
51 if (prevOffset >= 0 && count >= 0)
52 {
54 << " while trying to add (" << count
55 << ") to offset (" << prevOffset << ")";
56 }
57
59 << nl
60 << "Please recompile with larger datatype for label." << nl
61 << exit(FatalError);
62}
63
64
65template<class T>
66template<class ListListType>
67Foam::CompactListList<T> Foam::CompactListList<T>::pack_impl
68(
69 const ListListType& lists,
70 const bool checkOverflow
71)
72{
73 CompactListList<T> compact;
74
75 auto& newOffsets = compact.offsets_;
76 auto& newValues = compact.values_;
77
78 label total = 0;
79 const label len = lists.size();
80
81 if (len)
82 {
83 newOffsets.resize(len+1, Foam::zero{});
84
85 for (label i = 0; i < len; ++i)
86 {
87 const label count = lists[i].size();
88
89 newOffsets[i] = total;
90 total += count;
91
92 if (checkOverflow && total < newOffsets[i])
93 {
94 reportOverflowAndExit(i, newOffsets[i], count);
95 }
96 }
97 newOffsets[len] = total;
98 }
99
100 if (total)
101 {
102 // Make a deepCopy of data
103 newValues.resize(total);
104
105 auto iter = newValues.begin();
106
107 // NB: operator[] for sub-list read access (eg, an indirect list)
108 // cannot replace with std::copy
109
110 for (const auto& list : lists)
111 {
112 const label sublen = list.size();
113
114 for (label i = 0; i < sublen; (void)++i, (void)++iter)
115 {
116 *iter = list[i];
117 }
118 }
119 }
121 return compact;
122}
123
124
125template<class T>
126template<class SubListType>
128(
129 const UList<SubListType>& lists,
130 const bool checkOverflow
131)
132{
133 return CompactListList<T>::pack_impl<UList<SubListType>>
134 (
135 lists,
136 checkOverflow
137 );
138}
139
140
141template<class T>
142template<class SubListType, class Addr>
144(
146 const bool checkOverflow
147)
148{
149 return CompactListList<T>::pack_impl<IndirectListBase<SubListType, Addr>>
150 (
151 lists,
152 checkOverflow
153 );
154}
155
156
157// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
158
159template<class T>
160Foam::label Foam::CompactListList<T>::resize_offsets
161(
162 const labelUList& listSizes,
163 const bool checkOverflow
164)
165{
166 const label len = listSizes.size();
167 label total = 0;
168
169 if (len)
170 {
171 offsets_.resize(len+1);
172
173 for (label i = 0; i < len; ++i)
174 {
175 const label count = listSizes[i];
176
177 offsets_[i] = total;
178 total += count;
179
180 if (checkOverflow && total < offsets_[i])
181 {
182 reportOverflowAndExit(i, offsets_[i], count);
183 }
184 }
185
186 offsets_[len] = total;
187 }
188 else
189 {
190 clear();
191 }
192 return total;
193}
194
195
196// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
197
198template<class T>
200{
201 #ifdef FULLDEBUG
202 const label total = resize_offsets(listSizes, true);
203 #else
204 const label total = resize_offsets(listSizes, false);
205 #endif
206 values_.resize(total);
207}
208
209
210template<class T>
212(
213 const labelUList& listSizes,
214 const T& val
215)
216{
217 #ifdef FULLDEBUG
218 const label total = resize_offsets(listSizes, true);
219 #else
220 const label total = resize_offsets(listSizes, false);
221 #endif
222 values_.resize(total, val);
223}
224
225
226// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
227
228template<class T>
229Foam::label Foam::CompactListList<T>::maxNonLocalSize(const label rowi) const
230{
231 const label len = (offsets_.size() - 1);
232
233 if (len < 1)
234 {
235 return 0;
236 }
237
238 label maxLen = 0;
239
240 for (label i=0; i < len; ++i)
241 {
242 if (i != rowi)
243 {
244 const label count = (offsets_[i+1] - offsets_[i]);
245 maxLen = max(maxLen, count);
246 }
248
249 return maxLen;
250}
251
252
253template<class T>
254std::streamsize Foam::CompactListList<T>::byteSize() const
255{
256 if constexpr (!is_contiguous_v<T>)
257 {
259 << "Invalid for non-contiguous data types"
261 }
262 return this->size_bytes();
263}
264
265
266template<class T>
269 return labelRange(offsets_[i], offsets_[i+1] - offsets_[i]);
270}
271
272
273template<class T>
276{
277 List<labelRange> values;
278
279 const label len = (offsets_.size() - 1);
280
281 if (len < 1)
282 {
283 return values;
284 }
285
286 values.resize(len);
287
288 for (label i=0; i < len; ++i)
289 {
290 values[i].reset(offsets_[i], (offsets_[i+1] - offsets_[i]));
292
293 return values;
294}
295
296
297template<class T>
298void Foam::CompactListList<T>::resize(const labelUList& listSizes)
299{
300 #ifdef FULLDEBUG
301 const label total = resize_offsets(listSizes, true);
302 #else
303 const label total = resize_offsets(listSizes, false);
304 #endif
305 values_.resize(total);
306}
307
308
309template<class T>
311{
312 #ifdef FULLDEBUG
313 const label total = resize_offsets(listSizes, true);
314 #else
315 const label total = resize_offsets(listSizes, false);
316 #endif
317 values_.resize_nocopy(total);
318}
319
320
321template<class T>
322void Foam::CompactListList<T>::setLocalSize(const label rowi, const label len)
323{
324 if (rowi >= 0 && rowi+1 < offsets_.size() && len >= 0)
325 {
326 const label delta = (len - (offsets_[rowi+1] - offsets_[rowi]));
327
328 // TBD: additional overflow check
329 if (delta)
330 {
331 for (label i = rowi+1; i < offsets_.size(); ++i)
332 {
333 offsets_[i] += delta;
335 }
336 }
337}
338
339
340template<class T>
342{
344
345 const label len = (offsets_.size() - 1);
346
347 if (len < 1)
348 {
349 return values;
350 }
351
352 values.resize(len);
353
354 for (label i=0; i < len; ++i)
355 {
356 values[i] = offsets_[i+1] - offsets_[i];
358
359 return values;
360}
361
362
363template<class T>
365(
366 CompactListList<T>& other
367)
368{
369 if (this == &other)
370 {
371 return; // Self-swap is a no-op
372 }
374 offsets_.swap(other.offsets_);
375 values_.swap(other.values_);
376}
377
378
379template<class T>
381(
383)
384{
385 if (this == &list)
386 {
387 return; // Self-assignment is a no-op
388 }
389
390 offsets_.transfer(list.offsets_);
391 values_.transfer(list.values_);
392}
393
394
395template<class T>
396template<class SubListType, class OutputIter>
398(
399 OutputIter d_iter,
400 const label pos,
401 label len
402) const
403{
404 if (pos >= 0 && pos < this->size())
405 {
406 // Change sub-length to (one-past) end position
407 // len == -1 (like std::string::npos) - search until end
408
409 if (len > 0) len += pos;
410 if (len < 0 || len > this->size())
411 {
412 len = this->size();
413 }
414
415 for (label i = pos; i < len; ++i)
416 {
417 *d_iter = SubListType(this->localList(i));
418 ++d_iter;
419 }
420 }
422 return d_iter;
423}
424
425
426template<class T>
427template<class SubListType, class OutputIter>
429(
430 OutputIter d_iter,
431 const labelRange& range
432) const
434 return this->copy_unpack<SubListType>(d_iter, range.start(), range.size());
435}
436
437
438template<class T>
439template<class SubListType, class OutputIter>
441(
442 OutputIter d_iter,
443 const labelUList& indices
444) const
445{
446 for (label i : indices)
447 {
448 *d_iter = SubListType(this->localList(i));
449 ++d_iter;
450 }
451
452 return d_iter;
453}
454
455
456// Could also support copy_unpack() with IndirectListBase, as required...
457// or the caller can also just use copy_unpack with len = 1 and the
458// desired position
459
460
461template<class T>
462template<class SubListType>
465{
466 List<SubListType> lists(size());
467
468 this->copy_unpack<SubListType>(lists.begin());
469
470 return lists;
471}
472
473
474template<class T>
475template<class SubListType>
478{
479 List<SubListType> lists(range.size());
480
481 this->copy_unpack<SubListType>(lists.begin(), range.start(), range.size());
482
483 return lists;
484}
485
486
487template<class T>
488template<class SubListType>
491{
492 List<SubListType> lists(indices.size());
493
494 this->copy_unpack<SubListType>(lists.begin(), indices);
495
496 return lists;
497}
498
499
500
501// ************************************************************************* //
scalar range
scalar delta
A packed storage of objects of type <T> using an offset table for access.
List< SubListType > unpack() const
Return non-compact list of lists.
void resize_nocopy(const label mRows, const label nVals)
Redimension without preserving existing content.
const List< T > & values() const noexcept
Return the packed values.
List< labelRange > ranges() const
Return start/size ranges for all sub-lists.
labelRange range(const label i) const
Return start/size range for given sub-list.
static CompactListList< T > pack(const UList< SubListType > &lists, const bool checkOverflow=false)
Construct by packing together the list of lists.
void transfer(CompactListList< T > &list)
Transfer contents into this and annul the argument.
label size() const noexcept
The primary size (the number of rows/sublists).
std::streamsize byteSize() const
Number of contiguous bytes for the values data, runtime FatalError if type is not contiguous.
const SubList< T > localList(const label i) const
Return const access to sub-list (no subscript checking).
void setLocalSize(const label rowi, const label len)
Alter local addressing size for given row, does not change content.
void resize(const label mRows)
Reset size of CompactListList.
labelList localSizes() const
The local row sizes.
void swap(CompactListList< T > &other)
Swap contents.
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the values data, no runtime check that the type is actually contiguous...
CompactListList() noexcept=default
OutputIter copy_unpack(OutputIter d_iter, const label pos=0, label len=-1) const
Unpack sub-list copies in the range defined by pos and len with bounding behaviour like List::slice()...
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
label size() const noexcept
The number of elements in the list.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition UListI.H:410
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
A range or interval of labels defined by a start and a size.
Definition labelRange.H:66
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
surface1 clear()
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition BitOps.H:73
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition HashOps.H:164
dimensionedScalar pos(const dimensionedScalar &ds)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< label > labelList
A List of labels.
Definition List.H:62
constexpr label labelMax
Definition label.H:55
errorManip< error > abort(error &err)
Definition errorManip.H:139
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
constexpr bool is_contiguous_v
The is_contiguous value of Type (after stripping of qualifiers).
Definition contiguous.H:77
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50