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 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 "labelRanges.H"
30 #include "ListOps.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 void Foam::labelRanges::insertBefore
35 (
36  const label insert,
37  const labelRange& range
38 )
39 {
40  // insert via copying up
41  label nElem = this->size();
42 
44  {
45  Info<<"before insert "
46  << nElem << " elements, insert at " << insert << nl
47  << *this << endl;
48  }
49 
51 
53  {
54  Info<<"copy between " << nElem << " and " << insert << nl;
55  }
56 
57  for (label i = nElem-1; i >= insert; --i)
58  {
60  {
61  Info<<"copy from " << (i) << " to " << (i+1) << nl;
62  }
63 
64  StorageContainer::operator[](i+1) = StorageContainer::operator[](i);
65  }
66 
67  // finally insert the range
69  {
70  Info<< "finally insert the range at " << insert << nl;
71  }
72  StorageContainer::operator[](insert) = range;
73 }
74 
75 
76 void Foam::labelRanges::purgeEmpty()
77 {
78  // purge empty ranges by copying down
79  label nElem = 0;
80  forAll(*this, elemI)
81  {
82  if (!StorageContainer::operator[](elemI).empty())
83  {
84  if (nElem != elemI)
85  {
86  StorageContainer::operator[](nElem) =
87  StorageContainer::operator[](elemI);
88  }
89  ++nElem;
90  }
91  }
92 
93  // truncate
94  this->StorageContainer::setSize(nElem);
95 }
96 
97 
98 Foam::Ostream& Foam::labelRanges::printRange
99 (
100  Ostream& os,
101  const labelRange& range
102 ) const
103 {
104  if (range.empty())
105  {
106  os << "empty";
107  }
108  else
109  {
110  os << range << " = " << range.first() << ":" << range.last();
111  }
112  return os;
113 }
114 
115 
116 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
117 
119 {
120  is >> *this;
121 }
122 
123 
124 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
125 
127 {
128  if (range.empty())
129  {
130  return false;
131  }
132  else if (this->empty())
133  {
134  this->append(range);
135  return true;
136  }
137 
138  // find the correct place for insertion
139  forAll(*this, elemI)
140  {
141  labelRange& currRange = StorageContainer::operator[](elemI);
142 
143  if (currRange.overlaps(range, true))
144  {
145  // absorb into the existing (adjacent/overlapping) range
146  currRange.join(range);
147 
148  // might connect with the next following range(s)
149  for (; elemI < this->size()-1; ++elemI)
150  {
151  labelRange& nextRange = StorageContainer::operator[](elemI+1);
152  if (currRange.overlaps(nextRange, true))
153  {
154  currRange.join(nextRange);
155  nextRange.clear();
156  }
157  else
158  {
159  break;
160  }
161  }
162 
163  // done - remove any empty ranges that might have been created
164  purgeEmpty();
165  return true;
166  break;
167  }
168  else if (range < currRange)
169  {
170  insertBefore(elemI, range);
171  return true;
172  break;
173  }
174  }
175 
176 
177  // not found: simply append
178  this->append(range);
179 
180  return true;
181 }
182 
183 
185 {
186  bool status = false;
187  if (range.empty() || this->empty())
188  {
189  return status;
190  }
191 
192  forAll(*this, elemI)
193  {
194  labelRange& currRange = StorageContainer::operator[](elemI);
195 
196  if (range.first() > currRange.first())
197  {
198  if (range.last() < currRange.last())
199  {
200  // removal of range fragments of currRange
201 
202  if (labelRange::debug)
203  {
204  Info<<"Fragment removal ";
205  printRange(Info, range) << " from ";
206  printRange(Info, currRange) << endl;
207  }
208 
209  // left-hand-side fragment: insert before current range
210  label lower = currRange.first();
211  label upper = range.first() - 1;
212 
213  labelRange fragment(lower, upper - lower + 1);
214 
215  // right-hand-side fragment
216  lower = range.last() + 1;
217  upper = currRange.last();
218 
219  currRange = labelRange(lower, upper - lower + 1);
220  status = true;
221  insertBefore(elemI, fragment);
222 
223  if (labelRange::debug)
224  {
225  Info<<"fragment ";
226  printRange(Info, fragment) << endl;
227  Info<<"yields ";
228  printRange(Info, currRange) << endl;
229  }
230 
231  // fragmentation can only affect a single range
232  // thus we are done
233  break;
234  }
235  else if (range.first() <= currRange.last())
236  {
237  // keep left-hand-side, remove right-hand-side
238 
239  if (labelRange::debug)
240  {
241  Info<<"RHS removal ";
242  printRange(Info, range) << " from ";
243  printRange(Info, currRange) << endl;
244  }
245 
246  const label lower = currRange.first();
247  const label upper = range.first() - 1;
248 
249  currRange = labelRange(lower, upper - lower + 1);
250  status = true;
251 
252  if (labelRange::debug)
253  {
254  Info<<"yields ";
255  printRange(Info, currRange) << endl;
256  }
257  }
258  }
259  else if (range.first() <= currRange.first())
260  {
261  if (range.last() >= currRange.first())
262  {
263  // remove left-hand-side, keep right-hand-side
264 
265  if (labelRange::debug)
266  {
267  Info<<"LHS removal ";
268  printRange(Info, range) << " from ";
269  printRange(Info, currRange) << endl;
270  }
271 
272  const label lower = range.last() + 1;
273  const label upper = currRange.last();
274 
275  currRange = labelRange(lower, upper - lower + 1);
276  status = true;
277 
278  if (labelRange::debug)
279  {
280  Info<<"yields ";
281  printRange(Info, currRange) << endl;
282  }
283  }
284  }
285  }
286 
287  purgeEmpty();
288 
289  return status;
290 }
291 
292 
293 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
294 
296 {
297  is >> static_cast<labelRanges::StorageContainer&>(ranges);
298  return is;
299 }
300 
301 
303 {
304  os << static_cast<const labelRanges::StorageContainer&>(ranges);
305  return os;
306 }
307 
308 
309 // ************************************************************************* //
insert
srcOptions insert("case", fileName(rootDirSource/caseDirSource))
setSize
points setSize(newPointi)
Foam::labelRange::join
labelRange join(const labelRange &range) const
Return a joined range, squashing any gaps in between.
Definition: labelRange.C:125
Foam::DynamicList< labelRange >
Foam::labelRanges::labelRanges
labelRanges()
Construct null.
Definition: labelRangesI.H:32
Foam::labelRanges::add
bool add(const labelRange &range)
Add the range to the list.
Definition: labelRanges.C:126
Foam::operator>>
Istream & operator>>(Istream &, directionInfo &)
Definition: directionInfo.C:228
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
labelRanges.H
Foam::stringOps::lower
string lower(const std::string &str)
Return string transformed with std::tolower on each character.
Definition: stringOps.C:1199
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::labelRange::clear
void clear() noexcept
Reset to zero start and zero size.
Definition: labelRangeI.H:208
Foam::labelRange::overlaps
bool overlaps(const labelRange &range, bool touches=false) const
Return true if the ranges overlap.
Definition: labelRange.C:102
Foam::label
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:62
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::labelRanges
A list of labelRange.
Definition: labelRanges.H:61
Foam::stringOps::upper
string upper(const std::string &str)
Return string transformed with std::toupper on each character.
Definition: stringOps.C:1219
Foam::labelRange
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:58
Foam::labelRange::first
label first() const noexcept
The (inclusive) lower value of the range - same as start()
Definition: labelRangeI.H:244
Foam::labelRange::debug
static int debug
Debugging.
Definition: labelRange.H:80
Foam::DynamicList< labelRange >::setSize
void setSize(const label nElem)
Alter addressable list size.
Definition: DynamicListI.H:282
range
scalar range
Definition: LISASMDCalcMethod1.H:12
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::labelRange::last
label last() const noexcept
The (inclusive) upper value of the range - same as max()
Definition: labelRangeI.H:256
Foam::DynamicList< labelRange >::remove
labelRange remove()
Remove and return the last element. Fatal on an empty list.
Definition: DynamicListI.H:651
append
rAUs append(new volScalarField(IOobject::groupName("rAU", phase1.name()), 1.0/(U1Eqn.A()+byDt(max(phase1.residualAlpha() - alpha1, scalar(0)) *rho1))))
ListOps.H
Various functions to operate on Lists.
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::operator<<
Ostream & operator<<(Ostream &, const boundaryPatch &)
Definition: boundaryPatch.C:102