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