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-2023 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 #include "labelRange.H"
31 
32 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
33 
34 template<class T>
36 (
37  const label idx,
38  const label prevOffset,
39  const label count
40 )
41 {
42  if (idx < 0)
43  {
44  // No overflow tagged
45  return;
46  }
47 
49  << "Overflow : sum of sizes exceeds labelMax ("
50  << labelMax << ") after index " << idx;
51 
52  if (prevOffset >= 0 && count >= 0)
53  {
55  << " while trying to add (" << count
56  << ") to offset (" << prevOffset << ")";
57  }
58 
60  << nl
61  << "Please recompile with larger datatype for label." << nl
63 }
64 
65 
66 template<class T>
67 template<class ListListType>
69 (
70  const ListListType& lists,
71  const bool checkOverflow
72 )
73 {
74  CompactListList<T> compact;
75 
76  auto& newOffsets = compact.offsets_;
77  auto& newValues = compact.values_;
78 
79  label total = 0;
80  const label len = lists.size();
81 
82  if (len)
83  {
84  newOffsets.resize(len+1, Zero);
85 
86  for (label i = 0; i < len; ++i)
87  {
88  const label count = lists[i].size();
89 
90  newOffsets[i] = total;
91  total += count;
92 
93  if (checkOverflow && total < newOffsets[i])
94  {
95  reportOverflowAndExit(i, newOffsets[i], count);
96  }
97  }
98  newOffsets[len] = total;
99  }
100 
101  if (total)
102  {
103  // Make a deepCopy of data
104  newValues.resize(total);
105 
106  auto iter = newValues.begin();
107 
108  // NB: operator[] for sub-list read access (eg, an indirect list)
109  // cannot replace with std::copy
110 
111  for (const auto& list : lists)
112  {
113  const label sublen = list.size();
114 
115  for (label i = 0; i < sublen; (void)++i, (void)++iter)
116  {
117  *iter = list[i];
118  }
119  }
120  }
121 
122  return compact;
123 }
124 
125 
126 template<class T>
127 template<class SubListType>
129 (
130  const UList<SubListType>& lists,
131  const bool checkOverflow
132 )
133 {
135  (
136  lists,
137  checkOverflow
138  );
139 }
140 
141 
142 template<class T>
143 template<class SubListType, class Addr>
145 (
147  const bool checkOverflow
148 )
149 {
151  (
152  lists,
153  checkOverflow
154  );
155 }
156 
157 
158 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
159 
160 template<class T>
162 (
163  const labelUList& listSizes,
164  const bool checkOverflow
165 )
166 {
167  const label len = listSizes.size();
168  label total = 0;
169 
170  if (len)
171  {
172  offsets_.resize(len+1);
173 
174  for (label i = 0; i < len; ++i)
175  {
176  const label count = listSizes[i];
177 
178  offsets_[i] = total;
179  total += count;
180 
181  if (checkOverflow && total < offsets_[i])
182  {
183  reportOverflowAndExit(i, offsets_[i], count);
184  }
185  }
186 
187  offsets_[len] = total;
188  }
189  else
190  {
191  clear();
192  }
193  return total;
194 }
195 
196 
197 // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
198 
199 template<class T>
201 {
202  #ifdef FULLDEBUG
203  const label total = resize_offsets(listSizes, true);
204  #else
205  const label total = resize_offsets(listSizes, false);
206  #endif
207  values_.resize(total);
208 }
209 
210 
211 template<class T>
213 (
214  const labelUList& listSizes,
215  const T& val
216 )
217 {
218  #ifdef FULLDEBUG
219  const label total = resize_offsets(listSizes, true);
220  #else
221  const label total = resize_offsets(listSizes, false);
222  #endif
223  values_.resize(total, val);
224 }
225 
226 
227 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
228 
229 template<class T>
230 Foam::label Foam::CompactListList<T>::maxNonLocalSize(const label rowi) const
231 {
232  const label len = (offsets_.size() - 1);
233 
234  if (len < 1)
235  {
236  return 0;
237  }
238 
239  label maxLen = 0;
240 
241  for (label i=0; i < len; ++i)
242  {
243  if (i != rowi)
244  {
245  const label count = (offsets_[i+1] - offsets_[i]);
246  maxLen = max(maxLen, count);
247  }
248  }
249 
250  return maxLen;
251 }
252 
253 
254 template<class T>
255 std::streamsize Foam::CompactListList<T>::byteSize() const
256 {
257  if (!is_contiguous<T>::value)
258  {
260  << "Invalid for non-contiguous data types"
262  }
263  return this->size_bytes();
264 }
265 
266 
267 template<class T>
269 {
270  return labelRange(offsets_[i], offsets_[i+1] - offsets_[i]);
271 }
272 
273 
274 template<class T>
277 {
279 
280  const label len = (offsets_.size() - 1);
281 
282  if (len < 1)
283  {
284  return values;
285  }
286 
287  values.resize(len);
288 
289  for (label i=0; i < len; ++i)
290  {
291  values[i].reset(offsets_[i], (offsets_[i+1] - offsets_[i]));
292  }
293 
294  return values;
295 }
296 
297 
298 template<class T>
299 void Foam::CompactListList<T>::resize(const labelUList& listSizes)
300 {
301  #ifdef FULLDEBUG
302  const label total = resize_offsets(listSizes, true);
303  #else
304  const label total = resize_offsets(listSizes, false);
305  #endif
306  values_.resize(total);
307 }
308 
309 
310 template<class T>
312 {
313  #ifdef FULLDEBUG
314  const label total = resize_offsets(listSizes, true);
315  #else
316  const label total = resize_offsets(listSizes, false);
317  #endif
318  values_.resize_nocopy(total);
319 }
320 
321 
322 template<class T>
323 void Foam::CompactListList<T>::setLocalSize(const label rowi, const label len)
324 {
325  if (rowi >= 0 && rowi+1 < offsets_.size() && len >= 0)
326  {
327  const label delta = (len - (offsets_[rowi+1] - offsets_[rowi]));
328 
329  // TBD: additional overflow check
330  if (delta)
331  {
332  for (label i = rowi+1; i < offsets_.size(); ++i)
333  {
334  offsets_[i] += delta;
335  }
336  }
337  }
338 }
339 
340 
341 template<class T>
343 {
345 
346  const label len = (offsets_.size() - 1);
347 
348  if (len < 1)
349  {
350  return values;
351  }
352 
353  values.resize(len);
354 
355  for (label i=0; i < len; ++i)
356  {
357  values[i] = offsets_[i+1] - offsets_[i];
358  }
360  return values;
361 }
362 
363 
364 template<class T>
366 (
367  CompactListList<T>& other
368 )
369 {
370  if (this == &other)
371  {
372  return; // Self-swap is a no-op
373  }
374 
375  offsets_.swap(other.offsets_);
376  values_.swap(other.values_);
377 }
378 
379 
380 template<class T>
382 (
383  CompactListList<T>& list
384 )
385 {
386  if (this == &list)
387  {
388  return; // Self-assignment is a no-op
389  }
390 
391  offsets_.transfer(list.offsets_);
392  values_.transfer(list.values_);
393 }
394 
395 
396 template<class T>
397 template<class SubListType, class OutputIter>
399 (
400  OutputIter d_iter,
401  const label pos,
402  label len
403 ) const
404 {
405  if (pos >= 0 && pos < this->size())
406  {
407  // Change sub-length to (one-past) end position
408  // len == -1 (like std::string::npos) - search until end
409 
410  if (len > 0) len += pos;
411  if (len < 0 || len > this->size())
412  {
413  len = this->size();
414  }
415 
416  for (label i = pos; i < len; ++i)
417  {
418  *d_iter = SubListType(this->localList(i));
419  ++d_iter;
420  }
421  }
422 
423  return d_iter;
424 }
425 
426 
427 template<class T>
428 template<class SubListType, class OutputIter>
430 (
431  OutputIter d_iter,
432  const labelRange& range
433 ) const
434 {
435  return this->copy_unpack<SubListType>(d_iter, range.start(), range.size());
436 }
437 
438 
439 template<class T>
440 template<class SubListType, class OutputIter>
442 (
443  OutputIter d_iter,
444  const labelUList& indices
445 ) const
446 {
447  for (label i : indices)
448  {
449  *d_iter = SubListType(this->localList(i));
450  ++d_iter;
451  }
452 
453  return d_iter;
454 }
455 
456 
457 // Could also support copy_unpack() with IndirectListBase, as required...
458 // or the caller can also just use copy_unpack with len = 1 and the
459 // desired position
460 
461 
462 template<class T>
463 template<class SubListType>
466 {
467  List<SubListType> lists(size());
468 
469  this->copy_unpack<SubListType>(lists.begin());
470 
471  return lists;
472 }
473 
474 
475 template<class T>
476 template<class SubListType>
479 {
480  List<SubListType> lists(range.size());
481 
482  this->copy_unpack<SubListType>(lists.begin(), range.start(), range.size());
483 
484  return lists;
485 }
486 
487 
488 template<class T>
489 template<class SubListType>
491 Foam::CompactListList<T>::unpack(const labelUList& indices) const
492 {
493  List<SubListType> lists(indices.size());
494 
495  this->copy_unpack<SubListType>(lists.begin(), indices);
496 
497  return lists;
498 }
499 
500 
501 
502 // ************************************************************************* //
scalar delta
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
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:598
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:52
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:78
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.
patchWriters clear()
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:391
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.
constexpr label labelMax
Definition: label.H:55
void resize_nocopy(const label mRows, const label nVals)
Redimension without preserving existing content.
List< label > labelList
A List of labels.
Definition: List.H:62
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127