Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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/*
40I began work on reverse iterators. All associated code is in comments.
41The method erase has not yet been adjusted.
42I stopped implementing those reverse-iterators, since they would require quite
43some additional instructions during element insertion (Each time the rbegin
44iterator of the current and rend iterator of the next section would
45have to be adjusted).
46If reverse iterators are required, one should think about constructing them
47directly from normal iterators in the rbegin / rend calls. This is done
48similar in the current implementation of back.
49*/
50
51namespace ug
52{
53
54template <class TValue, class TContainer>
59
60template <class TValue, class TContainer>
61void
63clear()
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
78template <class TValue, class TContainer>
79void
81clear_section(int sectionIndex)
82{
83 assert((sectionIndex >= 0) && (sectionIndex < num_sections()) &&
84 "ERROR in SectionContainer::clear_section(): bad sectionIndex");
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
114template <class TValue, class TContainer>
117section_begin(int sectionIndex)
118{
119 if(sectionIndex < 0)
120 return m_container.begin();
121 else if(sectionIndex >= num_sections())
122 return m_container.end();
124 return m_vSections[sectionIndex].m_elemsBegin;
125}
127template <class TValue, class TContainer>
130section_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
140template <class TValue, class TContainer>
143section_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
151template <class TValue, class TContainer>
154section_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
162template <class TValue, class TContainer>
165front(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
173template <class TValue, class TContainer>
176back(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
197template <class TValue, class TContainer>
198void
200add_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
208template <class TValue, class TContainer>
209uint
211num_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
221template <class TValue, class TContainer>
224insert(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
293template <class TValue, class TContainer>
294void
296erase(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
344template <class TValue, class TContainer>
345void
347append(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
358template <class TValue, class TContainer>
359void
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 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