ListOpsTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "ListOps.H"
27 
28 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
29 
30 template<class ListType>
31 ListType Foam::renumber(const labelUList& oldToNew, const ListType& lst)
32 {
33  ListType newLst;
34 
35  renumber(oldToNew, lst, newLst);
36 
37  return newLst;
38 }
39 
40 
41 template<class ListType>
43 (
44  const labelUList& oldToNew,
45  const ListType& lst,
46  ListType& newLst
47 )
48 {
49  newLst.setSize(lst.size());
50 
51  forAll(lst, elemI)
52  {
53  renumber(oldToNew, lst[elemI], newLst[elemI]);
54  }
55 }
56 
57 
58 inline void Foam::renumber
59 (
60  const labelUList& oldToNew,
61  const label lst,
62  label& newLst
63 )
64 {
65  if (lst >= 0)
66  {
67  newLst = oldToNew[lst];
68  }
69 }
70 
71 
72 template<class ListType>
73 void Foam::inplaceRenumber(const labelUList& oldToNew, ListType& lst)
74 {
75  forAll(lst, elemI)
76  {
77  inplaceRenumber(oldToNew, lst[elemI]);
78  }
79 }
80 
81 
82 inline void Foam::inplaceRenumber(const labelUList& oldToNew, label& lst)
83 {
84  if (lst >= 0)
85  {
86  lst = oldToNew[lst];
87  }
88 }
89 
90 
91 template<class ListType>
92 ListType Foam::reorder
93 (
94  const labelUList& oldToNew,
95  const ListType& lst
96 )
97 {
98  // Create copy
99  ListType newLst(lst.size());
100 
101  // ensure consistent addressable size (eg, DynamicList)
102  newLst.setSize(lst.size());
103 
104  forAll(lst, elemI)
105  {
106  if (oldToNew[elemI] >= 0)
107  {
108  newLst[oldToNew[elemI]] = lst[elemI];
109  }
110  else
111  {
112  newLst[elemI] = lst[elemI];
113  }
114  }
115  return newLst;
116 }
117 
118 
119 template<class ListType>
121 (
122  const labelUList& oldToNew,
123  ListType& lst
124 )
125 {
126  // Create copy
127  ListType newLst(lst.size());
128 
129  // ensure consistent addressable size (eg, DynamicList)
130  newLst.setSize(lst.size());
131 
132  forAll(lst, elemI)
133  {
134  if (oldToNew[elemI] >= 0)
135  {
136  newLst[oldToNew[elemI]] = lst[elemI];
137  }
138  else
139  {
140  newLst[elemI] = lst[elemI];
141  }
142  }
143 
144  lst.transfer(newLst);
145 }
146 
147 
148 template<class Container>
150 (
151  const labelUList& oldToNew,
152  Container& lst
153 )
154 {
155  for
156  (
157  typename Container::iterator iter = lst.begin();
158  iter != lst.end();
159  ++iter
160  )
161  {
162  if (*iter >= 0)
163  {
164  *iter = oldToNew[*iter];
165  }
166  }
167 }
168 
169 
170 template<class Container>
172 (
173  const labelUList& oldToNew,
174  Container& lst
175 )
176 {
177  Container newLst(lst.size());
178 
179  for
180  (
181  typename Container::iterator iter = lst.begin();
182  iter != lst.end();
183  ++iter
184  )
185  {
186  if (iter.key() >= 0)
187  {
188  newLst.insert(oldToNew[iter.key()], iter());
189  }
190  }
191 
192  lst.transfer(newLst);
193 }
194 
195 
196 template<class T>
198 (
199  const UList<T>& lst,
201 )
202 {
203  sortedOrder(lst, order, typename UList<T>::less(lst));
204 }
205 
206 
207 template<class T, class Cmp>
209 (
210  const UList<T>& lst,
211  labelList& order,
212  const Cmp& cmp
213 )
214 {
215  // list lengths must be identical
216  if (order.size() != lst.size())
217  {
218  // avoid copying any elements, they are overwritten anyhow
219  order.clear();
220  order.setSize(lst.size());
221  }
222 
223  forAll(order, elemI)
224  {
225  order[elemI] = elemI;
226  }
227  Foam::stableSort(order, cmp);
228 }
229 
230 
231 template<class T>
233 (
234  const UList<T>& lst,
236 )
237 {
238  duplicateOrder(lst, order, typename UList<T>::less(lst));
239 }
240 
241 
242 template<class T, class Cmp>
244 (
245  const UList<T>& lst,
246  labelList& order,
247  const Cmp& cmp
248 )
249 {
250  if (lst.size() < 2)
251  {
252  order.clear();
253  return;
254  }
255 
256  sortedOrder(lst, order, cmp);
257 
258  label n = 0;
259  for (label i = 0; i < order.size() - 1; ++i)
260  {
261  if (lst[order[i]] == lst[order[i+1]])
262  {
263  order[n++] = order[i];
264  }
265  }
266  order.setSize(n);
267 }
268 
269 
270 template<class T>
272 (
273  const UList<T>& lst,
275 )
276 {
277  uniqueOrder(lst, order, typename UList<T>::less(lst));
278 }
279 
280 
281 template<class T, class Cmp>
283 (
284  const UList<T>& lst,
285  labelList& order,
286  const Cmp& cmp
287 )
288 {
289  sortedOrder(lst, order, cmp);
290 
291  if (order.size() > 1)
292  {
293  label n = 0;
294  for (label i = 0; i < order.size() - 1; ++i)
295  {
296  if (lst[order[i]] != lst[order[i+1]])
297  {
298  order[n++] = order[i];
299  }
300  }
301  order[n++] = order[order.size()-1];
302  order.setSize(n);
303  }
304 }
305 
306 
307 template<class T, class ListType>
308 ListType Foam::subset
309 (
310  const UList<T>& select,
311  const T& value,
312  const ListType& lst
313 )
314 {
315  // select must at least cover the list range
316  if (select.size() < lst.size())
317  {
319  << "select is of size " << select.size()
320  << "; but it must index a list of size " << lst.size()
321  << abort(FatalError);
322  }
323 
324  ListType newLst(lst.size());
325 
326  // ensure consistent addressable size (eg, DynamicList)
327  newLst.setSize(lst.size());
328 
329  label nElem = 0;
330  forAll(lst, elemI)
331  {
332  if (select[elemI] == value)
333  {
334  newLst[nElem++] = lst[elemI];
335  }
336  }
337  newLst.setSize(nElem);
338 
339  return newLst;
340 }
341 
342 
343 template<class T, class ListType>
345 (
346  const UList<T>& select,
347  const T& value,
348  ListType& lst
349 )
350 {
351  // select must at least cover the list range
352  if (select.size() < lst.size())
353  {
355  << "select is of size " << select.size()
356  << "; but it must index a list of size " << lst.size()
357  << abort(FatalError);
358  }
359 
360  label nElem = 0;
361  forAll(lst, elemI)
362  {
363  if (select[elemI] == value)
364  {
365  if (nElem != elemI)
366  {
367  lst[nElem] = lst[elemI];
368  }
369  ++nElem;
370  }
371  }
372 
373  lst.setSize(nElem);
374 }
375 
376 
377 template<class BoolListType, class ListType>
378 ListType Foam::subset
379 (
380  const BoolListType& select,
381  const ListType& lst
382 )
383 {
384  // select can have a different size
385  // eg, when it is a PackedBoolList or a labelHashSet
386 
387  ListType newLst(lst.size());
388 
389  // ensure consistent addressable size (eg, DynamicList)
390  newLst.setSize(lst.size());
391 
392  label nElem = 0;
393  forAll(lst, elemI)
394  {
395  if (select[elemI])
396  {
397  newLst[nElem++] = lst[elemI];
398  }
399  }
400  newLst.setSize(nElem);
401 
402  return newLst;
403 }
404 
405 
406 template<class BoolListType, class ListType>
408 (
409  const BoolListType& select,
410  ListType& lst
411 )
412 {
413  // select can have a different size
414  // eg, when it is a PackedBoolList or a labelHashSet
415 
416  label nElem = 0;
417  forAll(lst, elemI)
418  {
419  if (select[elemI])
420  {
421  if (nElem != elemI)
422  {
423  lst[nElem] = lst[elemI];
424  }
425  ++nElem;
426  }
427  }
428 
429  lst.setSize(nElem);
430 }
431 
432 
433 template<class InList, class OutList>
435 (
436  const label nEdges,
437  const UList<InList>& pointEdges,
438  List<OutList>& edges
439 )
440 {
441  // Number of points per edge
442  labelList nPointsPerEdge(nEdges, 0);
443 
444  forAll(pointEdges, pointi)
445  {
446  const InList& pEdges = pointEdges[pointi];
447 
448  forAll(pEdges, j)
449  {
450  nPointsPerEdge[pEdges[j]]++;
451  }
452  }
453 
454  // Size edges
455  edges.setSize(nEdges);
456 
457  forAll(nPointsPerEdge, edgeI)
458  {
459  edges[edgeI].setSize(nPointsPerEdge[edgeI]);
460  }
461  nPointsPerEdge = 0;
462 
463  // Fill edges
464  forAll(pointEdges, pointi)
465  {
466  const InList& pEdges = pointEdges[pointi];
467 
468  forAll(pEdges, j)
469  {
470  label edgeI = pEdges[j];
471 
472  edges[edgeI][nPointsPerEdge[edgeI]++] = pointi;
473  }
474  }
475 }
476 
477 
478 template<class ListType>
480 (
481  const ListType& l,
482  typename ListType::const_reference x
483 )
484 {
485  label result = 0;
486  forAll(l, i)
487  {
488  if (l[i] == x)
489  {
490  ++ result;
491  }
492  }
493  return result;
494 }
495 
496 
497 template<class ListType>
499 (
500  const ListType& l,
501  typename ListType::const_reference t,
502  const label start
503 )
504 {
505  label index = -1;
506 
507  for (label i = start; i < l.size(); i++)
508  {
509  if (l[i] == t)
510  {
511  index = i;
512  break;
513  }
514  }
515 
516  return index;
517 }
518 
519 
520 template<class ListType>
522 (
523  const ListType& l,
524  typename ListType::const_reference t,
525  const label start
526 )
527 {
528  return
530  (
531  l,
532  [&](const typename ListType::const_reference li)
533  {
534  return li == t;
535  }
536  );
537 }
538 
539 
540 template<class ListType, class BoolOp>
542 (
543  const ListType& l,
544  const BoolOp& bop,
545  const label start
546 )
547 {
548  // Count occurrences
549  label n = 0;
550 
551  for (label i = start; i < l.size(); i++)
552  {
553  if (bop(l[i]))
554  {
555  n++;
556  }
557  }
558 
559  // Create and fill
560  labelList indices(n);
561  n = 0;
562 
563  for (label i = start; i < l.size(); i++)
564  {
565  if (bop(l[i]))
566  {
567  indices[n++] = i;
568  }
569  }
570 
571  return indices;
572 }
573 
574 
575 template<class ListType>
577 (
578  ListType& l,
579  const labelUList& indices,
580  typename ListType::const_reference t
581 )
582 {
583  forAll(indices, i)
584  {
585  l[indices[i]] = t;
586  }
587 }
588 
589 
590 template<class ListType>
592 (
593  const label sz,
594  const typename ListType::const_reference initValue,
595  const labelUList& indices,
596  typename ListType::const_reference setValue
597 )
598 {
599  ListType l(sz, initValue);
600  setValues(l, indices, setValue);
601  return l;
602 }
603 
604 
605 template<class ListType>
606 Foam::label Foam::findMax(const ListType& l, const label start)
607 {
608  if (start >= l.size())
609  {
610  return -1;
611  }
612 
613  label index = start;
614 
615  for (label i = start+1; i < l.size(); i++)
616  {
617  if (l[i] > l[index])
618  {
619  index = i;
620  }
621  }
622 
623  return index;
624 }
625 
626 
627 template<class ListType>
628 Foam::label Foam::findMin(const ListType& l, const label start)
629 {
630  if (start >= l.size())
631  {
632  return -1;
633  }
634 
635  label index = start;
636 
637  for (label i = start+1; i < l.size(); i++)
638  {
639  if (l[i] < l[index])
640  {
641  index = i;
642  }
643  }
644 
645  return index;
646 }
647 
648 
649 template<class ListType>
651 (
652  const ListType& l,
653  typename ListType::const_reference t,
654  const label start
655 )
656 {
657  if (start >= l.size())
658  {
659  return -1;
660  }
661 
662  label low = start;
663  label high = l.size() - 1;
664 
665  while (low <= high)
666  {
667  label mid = (low + high)/2;
668 
669  if (t < l[mid])
670  {
671  high = mid - 1;
672  }
673  else if (t > l[mid])
674  {
675  low = mid + 1;
676  }
677  else
678  {
679  return mid;
680  }
681  }
682 
683  return -1;
684 }
685 
686 
687 template<class ListType, class BinaryOp>
689 (
690  const ListType& l,
691  typename ListType::const_reference t,
692  const label start,
693  const BinaryOp& bop
694 )
695 {
696  if (start >= l.size())
697  {
698  return -1;
699  }
700 
701  label low = start;
702  label high = l.size() - 1;
703 
704  while ((high - low) > 1)
705  {
706  label mid = (low + high)/2;
707 
708  if (bop(l[mid], t))
709  {
710  low = mid;
711  }
712  else
713  {
714  high = mid;
715  }
716  }
717 
718  if (bop(l[high], t))
719  {
720  return high;
721  }
722  else
723  {
724  if (bop(l[low], t))
725  {
726  return low;
727  }
728  else
729  {
730  return -1;
731  }
732  }
733 }
734 
735 
736 template<class ListType>
738 (
739  const ListType& l,
740  typename ListType::const_reference t,
741  const label start
742 )
743 {
744  return findLower(l, t, start, lessOp<typename ListType::value_type>());
745 }
746 
747 
748 template<class Container, class T, int mRows>
749 Foam::List<Container> Foam::initList(const T elems[mRows])
750 {
751  List<Container> lst(mRows);
752 
753  forAll(lst, rowI)
754  {
755  lst[rowI] = Container(elems[rowI]);
756  }
757  return lst;
758 }
759 
760 
761 template<class Container, class T, int mRows, int nColumns>
762 Foam::List<Container> Foam::initListList(const T elems[mRows][nColumns])
763 {
764  List<Container> lst(mRows);
765 
766  Container cols(nColumns);
767  forAll(lst, rowI)
768  {
769  forAll(cols, colI)
770  {
771  cols[colI] = elems[rowI][colI];
772  }
773  lst[rowI] = cols;
774  }
775  return lst;
776 }
777 
778 
779 template<class ListType>
780 ListType Foam::reverseList(const ListType& list)
781 {
782  const label listSize = list.size();
783  const label lastIndex = listSize - 1;
784 
785  ListType tmpList(listSize);
786 
787  forAll(tmpList, elemI)
788  {
789  tmpList[elemI] = list[lastIndex - elemI];
790  }
791 
792  return tmpList;
793 }
794 
795 
796 template<class ListType>
797 void Foam::inplaceReverseList(ListType& list)
798 {
799  const label listSize = list.size();
800  const label lastIndex = listSize - 1;
801  const label nIterations = listSize >> 1;
802 
803  label elemI = 0;
804  while (elemI < nIterations)
805  {
806  Swap(list[elemI], list[lastIndex - elemI]);
807 
808  elemI++;
809  }
810 }
811 
812 
813 template<class ListType>
814 ListType Foam::rotateList(const ListType& list, const label n)
815 {
816  const label listSize = list.size();
817 
818  ListType tmpList(listSize);
819 
820  forAll(tmpList, elemI)
821  {
822  label index = (elemI - n) % listSize;
823 
824  if (index < 0)
825  {
826  index += listSize;
827  }
828 
829  tmpList[elemI] = list[index];
830  }
831 
832  return tmpList;
833 }
834 
835 
836 template<template<typename> class ListType, class DataType>
837 void Foam::inplaceRotateList(ListType<DataType>& list, label n)
838 {
839  const label listSize = list.size();
840 
841  n = (listSize - n) % listSize;
842 
843  if (n < 0)
844  {
845  n += listSize;
846  }
847 
848  SubList<DataType> firstHalf(list, n, 0);
849  SubList<DataType> secondHalf(list, listSize - n, n);
850 
851  inplaceReverseList(firstHalf);
852  inplaceReverseList(secondHalf);
853 
854  inplaceReverseList(list);
855 }
856 
857 
858 template<class BinaryOp>
859 template<class Type>
861 (
862  const List<Type>& a,
863  const List<Type>& b
864 ) const
865 {
866  List<Type> c(a.size());
867  forAll(a, i)
868  {
869  c[i] = BinaryOp()(a[i], b[i]);
870  }
871  return c;
872 }
873 
874 
875 template<class BinaryEqOp>
876 template<class Type>
878 (
879  List<Type>& a,
880  const List<Type>& b
881 ) const
882 {
883  forAll(a, i)
884  {
885  BinaryEqOp()(a[i], b[i]);
886  }
887 }
888 
889 
890 template<class T>
892 {
893  if (y.size())
894  {
895  if (x.size())
896  {
897  label sz = x.size();
898  x.setSize(sz + y.size());
899  forAll(y, i)
900  {
901  x[sz++] = y[i];
902  }
903  }
904  else
905  {
906  x = y;
907  }
908  }
909 }
910 
911 
912 // ************************************************************************* //
scalar y
Various functions to operate on Lists.
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
A List obtained as a section of another List.
Definition: SubList.H:56
Less function class that can be used for sorting.
Definition: UList.H:118
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
Motion of the mesh specified as a list of pointMeshMovers.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
volScalarField & b
Definition: createFields.H:27
const dimensionedScalar c
Speed of light in a vacuum.
labelList selectIndices(const ListType &, const BoolOp &bop, const label start=0)
Select all occurrences given a boolean critera. Linear search.
List< Container > initList(const T[mRows])
To construct a List from a C array. Has extra Container type.
void inplaceMapValue(const labelUList &oldToNew, Container &)
Map values. Do not map negative values.
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
label findMax(const ListType &, const label start=0)
Find index of max element (and larger than given element).
ListType reverseList(const ListType &list)
Reverse a list. First element becomes last element etc.
void inplaceReverseList(ListType &list)
Inplace reversal of a list using Swap.
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurrences of given element. Linear search.
void duplicateOrder(const UList< T > &, labelList &order)
Generate (sorted) indices corresponding to duplicate list values.
void inplaceMapKey(const labelUList &oldToNew, Container &)
Recreate with mapped keys. Do not map elements with negative key.
label findLower(const ListType &, typename ListType::const_reference, const label stary, const BinaryOp &bop)
Find last element < given value in sorted list and return index,.
int order(const scalar s)
void inplaceSubset(const UList< T > &select, const T &value, ListType &)
Inplace extract elements of List when select is a certain value.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
ListType rotateList(const ListType &list, const label n)
Rotate a list by n places. If n is positive rotate clockwise/right/down.
void inplaceRotateList(ListType< DataType > &list, label n)
Inplace reversal of a list using the Reversal Block Swapping algorithm.
ListType reorder(const label size, const typename ListType::value_type &defaultValue, const labelUList &oldToNew, const ListType &lst)
label findSortedIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element in sorted list and return index,.
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
List< Container > initListList(const T[mRows][nColumns])
To construct a (square) ListList from a C array. Has extra Container type.
void Swap(T &a, T &b)
Definition: Swap.H:43
void stableSort(UList< T > &)
Definition: UList.C:129
void uniqueOrder(const UList< T > &, labelList &order)
Generate (sorted) indices corresponding to unique list values.
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
void setValues(ListType &, const labelUList &indices, typename ListType::const_reference)
Opposite of findIndices: set values at indices to given value.
void T(GeometricField< Type, GeoMesh, PrimitiveField1 > &gf, const GeometricField< Type, GeoMesh, PrimitiveField2 > &gf1)
ListType createWithValues(const label sz, typename ListType::const_reference initValue, const labelUList &indices, typename ListType::const_reference setValue)
Opposite of findIndices: set values at indices to given value.
ListType subset(const UList< T > &select, const T &value, const ListType &)
Extract elements of List when select is a certain value.
void invertManyToMany(const label len, const UList< InList > &, List< OutList > &)
Invert many-to-many.
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
void operator()(List< T > &x, const List< T > &y) const
Operator to apply a binary-equals operation to a pair of lists.
Definition: ListOps.H:305
Operator to apply a binary operation to a pair of lists.
Definition: ListOps.H:297