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 -------------------------------------------------------------------------------
11 License
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 
33 template<class T>
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
62 }
63 
64 
65 template<class T>
66 template<class ListListType>
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  }
120 
121  return compact;
122 }
123 
124 
125 template<class T>
126 template<class SubListType>
128 (
129  const UList<SubListType>& lists,
130  const bool checkOverflow
131 )
132 {
134  (
135  lists,
136  checkOverflow
137  );
138 }
139 
140 
141 template<class T>
142 template<class SubListType, class Addr>
144 (
146  const bool checkOverflow
147 )
148 {
150  (
151  lists,
152  checkOverflow
153  );
154 }
155 
156 
157 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
158 
159 template<class T>
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 
198 template<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 
210 template<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 
228 template<class T>
229 Foam::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  }
247  }
248 
249  return maxLen;
250 }
251 
252 
253 template<class T>
254 std::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 
266 template<class T>
268 {
269  return labelRange(offsets_[i], offsets_[i+1] - offsets_[i]);
270 }
271 
272 
273 template<class T>
276 {
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]));
291  }
292 
293  return values;
294 }
295 
296 
297 template<class T>
298 void 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 
309 template<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 
321 template<class T>
322 void 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;
334  }
335  }
336  }
337 }
338 
339 
340 template<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];
357  }
359  return values;
360 }
361 
362 
363 template<class T>
365 (
366  CompactListList<T>& other
367 )
368 {
369  if (this == &other)
370  {
371  return; // Self-swap is a no-op
372  }
373 
374  offsets_.swap(other.offsets_);
375  values_.swap(other.values_);
376 }
377 
378 
379 template<class T>
381 (
382  CompactListList<T>& list
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 
395 template<class T>
396 template<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  }
421 
422  return d_iter;
423 }
424 
425 
426 template<class T>
427 template<class SubListType, class OutputIter>
429 (
430  OutputIter d_iter,
431  const labelRange& range
432 ) const
433 {
434  return this->copy_unpack<SubListType>(d_iter, range.start(), range.size());
435 }
436 
437 
438 template<class T>
439 template<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 
461 template<class T>
462 template<class SubListType>
465 {
466  List<SubListType> lists(size());
467 
468  this->copy_unpack<SubListType>(lists.begin());
469 
470  return lists;
471 }
472 
473 
474 template<class T>
475 template<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 
487 template<class T>
488 template<class SubListType>
490 Foam::CompactListList<T>::unpack(const labelUList& indices) const
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 delta
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
label size() const noexcept
The primary size (the number of rows/sublists)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:652
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:63
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
void swap(CompactListList< T > &other)
Swap contents.
static CompactListList< T > pack(const UList< SubListType > &lists, const bool checkOverflow=false)
Construct by packing together the list of lists.
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
scalar range
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
void transfer(CompactListList< T > &list)
Transfer contents into this and annul the argument.
void setLocalSize(const label rowi, const label len)
Alter local addressing size for given row, does not change content.
List< labelRange > ranges() const
Return start/size ranges for all sub-lists.
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)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
List< SubListType > unpack() const
Return non-compact list of lists.
labelRange range(const label i) const
Return start/size range for given sub-list.
CompactListList() noexcept=default
Default construct.
void resize(const label mRows)
Reset size of CompactListList.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:403
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
std::streamsize byteSize() const
Number of contiguous bytes for the values data, runtime FatalError if type is not contiguous...
A packed storage of objects of type <T> using an offset table for access.
const volScalarField & T
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()...
labelList localSizes() const
The local row sizes.
surface1 clear()
constexpr label labelMax
Definition: label.H:55
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
void resize_nocopy(const label mRows, const label nVals)
Redimension without preserving existing content.
List< label > labelList
A List of labels.
Definition: List.H:61