labelRanges.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 OpenFOAM Foundation
9 Copyright (C) 2017-2020 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 "labelRanges.H"
30#include "ListOps.H"
31
32// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
33
34namespace Foam
35{
36
37 // Print range for debugging purposes
39 {
40 if (range.empty())
41 {
42 os << "empty";
43 }
44 else
45 {
46 os << range << " = " << range.first() << ":" << range.last();
47 }
48 return os;
49 }
50
51} // End namespace Foam
52
53
54
55// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56
57void Foam::labelRanges::insertBefore
58(
59 const label insert,
60 const labelRange& range
61)
62{
63 auto& list = static_cast<StorageContainer&>(*this);
64
65 // Insert via copying up
66 label nElem = list.size();
67
69 {
70 Info<< "before insert "
71 << nElem << " elements, insert at " << insert << nl
72 << list << endl;
73 }
74
75 list.resize(nElem+1);
76
78 {
79 Info<< "copy between " << nElem << " and " << insert << nl;
80 }
81
82 for (label i = nElem-1; i >= insert; --i)
83 {
85 {
86 Info<< "copy from " << (i) << " to " << (i+1) << nl;
87 }
88
89 list[i+1] = list[i];
90 }
91
92 // Finally insert the range
94 {
95 Info<< "finally insert the range at " << insert << nl;
96 }
97
98 list[insert] = range;
99}
100
101
102void Foam::labelRanges::purgeEmpty()
103{
104 auto& list = static_cast<StorageContainer&>(*this);
105
106 // Purge empty ranges by copying down
107 label nElem = 0;
108
109 forAll(list, elemi)
110 {
111 if (!list[elemi].empty())
112 {
113 if (nElem != elemi)
114 {
115 list[nElem] = list[elemi];
116 }
117 ++nElem;
118 }
119 }
120
121 // Truncate
122 list.resize(nElem);
123}
124
125
126// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
127
129{
130 is >> *this;
131}
132
133
134// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
135
137{
138 if (range.empty())
139 {
140 return false;
141 }
142 else if (this->empty())
143 {
144 this->append(range);
145 return true;
146 }
147
148 auto& list = static_cast<StorageContainer&>(*this);
149
150 // Find the correct place for insertion
151 forAll(list, elemi)
152 {
153 labelRange& currRange = list[elemi];
154
155 if (currRange.overlaps(range, true))
156 {
157 // absorb into the existing (adjacent/overlapping) range
158 currRange.join(range);
159
160 // Might connect with the next following range(s)
161 for (; elemi < this->size()-1; ++elemi)
162 {
163 labelRange& nextRange = list[elemi+1];
164 if (currRange.overlaps(nextRange, true))
165 {
166 currRange.join(nextRange);
167 nextRange.clear();
168 }
169 else
170 {
171 break;
172 }
173 }
174
175 // Done - remove any empty ranges that might have been created
176 purgeEmpty();
177 return true;
178 break;
179 }
180 else if (range < currRange)
181 {
182 insertBefore(elemi, range);
183 return true;
184 break;
185 }
186 }
187
188
189 // not found: simply append
190 this->append(range);
191
192 return true;
193}
194
195
197{
198 bool status = false;
199 if (range.empty() || this->empty())
200 {
201 return status;
202 }
203
204 auto& list = static_cast<StorageContainer&>(*this);
205
206 forAll(list, elemi)
207 {
208 labelRange& currRange = list[elemi];
209
210 if (range.first() > currRange.first())
211 {
212 if (range.last() < currRange.last())
213 {
214 // Removal of range fragments of currRange
215
217 {
218 Info<< "Fragment removal ";
219 printRange(Info, range) << " from ";
220 printRange(Info, currRange) << endl;
221 }
222
223 // left-hand-side fragment: insert before current range
224 label lower = currRange.first();
225 label upper = range.first() - 1;
226
227 labelRange fragment(lower, upper - lower + 1);
228
229 // right-hand-side fragment
230 lower = range.last() + 1;
231 upper = currRange.last();
232
233 currRange.reset(lower, upper - lower + 1);
234 currRange.clampSize();
235 status = true;
236 insertBefore(elemi, fragment);
237
239 {
240 Info<< "fragment ";
241 printRange(Info, fragment) << endl;
242 Info<< "yields ";
243 printRange(Info, currRange) << endl;
244 }
245
246 // fragmentation can only affect a single range
247 // thus we are done
248 break;
249 }
250 else if (range.first() <= currRange.last())
251 {
252 // keep left-hand-side, remove right-hand-side
253
255 {
256 Info<< "RHS removal ";
257 printRange(Info, range) << " from ";
258 printRange(Info, currRange) << endl;
259 }
260
261 const label lower = currRange.first();
262 const label upper = range.first() - 1;
263
264 currRange.reset(lower, upper - lower + 1);
265 currRange.clampSize();
266 status = true;
267
269 {
270 Info<< "yields ";
271 printRange(Info, currRange) << endl;
272 }
273 }
274 }
275 else if (range.first() <= currRange.first())
276 {
277 if (range.last() >= currRange.first())
278 {
279 // remove left-hand-side, keep right-hand-side
280
282 {
283 Info<< "LHS removal ";
284 printRange(Info, range) << " from ";
285 printRange(Info, currRange) << endl;
286 }
287
288 const label lower = range.last() + 1;
289 const label upper = currRange.last();
290
291 currRange.reset(lower, upper - lower + 1);
292 currRange.clampSize();
293 status = true;
294
296 {
297 Info<< "yields ";
298 printRange(Info, currRange) << endl;
299 }
300 }
301 }
302 }
303
304 purgeEmpty();
305
306 return status;
307}
308
309
310// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
311
313{
314 is >> static_cast<labelRanges::StorageContainer&>(ranges);
315 return is;
316}
317
318
320{
321 os << static_cast<const labelRanges::StorageContainer&>(ranges);
322 return os;
323}
324
325
326// ************************************************************************* //
scalar range
Various functions to operate on Lists.
void clear() noexcept
Reset to zero start and zero size.
Definition: IntRangeI.H:471
IntType last() const noexcept
The (inclusive) upper value of the range.
Definition: IntRangeI.H:450
void clampSize() noexcept
Enforce non-negative size.
Definition: IntRangeI.H:511
IntType first() const noexcept
The (inclusive) lower value of the range. Same as start()
Definition: IntRangeI.H:443
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
unsigned int remove()
Remove and return the last element.
Definition: PackedListI.H:709
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Sums a given list of (at least two or more) fields and outputs the result into a new field,...
Definition: add.H:161
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:58
bool overlaps(const labelRange &range, bool touches=false) const
Return true if the ranges overlap.
Definition: labelRange.C:96
static int debug
Debugging.
Definition: labelRange.H:73
labelRange join(const labelRange &range) const
Return a joined range, squashing any gaps in between.
Definition: labelRange.C:119
void reset(const label beg, const label end, const bool adjustStart) noexcept
Reset start and length, enforces non-negative size.
Definition: labelRangeI.H:102
A list of labelRange.
Definition: labelRanges.H:62
labelRanges()=default
Default construct.
OBJstream os(runTime.globalPath()/outputName)
rAUs append(new volScalarField(IOobject::groupName("rAU", phase1.name()), 1.0/(U1Eqn.A()+byDt(max(phase1.residualAlpha() - alpha1, scalar(0)) *rho1))))
Namespace for OpenFOAM.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:83
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
Istream & operator>>(Istream &, directionInfo &)
static Ostream & printRange(Ostream &os, const labelRange &range)
Definition: labelRanges.C:38
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
srcOptions insert("case", fileName(rootDirSource/caseDirSource))
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333