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 | Copyright (C) 2011-2017 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 "labelRanges.H"
27 #include "ListOps.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 const Foam::labelRanges Foam::labelRanges::endLabelRanges_;
32 const Foam::labelRanges::const_iterator Foam::labelRanges::endIter_;
33 
34 
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 
37 void Foam::labelRanges::insertBefore
38 (
39  const label insert,
40  const labelRange& range
41 )
42 {
43  // insert via copying up
44  label nElem = this->size();
45 
47  {
48  Info<<"before insert "
49  << nElem << " elements, insert at " << insert << nl
50  << *this << endl;
51  }
52 
53  ParentType::setSize(nElem+1);
54 
56  {
57  Info<<"copy between " << nElem << " and " << insert << nl;
58  }
59 
60  for (label i = nElem-1; i >= insert; --i)
61  {
63  {
64  Info<<"copy from " << (i) << " to " << (i+1) << nl;
65  }
66 
68  }
69 
70  // finally insert the range
72  {
73  Info<< "finally insert the range at " << insert << nl;
74  }
75  ParentType::operator[](insert) = range;
76 }
77 
78 
79 void Foam::labelRanges::purgeEmpty()
80 {
81  // purge empty ranges by copying down
82  label nElem = 0;
83  forAll(*this, elemI)
84  {
85  if (!ParentType::operator[](elemI).empty())
86  {
87  if (nElem != elemI)
88  {
90  }
91  ++nElem;
92  }
93  }
94 
95  // truncate
96  this->ParentType::setSize(nElem);
97 }
98 
99 
100 Foam::Ostream& Foam::labelRanges::printRange
101 (
102  Ostream& os,
103  const labelRange& range
104 ) const
105 {
106  if (range.empty())
107  {
108  os << "empty";
109  }
110  else
111  {
112  os << range << " = " << range.first() << ":" << range.last();
113  }
114  return os;
115 }
116 
117 
118 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
119 
121 {
122  is >> *this;
123 }
124 
125 
126 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
127 
129 {
130  if (range.empty())
131  {
132  return false;
133  }
134  else if (this->empty())
135  {
136  this->append(range);
137  return true;
138  }
139 
140  // find the correct place for insertion
141  forAll(*this, elemI)
142  {
143  labelRange& currRange = ParentType::operator[](elemI);
144 
145  if (currRange.intersects(range, true))
146  {
147  // absorb into the existing (adjacent/overlapping) range
148  currRange += range;
149 
150  // might connect with the next following range(s)
151  for (; elemI < this->size()-1; ++elemI)
152  {
153  labelRange& nextRange = ParentType::operator[](elemI+1);
154  if (currRange.intersects(nextRange, true))
155  {
156  currRange += nextRange;
157  nextRange.clear();
158  }
159  else
160  {
161  break;
162  }
163  }
164 
165  // done - remove any empty ranges that might have been created
166  purgeEmpty();
167  return true;
168  break;
169  }
170  else if (range < currRange)
171  {
172  insertBefore(elemI, range);
173  return true;
174  break;
175  }
176  }
177 
178 
179  // not found: simply append
180  this->append(range);
181 
182  return true;
183 }
184 
185 
187 {
188  bool status = false;
189  if (range.empty() || this->empty())
190  {
191  return status;
192  }
193 
194  forAll(*this, elemI)
195  {
196  labelRange& currRange = ParentType::operator[](elemI);
197 
198  if (range.first() > currRange.first())
199  {
200  if (range.last() < currRange.last())
201  {
202  // removal of range fragments of currRange
203 
204  if (labelRange::debug)
205  {
206  Info<<"Fragment removal ";
207  printRange(Info, range) << " from ";
208  printRange(Info, currRange) << endl;
209  }
210 
211  // left-hand-side fragment: insert before current range
212  label lower = currRange.first();
213  label upper = range.first() - 1;
214 
215  labelRange fragment(lower, upper - lower + 1);
216 
217  // right-hand-side fragment
218  lower = range.last() + 1;
219  upper = currRange.last();
220 
221  currRange = labelRange(lower, upper - lower + 1);
222  status = true;
223  insertBefore(elemI, fragment);
224 
225  if (labelRange::debug)
226  {
227  Info<<"fragment ";
228  printRange(Info, fragment) << endl;
229  Info<<"yields ";
230  printRange(Info, currRange) << endl;
231  }
232 
233  // fragmentation can only affect a single range
234  // thus we are done
235  break;
236  }
237  else if (range.first() <= currRange.last())
238  {
239  // keep left-hand-side, remove right-hand-side
240 
241  if (labelRange::debug)
242  {
243  Info<<"RHS removal ";
244  printRange(Info, range) << " from ";
245  printRange(Info, currRange) << endl;
246  }
247 
248  const label lower = currRange.first();
249  const label upper = range.first() - 1;
250 
251  currRange = labelRange(lower, upper - lower + 1);
252  status = true;
253 
254  if (labelRange::debug)
255  {
256  Info<<"yields ";
257  printRange(Info, currRange) << endl;
258  }
259  }
260  }
261  else if (range.first() <= currRange.first())
262  {
263  if (range.last() >= currRange.first())
264  {
265  // remove left-hand-side, keep right-hand-side
266 
267  if (labelRange::debug)
268  {
269  Info<<"LHS removal ";
270  printRange(Info, range) << " from ";
271  printRange(Info, currRange) << endl;
272  }
273 
274  const label lower = range.last() + 1;
275  const label upper = currRange.last();
276 
277  currRange = labelRange(lower, upper - lower + 1);
278  status = true;
279 
280  if (labelRange::debug)
281  {
282  Info<<"yields ";
283  printRange(Info, currRange) << endl;
284  }
285  }
286  }
287  }
288 
289  purgeEmpty();
290 
291  return status;
292 }
293 
294 
295 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
296 
298 {
299  is >> static_cast<labelRanges::ParentType&>(ranges);
300  return is;
301 }
302 
303 
305 {
306  os << static_cast<const labelRanges::ParentType&>(ranges);
307  return os;
308 }
309 
310 
311 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:313
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
T & operator[](const label)
Return element of UList.
Definition: UListI.H:167
bool empty() const
Is the range empty?
Definition: labelRangeI.H:149
A label range specifier.
Definition: labelRange.H:57
void clear()
Reset to zero size.
Definition: labelRangeI.H:143
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
labelRanges()
Construct null.
Definition: labelRangesI.H:29
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static int debug
Definition: labelRange.H:66
scalar range
bool add(const labelRange &)
Add the range to the list.
Definition: labelRanges.C:128
Various functions to operate on Lists.
void setSize(const label)
Alter the addressed list size.
Definition: DynamicListI.H:163
Istream & operator>>(Istream &, directionInfo &)
timeIndices insert(timeIndex, timeDirs[timeI].value())
DynamicList< labelRange, 0, 2, 1 > & append(const labelRange &)
Append an element at the end of the list.
Definition: DynamicListI.H:292
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
static const char nl
Definition: Ostream.H:262
label last() const
The (inclusive) upper value of the range.
Definition: labelRangeI.H:167
labelRange remove()
Remove and return the top element.
Definition: DynamicListI.H:347
Ostream & operator<<(Ostream &, const ensightPart &)
messageStream Info
A list of labelRange.
Definition: labelRanges.H:58
label size() const
Return the number of elements in the UList.
Definition: ListI.H:170
bool intersects(const labelRange &, const bool touches=false) const
Return true if the ranges intersect.
Definition: labelRange.C:51
friend Ostream & operator(Ostream &, const DynamicList< labelRange, 0, 2, 1 > &)
label first() const
The (inclusive) lower value of the range.
Definition: labelRangeI.H:161
An STL const_iterator.
Definition: labelRanges.H:113