ug4
section_container.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2015: G-CSC, Goethe University Frankfurt
3  * Author: Sebastian Reiter
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __UTIL__SECTION_CONTAINER__IMPL__
34 #define __UTIL__SECTION_CONTAINER__IMPL__
35 
36 #include <cassert>
37 #include "section_container.h"
38 
39 /*
40 I began work on reverse iterators. All associated code is in comments.
41 The method erase has not yet been adjusted.
42 I stopped implementing those reverse-iterators, since they would require quite
43 some additional instructions during element insertion (Each time the rbegin
44 iterator of the current and rend iterator of the next section would
45 have to be adjusted).
46 If reverse iterators are required, one should think about constructing them
47 directly from normal iterators in the rbegin / rend calls. This is done
48 similar in the current implementation of back.
49 */
50 
51 namespace ug
52 {
53 
54 template <class TValue, class TContainer>
56 SectionContainer() : m_numElements(0)
57 {
58 }
59 
60 template <class TValue, class TContainer>
61 void
63 clear()
64 {
65 // clear the container. correct all sections afterwards.
66  m_container.clear();
67  m_numElements = 0;
68  for(typename SectionVec::iterator iter = m_vSections.begin();
69  iter != m_vSections.end(); ++iter)
70  {
71  Section& sec = *iter;
72  sec.m_elemsBegin = sec.m_elemsEnd = m_container.end();
73 // sec.m_elemsRBegin = sec.m_elemsREnd = m_container.rend();
74  sec.m_numElements = 0;
75  }
76 }
77 
78 template <class TValue, class TContainer>
79 void
81 clear_section(int sectionIndex)
82 {
83  assert((sectionIndex >= 0) && (sectionIndex < num_sections()) &&
84  "ERROR in SectionContainer::clear_section(): bad sectionIndex");
85 
86  iterator iterStart = section_begin(sectionIndex);
87  iterator iterEnd = section_end(sectionIndex);
88  if(iterStart != iterEnd)
89  {
90  m_container.erase(iterStart, iterEnd);
91  m_vSections[sectionIndex].m_elemsBegin = m_vSections[sectionIndex].m_elemsEnd;
92 // m_vSections[sectionIndex].m_elemsRBegin = m_vSections[sectionIndex].m_elemsREnd;
93  m_numElements -= m_vSections[sectionIndex].m_numElements;
94  m_vSections[sectionIndex].m_numElements = 0;
95 
96  // iterators of previous sections have to be adjusted
97  for(int i = sectionIndex - 1; i >= 0; --i){
98  if(m_vSections[i].m_numElements > 0){
99  m_vSections[i].m_elemsEnd = m_vSections[sectionIndex].m_elemsBegin;
100  break;// we don't have to correct any more sections
101  }
102  }
103 
104  // same for iterators of following sections
105 // for(int i = sectionIndex + 1; i < num_sections(); ++i){
106 // if(m_vSections[i].m_numElements > 0){
107 // m_vSections[i].m_elemsREnd = m_vSections[sectionIndex].m_elemsRBegin;
108 // break;// we don't have to correct any more sections
109 // }
110 // }
111  }
112 }
113 
114 template <class TValue, class TContainer>
117 section_begin(int sectionIndex)
118 {
119  if(sectionIndex < 0)
120  return m_container.begin();
121  else if(sectionIndex >= num_sections())
122  return m_container.end();
123 
124  return m_vSections[sectionIndex].m_elemsBegin;
125 }
126 
127 template <class TValue, class TContainer>
130 section_begin(int sectionIndex) const
131 {
132  if(sectionIndex < 0)
133  return m_container.begin();
134  else if(sectionIndex >= num_sections())
135  return m_container.end();
136 
137  return m_vSections[sectionIndex].m_elemsBegin;
138 }
139 
140 template <class TValue, class TContainer>
143 section_end(int sectionIndex)
144 {
145  if(sectionIndex >= num_sections() || sectionIndex < 0)
146  return m_container.end();
147 
148  return m_vSections[sectionIndex].m_elemsEnd;
149 }
150 
151 template <class TValue, class TContainer>
154 section_end(int sectionIndex) const
155 {
156  if(sectionIndex >= num_sections() || sectionIndex < 0)
157  return m_container.end();
158 
159  return m_vSections[sectionIndex].m_elemsEnd;
160 }
161 
162 template <class TValue, class TContainer>
165 front(int secIndex)
166 {
167  assert((secIndex >= -1) && (secIndex < num_sections()) && "Bad section index");
168  if(secIndex == -1)
169  return m_container.front();
170  return *m_vSections[secIndex].m_elemsBegin;
171 }
172 
173 template <class TValue, class TContainer>
176 back(int secIndex)
177 {
178  assert((secIndex >= -1) && (secIndex < num_sections()) && "Bad section index");
179  if(secIndex == -1)
180  return m_container.back();
181 
182 // things are a little more complicated here, since there is no rbegin
183 // check whether the last element is the last element of the underlying
184 // container, too. If so, we'll return the last element of this container.
185  if(m_vSections[secIndex].m_elemsEnd == m_container.end())
186  return m_container.back();
187 
188 // since it is not, it points to the element in m_container, which
189 // directly follows the last element of this section.
190 // we'll thus create a reverse iterator on m_elemsEnd, increase it
191 // once, and return the element, to which the iterator now points.
192  iterator titer(m_vSections[secIndex].m_elemsEnd);
193  --titer;
194  return *titer;
195 }
196 
197 template <class TValue, class TContainer>
198 void
200 add_sections(int num)
201 {
202  for(int i = 0; i < num; ++i)
203  m_vSections.push_back(Section(m_container.end(), m_container.end(),
204  //m_container.rend(), m_container.rend(),
205  0));
206 }
207 
208 template <class TValue, class TContainer>
209 uint
211 num_elements(int sectionIndex) const
212 {
213  assert((sectionIndex >= 0) &&
214  "ERROR in SectionContainer::num_elements(): bad sectionIndex");
215 
216  if(sectionIndex >= num_sections())
217  return 0;
218  return m_vSections[sectionIndex].m_numElements;
219 }
220 
221 template <class TValue, class TContainer>
224 insert(const TValue& val, int sectionIndex)
225 {
226  assert((sectionIndex >= 0) &&
227  "ERROR in SectionContainer::insert(): bad sectionIndex");
228 
229  iterator nHandle;
230 
231 // check if a new section has to be created.
232  if(sectionIndex >= num_sections())
233  add_sections(sectionIndex - num_sections() + 1);
234 
235 // if the current section is empty, we have to initialize it.
236  if(num_elements(sectionIndex) == 0)
237  {
238  // it's the first element in this section.
239  // iterate through the sections and find the next one which is not empty
240  int nextValidSection = -1;
241  for(int i = sectionIndex + 1; i < num_sections(); ++i){
242  if(num_elements(i) > 0){
243  nextValidSection = i;
244  break;
245  }
246  }
247 
248  // we have to find the previous valid section, too
249  int prevValidSection = -1;
250  for(int i = sectionIndex - 1; i >= 0; --i){
251  if(num_elements(i) > 0){
252  prevValidSection = i;
253  break;
254  }
255  }
256 
257  // get the iterator before which the element shall be inserted.
258  if(nextValidSection != -1){
259  m_vSections[sectionIndex].m_elemsEnd = m_vSections[nextValidSection].m_elemsBegin;
260  }
261  else
262  m_vSections[sectionIndex].m_elemsEnd = m_container.end();
263 
264  // insert the element
265  nHandle = m_vSections[sectionIndex].m_elemsBegin = m_container.insert(m_vSections[sectionIndex].m_elemsEnd, val);
266  m_vSections[sectionIndex].m_numElements++;
267 // m_vSections[sectionIndex].m_elemsRBegin = reverse_iterator(nHandle);
268 
269  // adjust rend iterator of the next section
270 // if(nextValidSection != -1)
271 // m_vSections[nextValidSection].m_elemsREnd = m_vSections[sectionIndex].m_elemsRBegin;
272 
273  // adjust the end-iterator of the previous valid section.
274  if(prevValidSection != -1){
275  m_vSections[prevValidSection].m_elemsEnd = m_vSections[sectionIndex].m_elemsBegin;
276 // m_vSections[sectionIndex].m_elemsREnd = m_vSections[prevValidSection].m_elemsRBegin;
277  }
278 // else
279 // m_vSections[sectionIndex].m_elemsREnd = m_container.rend();
280  }
281  else
282  {
283  // the section is not empty. Simply insert the element before the sections end-iterator.
284  nHandle = m_container.insert(m_vSections[sectionIndex].m_elemsEnd, val);
285  m_vSections[sectionIndex].m_numElements++;
286  }
287 
288  m_numElements++;
289 
290  return nHandle;
291 }
292 
293 template <class TValue, class TContainer>
294 void
296 erase(const typename ug::SectionContainer<TValue, TContainer>::iterator& elemHandle, int sectionIndex)
297 {
298  assert((sectionIndex >= 0) && (sectionIndex < num_sections()) &&
299  "ERROR in SectionContainer::erase(): bad sectionIndex");
300 
301  iterator hNext;
302 
303 // check if the element is the first in the section.
304 // if this is the case, we have to update the begin-handle of this section
305  if(elemHandle == m_vSections[sectionIndex].m_elemsBegin)
306  {
307  // erase the element
308  hNext = m_container.erase(elemHandle);
309  m_vSections[sectionIndex].m_numElements--;
310 
311  // update the current section and the previous valid one.
312  m_vSections[sectionIndex].m_elemsBegin = hNext;
313 
314  // change begin and end iterators in all preceding empty sections
315  // and end iterator in the preceding non-empty section
316  for (int i = sectionIndex - 1; i >= 0; --i)
317  {
318  if (num_elements(i) <= 0)
319  {
320  m_vSections[i].m_elemsBegin = m_vSections[i].m_elemsEnd = hNext;
321  continue;
322  }
323  m_vSections[i].m_elemsEnd = hNext;
324  break;
325  }
326  }
327  else
328  {
329  // erase the element
330  hNext = m_container.erase(elemHandle);
331  m_vSections[sectionIndex].m_numElements--;
332  }
333 
334  m_numElements--;
335 
336 // check if hNext points to the end of the container. If so we will adjust the
337 // m_elemsEnd iterator of the section.
338 // included for safety reasons. Shouldn't be needed...
339 
340  if(hNext == m_container.end())
341  m_vSections[sectionIndex].m_elemsEnd = m_container.end();
342 }
343 
344 template <class TValue, class TContainer>
345 void
347 append(const SectionContainer& c)
348 {
349  for(int i = 0; i < c.num_sections(); ++i){
350  for(const_iterator iter = c.section_begin(i); iter != c.section_end(i);){
351  const TValue& val = *iter;
352  ++iter;
353  insert(val, i);
354  }
355  }
356 }
357 
358 template <class TValue, class TContainer>
359 void
362 {
363  for(int i = 0; i < c.num_sections(); ++i){
364  for(iterator iter = c.section_begin(i); iter != c.section_end(i);){
365  const TValue& val = *iter;
366  iterator iterOld = iter;
367  ++iter;
368  c.erase(iterOld, i);
369  insert(val, i);
370  }
371  }
372 }
373 
374 }
375 
376 #endif
A special iterator which allows to iterate over elements in a AttachedElementList.
Definition: attached_list.h:52
A container that is divided into different sections.
Definition: section_container.h:59
Container::const_iterator const_iterator
Definition: section_container.h:64
void erase(const iterator &iter, int sectionIndex)
Definition: section_container.hpp:296
iterator section_begin(int sectionIndex)
Definition: section_container.hpp:117
value_type & front(int secIndex=-1)
returns the first entry in the given section.
Definition: section_container.hpp:165
int num_sections() const
Definition: section_container.h:109
void add_sections(int num)
Definition: section_container.hpp:200
void clear_section(int sectionIndex)
Definition: section_container.hpp:81
uint num_elements() const
Definition: section_container.h:108
iterator section_end(int sectionIndex)
Definition: section_container.hpp:143
TValue value_type
Definition: section_container.h:61
value_type & back(int secIndex=-1)
returns the last entry in the given section.
Definition: section_container.hpp:176
void transfer_elements(SectionContainer &c)
takes all elements from the given section container and transfers them to this one.
Definition: section_container.hpp:361
Container::iterator iterator
Definition: section_container.h:63
void append(const SectionContainer &c)
appends the elements of the given container to the current one
Definition: section_container.hpp:347
void clear()
Definition: section_container.hpp:63
iterator insert(const TValue &val, int sectionIndex)
Definition: section_container.hpp:224
SectionContainer()
Definition: section_container.hpp:56
unsigned int uint
Definition: types.h:114
the ug namespace
Definition: section_container.h:133