ListOps.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-2015 OpenFOAM Foundation
9  Copyright (C) 2018-2024 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 "ListOps.H"
31 #include "HashSet.H"
32 #include <numeric>
33 
34 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
35 
37 (
38  const label len,
39  const labelUList& map
40 )
41 {
42  labelList inverse(len, -1);
43 
44  label i = 0;
45  for (const label newIdx : map)
46  {
47  if (newIdx >= 0)
48  {
49  #ifdef FULLDEBUG
50  if (newIdx >= len)
51  {
53  << "Inverse location " << newIdx
54  << " is out of range. List has size " << len
55  << abort(FatalError);
56  }
57  #endif
58 
59  if (inverse[newIdx] >= 0)
60  {
62  << "Map is not one-to-one. At index " << i
63  << " element " << newIdx << " has already occurred\n"
64  << "Please use invertOneToMany instead"
65  << abort(FatalError);
66  }
67 
68  inverse[newIdx] = i;
69  }
70 
71  ++i;
72  }
73 
74  return inverse;
75 }
76 
77 
79 (
80  const label len,
81  const bitSet& map
82 )
83 {
84  labelList inverse(len, -1);
85 
86  label i = 0;
87  for (const label newIdx : map)
88  {
89  #ifdef FULLDEBUG
90  if (newIdx >= len)
91  {
93  << "Inverse location " << newIdx
94  << " is out of range. List has size " << len
95  << abort(FatalError);
96  }
97  #endif
98 
99  inverse[newIdx] = i;
100 
101  ++i;
102  }
103 
104  return inverse;
105 }
106 
109 {
110  return invert(map.size(), map);
111 }
112 
113 
115 {
116  const label len = values.size();
117 
118  Map<label> inverse(2*len);
119 
120  for (label i = 0 ; i < len; ++i)
121  {
122  // For correct behaviour with duplicates, do NOT use
123  // inverse.insert(values[i], inverse.size());
124 
125  inverse.insert(values[i], i);
126  }
127 
128  return inverse;
129 }
130 
131 
133 (
134  const label len,
135  const labelUList& map
136 )
137 {
138  labelList sizes(len, Foam::zero{});
139 
140  for (const label newIdx : map)
141  {
142  if (newIdx >= 0)
143  {
144  #ifdef FULLDEBUG
145  if (newIdx >= len)
146  {
148  << "Inverse location " << newIdx
149  << " is out of range. List has size " << len
150  << abort(FatalError);
151  }
152  #endif
153 
154  ++sizes[newIdx];
155  }
156  }
157 
158  labelListList inverse(len);
159 
160  for (label i = 0; i < len; ++i)
161  {
162  inverse[i].resize(sizes[i]);
163  sizes[i] = 0; // reset size counter
164  }
165 
166  label i = 0;
167  for (const label newIdx : map)
168  {
169  if (newIdx >= 0)
170  {
171  inverse[newIdx][sizes[newIdx]++] = i;
172  }
173 
174  ++i;
175  }
177  return inverse;
178 }
179 
180 
183 (
184  const label len,
185  const labelUList& map
186 )
187 {
188  labelList sizes(len, Foam::zero{});
189 
190  for (const label newIdx : map)
191  {
192  if (newIdx >= 0)
193  {
194  #ifdef FULLDEBUG
195  if (newIdx >= len)
196  {
198  << "Inverse location " << newIdx
199  << " is out of range. List has size " << len
200  << abort(FatalError);
201  }
202  #endif
203 
204  ++sizes[newIdx];
205  }
206  }
207 
208  CompactListList<label> inverse(sizes);
209 
210  // Reuse sizes as output offset into inverse.values()
211  sizes = labelList::subList(inverse.offsets(), inverse.size());
212  labelList& values = inverse.values();
213 
214  label i = 0;
215  for (const label newIdx : map)
216  {
217  if (newIdx >= 0)
218  {
219  values[sizes[newIdx]++] = i;
220  }
221 
222  ++i;
223  }
224 
225  return inverse;
226 }
227 
228 
230 (
231  const labelUList& oldToNew,
232  const bitSet& input,
233  const bool prune
234 )
235 {
236  const label len = input.size();
237 
238  bitSet output;
239  output.reserve(len);
240 
241  for
242  (
243  label pos = input.find_first();
244  pos >= 0 && pos < len;
245  pos = input.find_next(pos)
246  )
247  {
248  const label newIdx = oldToNew[pos];
249 
250  if (newIdx >= 0)
251  {
252  output.set(newIdx);
253  }
254  else if (!prune)
255  {
256  output.set(pos);
257  }
258  }
259 
260  if (prune)
261  {
262  output.trim();
263  }
264 
265  return output;
266 }
267 
268 
270 (
271  const labelUList& oldToNew,
272  bitSet& input,
273  const bool prune
274 )
275 {
276  input = Foam::reorder(oldToNew, input, prune);
277 }
278 
279 
280 void Foam::ListOps::unionEqOp::operator()
281 (
282  labelList& x,
283  const labelList& y
284 ) const
285 {
286  if (y.size())
287  {
288  if (x.size())
289  {
290  labelHashSet set(x);
291  set.insert(y);
292  x = set.toc();
293  }
294  else
295  {
296  x = y;
297  }
298  }
299 }
300 
301 
302 // ************************************************************************* //
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:608
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:232
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
Various functions to operate on 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)
scalar y
CompactListList< label > invertOneToManyCompact(const label len, const labelUList &map)
Invert one-to-many compact map. Unmapped elements will be size 0.
Definition: ListOps.C:176
labelListList invertOneToMany(const label len, const labelUList &map)
Invert one-to-many map. Unmapped elements will be size 0.
Definition: ListOps.C:126
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:33
errorManip< error > abort(error &err)
Definition: errorManip.H:139
A packed storage of objects of type <T> using an offset table for access.
labelList invert(const label len, const labelUList &map)
Create an inverse one-to-one mapping.
Definition: ListOps.C:30
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:44
List< label > labelList
A List of labels.
Definition: List.H:62
ListType reorder(const labelUList &oldToNew, const ListType &input, const bool prune=false)
Reorder the elements of a list.
Map< label > invertToMap(const labelUList &values)
Create inverse mapping, which is a lookup table into the given list.
Definition: ListOps.C:107
label size() const noexcept
Number of entries.
Definition: PackedList.H:393
A HashTable to objects of type <T> with a label key.