Dune Core Modules (2.7.1)

vbvector.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_ISTL_VBVECTOR_HH
4#define DUNE_ISTL_VBVECTOR_HH
5
6#include <cmath>
7#include <complex>
8#include <iostream>
9#include <iterator>
10#include <memory>
11
13#include "istlexception.hh"
14#include "bvector.hh"
15
20namespace Dune {
21
37 template<class B, class A=std::allocator<B> >
38 class VariableBlockVector : public Imp::block_vector_unmanaged<B,A>
39 // this derivation gives us all the blas level 1 and norms
40 // on the large array. However, access operators have to be
41 // overwritten.
42 {
43 // just a shorthand
44 typedef Imp::BlockVectorWindow<B,A> window_type;
45
46 public:
47
48 //===== type definitions and constants
49
51 using field_type = typename Imp::BlockTraits<B>::field_type;
52
54 typedef A allocator_type;
55
60 typedef window_type& reference;
61
66 typedef const window_type& const_reference;
67
69 typedef typename A::size_type size_type;
70
77
81
85 static constexpr unsigned int blocklevel = Imp::BlockTraits<B>::blockLevel()+2;
86
87 //===== constructors and such
88
92 VariableBlockVector () : Imp::block_vector_unmanaged<B,A>()
93 {
94 // nothing is known ...
95 nblocks = 0;
96 block = nullptr;
97 initialized = false;
98 }
99
103 explicit VariableBlockVector (size_type _nblocks) : Imp::block_vector_unmanaged<B,A>()
104 {
105 // we can allocate the windows now
106 nblocks = _nblocks;
107 if (nblocks>0)
108 {
109 block = windowAllocator_.allocate(nblocks);
110 new (block) window_type[nblocks];
111 }
112 else
113 {
114 nblocks = 0;
115 block = nullptr;
116 }
117
118 // Note: memory in base class still not allocated
119 // the vector not usable
120 initialized = false;
121 }
122
129 VariableBlockVector (size_type _nblocks, size_type m) : Imp::block_vector_unmanaged<B,A>()
130 {
131 // and we can allocate the big array in the base class
132 this->n = _nblocks*m;
133 if (this->n>0)
134 {
135 this->p = allocator_.allocate(this->n);
136 new (this->p)B[this->n];
137 }
138 else
139 {
140 this->n = 0;
141 this->p = nullptr;
142 }
143
144 // we can allocate the windows now
145 nblocks = _nblocks;
146 if (nblocks>0)
147 {
148 // allocate and construct the windows
149 block = windowAllocator_.allocate(nblocks);
150 new (block) window_type[nblocks];
151
152 // set the windows into the big array
153 for (size_type i=0; i<nblocks; ++i)
154 block[i].set(m,this->p+(i*m));
155 }
156 else
157 {
158 nblocks = 0;
159 block = nullptr;
160 }
161
162 // and the vector is usable
163 initialized = true;
164 }
165
168 {
169 // allocate the big array in the base class
170 this->n = a.n;
171 if (this->n>0)
172 {
173 // allocate and construct objects
174 this->p = allocator_.allocate(this->n);
175 new (this->p)B[this->n];
176
177 // copy data
178 for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
179 }
180 else
181 {
182 this->n = 0;
183 this->p = nullptr;
184 }
185
186 // we can allocate the windows now
187 nblocks = a.nblocks;
188 if (nblocks>0)
189 {
190 // alloc
191 block = windowAllocator_.allocate(nblocks);
192 new (block) window_type[nblocks];
193
194 // and we must set the windows
195 block[0].set(a.block[0].getsize(),this->p); // first block
196 for (size_type i=1; i<nblocks; ++i) // and the rest
197 block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
198 }
199 else
200 {
201 nblocks = 0;
202 block = nullptr;
203 }
204
205 // and we have a usable vector
206 initialized = true;
207 }
208
211 {
212 if (this->n>0) {
213 size_type i=this->n;
214 while (i)
215 this->p[--i].~B();
216 allocator_.deallocate(this->p,this->n);
217 }
218 if (nblocks>0) {
219 size_type i=nblocks;
220 while (i)
221 block[--i].~window_type();
222 windowAllocator_.deallocate(block,nblocks);
223 }
224
225 }
226
227
229 void resize (size_type _nblocks)
230 {
231 // deconstruct objects and deallocate memory if necessary
232 if (this->n>0) {
233 size_type i=this->n;
234 while (i)
235 this->p[--i].~B();
236 allocator_.deallocate(this->p,this->n);
237 }
238 if (nblocks>0) {
239 size_type i=nblocks;
240 while (i)
241 block[--i].~window_type();
242 windowAllocator_.deallocate(block,nblocks);
243 }
244 this->n = 0;
245 this->p = nullptr;
246
247 // we can allocate the windows now
248 nblocks = _nblocks;
249 if (nblocks>0)
250 {
251 block = windowAllocator_.allocate(nblocks);
252 new (block) window_type[nblocks];
253 }
254 else
255 {
256 nblocks = 0;
257 block = nullptr;
258 }
259
260 // and the vector not fully usable
261 initialized = false;
262 }
263
265 void resize (size_type _nblocks, size_type m)
266 {
267 // deconstruct objects and deallocate memory if necessary
268 if (this->n>0) {
269 size_type i=this->n;
270 while (i)
271 this->p[--i].~B();
272 allocator_.deallocate(this->p,this->n);
273 }
274 if (nblocks>0) {
275 size_type i=nblocks;
276 while (i)
277 block[--i].~window_type();
278 windowAllocator_.deallocate(block,nblocks);
279 }
280
281 // and we can allocate the big array in the base class
282 this->n = _nblocks*m;
283 if (this->n>0)
284 {
285 this->p = allocator_.allocate(this->n);
286 new (this->p)B[this->n];
287 }
288 else
289 {
290 this->n = 0;
291 this->p = nullptr;
292 }
293
294 // we can allocate the windows now
295 nblocks = _nblocks;
296 if (nblocks>0)
297 {
298 // allocate and construct objects
299 block = windowAllocator_.allocate(nblocks);
300 new (block) window_type[nblocks];
301
302 // set the windows into the big array
303 for (size_type i=0; i<nblocks; ++i)
304 block[i].set(m,this->p+(i*m));
305 }
306 else
307 {
308 nblocks = 0;
309 block = nullptr;
310 }
311
312 // and the vector is usable
313 initialized = true;
314 }
315
318 {
319 if (&a!=this) // check if this and a are different objects
320 {
321 // reallocate arrays if necessary
322 // Note: still the block sizes may vary !
323 if (this->n!=a.n || nblocks!=a.nblocks)
324 {
325 // deconstruct objects and deallocate memory if necessary
326 if (this->n>0) {
327 size_type i=this->n;
328 while (i)
329 this->p[--i].~B();
330 allocator_.deallocate(this->p,this->n);
331 }
332 if (nblocks>0) {
333 size_type i=nblocks;
334 while (i)
335 block[--i].~window_type();
336 windowAllocator_.deallocate(block,nblocks);
337 }
338
339 // allocate the big array in the base class
340 this->n = a.n;
341 if (this->n>0)
342 {
343 // allocate and construct objects
344 this->p = allocator_.allocate(this->n);
345 new (this->p)B[this->n];
346 }
347 else
348 {
349 this->n = 0;
350 this->p = nullptr;
351 }
352
353 // we can allocate the windows now
354 nblocks = a.nblocks;
355 if (nblocks>0)
356 {
357 // alloc
358 block = windowAllocator_.allocate(nblocks);
359 new (block) window_type[nblocks];
360 }
361 else
362 {
363 nblocks = 0;
364 block = nullptr;
365 }
366 }
367
368 // copy block structure, might be different although
369 // sizes are the same !
370 if (nblocks>0)
371 {
372 block[0].set(a.block[0].getsize(),this->p); // first block
373 for (size_type i=1; i<nblocks; ++i) // and the rest
374 block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
375 }
376
377 // and copy the data
378 for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
379 }
380
381 // and we have a usable vector
382 initialized = true;
383
384 return *this; // Gebe Referenz zurueck damit a=b=c; klappt
385 }
386
387
388 //===== assignment from scalar
389
392 {
393 (static_cast<Imp::block_vector_unmanaged<B,A>&>(*this)) = k;
394 return *this;
395 }
396
397
398 //===== the creation interface
399
400 class CreateIterator;
401
402#ifndef DOXYGEN
403
404 // The window_type does not hand out a reference to its size,
405 // so in order to provide a valid iterator, we need a workaround
406 // to make assignment possible. This proxy enables just that by
407 // implicitly converting to the stored size for read access and
408 // tunneling assignment to the accessor method of the window.
409 struct SizeProxy
410 {
411
412 operator size_type() const
413 {
414 return target->getsize();
415 }
416
417 SizeProxy& operator=(size_type size)
418 {
419 target->setsize(size);
420 return *this;
421 }
422
423 private:
424
425 friend class CreateIterator;
426
427 SizeProxy(window_type& t)
428 : target(&t)
429 {}
430
431 window_type* target;
432 };
433
434#endif // DOXYGEN
435
438 {
439 public:
441 using iterator_category = std::output_iterator_tag;
442
445
452 using difference_type = void;
453
456
458 using reference = SizeProxy;
459
461 CreateIterator (VariableBlockVector& _v, int _i, bool _isEnd) :
462 v(_v),
463 i(_i),
464 isEnd(_isEnd) {}
465
467 // When the iterator gets destructed, we allocate the memory
468 // for the VariableBlockVector if
469 // 1. the current iterator was not created as enditerator
470 // 2. we're at the last block
471 // 3. the vector hasn't been initialized earlier
472 if (not isEnd && i==v.nblocks && not v.initialized)
473 v.allocate();
474 }
475
478 {
479 // go to next block
480 ++i;
481
482 return *this;
483 }
484
487 {
488 CreateIterator tmp(*this);
489 this->operator++();
490 return tmp;
491 }
492
494 bool operator!= (const CreateIterator& it) const
495 {
496 return (i!=it.i) || (&v!=&it.v);
497 }
498
500 bool operator== (const CreateIterator& it) const
501 {
502 return (i==it.i) && (&v==&it.v);
503 }
504
507 {
508 return i;
509 }
510
513 {
514 v.block[i].setsize(_k);
515 }
516
518#ifdef DOXYGEN
519 size_type&
520#else
521 SizeProxy
522#endif
524 {
525 return {v.block[i]};
526 }
527
528 private:
529 VariableBlockVector& v; // my vector
530 size_type i; // current block to be defined
531 const bool isEnd; // flag if this object was created as the end iterator.
532 };
533
534 // CreateIterator wants to set all the arrays ...
535 friend class CreateIterator;
536
539 {
540#ifdef DUNE_ISTL_WITH_CHECKING
541 if (initialized) DUNE_THROW(ISTLError,"no CreateIterator in initialized state");
542#endif
543 return CreateIterator(*this,0, false);
544 }
545
548 {
549 return CreateIterator(*this,nblocks, true);
550 }
551
552
553 //===== access to components
554 // has to be overwritten from base class because it must
555 // return access to the windows
556
558 window_type& operator[] (size_type i)
559 {
560#ifdef DUNE_ISTL_WITH_CHECKING
561 if (i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
562#endif
563 return block[i];
564 }
565
567 const window_type& operator[] (size_type i) const
568 {
569#ifdef DUNE_ISTL_WITH_CHECKING
570 if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
571#endif
572 return block[i];
573 }
574
576 template <class T, class R>
578 : public RandomAccessIteratorFacade<RealIterator<T,R>, T, R>
579 {
580 public:
583 {
584 p = nullptr;
585 i = 0;
586 }
587
589 RealIterator (window_type* _p, size_type _i)
590 : p(_p), i(_i)
591 {}
592
595 {
596 ++i;
597 }
598
601 {
602 --i;
603 }
604
606 bool equals (const RealIterator& it) const
607 {
608 return (p+i)==(it.p+it.i);
609 }
610
612 window_type& dereference () const
613 {
614 return p[i];
615 }
616
617 void advance(std::ptrdiff_t d)
618 {
619 i+=d;
620 }
621
622 std::ptrdiff_t distanceTo(const RealIterator& o) const
623 {
624 return o.i-i;
625 }
626
627 // Needed for operator[] of the iterator
628 window_type& elementAt (std::ptrdiff_t offset) const
629 {
630 return p[i+offset];
631 }
632
635 {
636 return i;
637 }
638
639 private:
640 window_type* p;
641 size_type i;
642 };
643
644 using Iterator = RealIterator<value_type,window_type&>;
645
648 {
649 return Iterator(block,0);
650 }
651
654 {
655 return Iterator(block,nblocks);
656 }
657
661 {
662 return Iterator(block,nblocks-1);
663 }
664
668 {
669 return Iterator(block,-1);
670 }
671
674
677
680
683 {
684 return ConstIterator(block,0);
685 }
686
689 {
690 return ConstIterator(block,nblocks);
691 }
692
696 {
697 return ConstIterator(block,nblocks-1);
698 }
699
702 {
703 return ConstIterator(block,-1);
704 }
705
708 {
709 return Iterator(block,std::min(i,nblocks));
710 }
711
714 {
715 return ConstIterator(block,std::min(i,nblocks));
716 }
717
718 //===== sizes
719
721 size_type N () const
722 {
723 return nblocks;
724 }
725
731 {
732 return nblocks;
733 }
734
735
736 private:
737
738 void allocate() {
739 if (this->initialized)
740 DUNE_THROW(ISTLError, "Attempt to re-allocate already initialized VariableBlockVector");
741
742 // calculate space needed:
743 this->n=0;
744 for(size_type i = 0; i < nblocks; i++) {
745 this->n += block[i].size();
746 }
747
748 // now we can allocate the big array in the base class of v
749 if (this->n>0)
750 {
751 // allocate and construct objects
752 this->p = allocator_.allocate(this->n);
753 new (this->p)B[this->n];
754 }
755 else
756 {
757 this->p = nullptr;
758 }
759
760 // and we set the window pointers
761 this->block[0].setptr(this->p); // pointer to first block
762 for (size_type j=1; j<nblocks; ++j) // and the rest
763 block[j].setptr(block[j-1].getptr()+block[j-1].getsize());
764
765 // and the vector is ready
766 this->initialized = true;
767 }
768
769 size_type nblocks; // number of blocks in vector
770 window_type* block; // array of blocks pointing to the array in the base class
771 bool initialized; // true if vector has been initialized
772
773 A allocator_;
774
775 typename std::allocator_traits<A>::template rebind_alloc<window_type> windowAllocator_;
776 };
777
778
779
782} // end namespace
783
784#endif
This file implements a vector space as a tensor product of a given vector space. The number of compon...
A vector of blocks with memory management.
Definition: bvector.hh:403
derive error class from the base class in common
Definition: istlexception.hh:16
Base class for stl conformant forward iterators.
Definition: iteratorfacades.hh:432
Iterator class for sequential creation of blocks.
Definition: vbvector.hh:438
bool operator==(const CreateIterator &it) const
equality
Definition: vbvector.hh:500
size_type index() const
dereferencing
Definition: vbvector.hh:506
SizeProxy reference
reference type
Definition: vbvector.hh:458
size_type * pointer
pointer type
Definition: vbvector.hh:455
bool operator!=(const CreateIterator &it) const
inequality
Definition: vbvector.hh:494
size_type value_type
value type
Definition: vbvector.hh:444
CreateIterator(VariableBlockVector &_v, int _i, bool _isEnd)
constructor
Definition: vbvector.hh:461
void setblocksize(size_type _k)
set size of current block
Definition: vbvector.hh:512
size_type & operator*()
Access size of current block.
Definition: vbvector.hh:523
std::output_iterator_tag iterator_category
iterator category
Definition: vbvector.hh:441
CreateIterator & operator++()
prefix increment
Definition: vbvector.hh:477
void difference_type
difference type (unused)
Definition: vbvector.hh:452
Iterator class for sequential access.
Definition: vbvector.hh:579
RealIterator(window_type *_p, size_type _i)
constructor
Definition: vbvector.hh:589
bool equals(const RealIterator &it) const
equality
Definition: vbvector.hh:606
size_type index() const
Return the index of the entry this iterator is pointing to.
Definition: vbvector.hh:634
void decrement()
prefix decrement
Definition: vbvector.hh:600
void increment()
prefix increment
Definition: vbvector.hh:594
RealIterator()
constructor, no arguments
Definition: vbvector.hh:582
window_type & dereference() const
dereferencing
Definition: vbvector.hh:612
A Vector of blocks with different blocksizes.
Definition: vbvector.hh:42
VariableBlockVector()
Definition: vbvector.hh:92
typename Imp::BlockTraits< B >::field_type field_type
export the type representing the field
Definition: vbvector.hh:51
A allocator_type
export the allocator type
Definition: vbvector.hh:54
VariableBlockVector(size_type _nblocks, size_type m)
Definition: vbvector.hh:129
size_type size() const
Definition: vbvector.hh:730
static constexpr unsigned int blocklevel
Definition: vbvector.hh:85
size_type N() const
number of blocks in the vector (are of variable size here)
Definition: vbvector.hh:721
VariableBlockVector(const VariableBlockVector &a)
copy constructor, has copy semantics
Definition: vbvector.hh:167
VariableBlockVector(size_type _nblocks)
Definition: vbvector.hh:103
~VariableBlockVector()
free dynamic memory
Definition: vbvector.hh:210
window_type & operator[](size_type i)
random access to blocks
Definition: vbvector.hh:558
CreateIterator createend()
get create iterator pointing to one after the last block
Definition: vbvector.hh:547
Iterator beforeBegin() const
Definition: vbvector.hh:667
CreateIterator createbegin()
get initial create iterator
Definition: vbvector.hh:538
VariableBlockVector & operator=(const VariableBlockVector &a)
assignment
Definition: vbvector.hh:317
ConstIterator rend() const
end ConstIterator
Definition: vbvector.hh:701
A::size_type size_type
The size type for the index access.
Definition: vbvector.hh:69
ConstIterator find(size_type i) const
random access returning iterator (end if not contained)
Definition: vbvector.hh:713
ConstIterator beforeEnd() const
Definition: vbvector.hh:695
Iterator find(size_type i)
random access returning iterator (end if not contained)
Definition: vbvector.hh:707
const window_type & const_reference
Export type used for const references to container entries.
Definition: vbvector.hh:66
RealIterator< const value_type, const window_type & > ConstIterator
Const iterator.
Definition: vbvector.hh:676
Iterator end()
end Iterator
Definition: vbvector.hh:653
ConstIterator begin() const
begin ConstIterator
Definition: vbvector.hh:682
BlockVector< B, A > value_type
Type of the elements of the outer vector, i.e., dynamic vectors of B.
Definition: vbvector.hh:76
ConstIterator end() const
end ConstIterator
Definition: vbvector.hh:688
BlockVector< B, A > block_type
Same as value_type, here for historical reasons.
Definition: vbvector.hh:80
void resize(size_type _nblocks, size_type m)
same effect as constructor with same argument
Definition: vbvector.hh:265
window_type & reference
Export type used for references to container entries.
Definition: vbvector.hh:60
void resize(size_type _nblocks)
same effect as constructor with same argument
Definition: vbvector.hh:229
Iterator beforeEnd()
Definition: vbvector.hh:660
Iterator begin()
begin Iterator
Definition: vbvector.hh:647
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:87
This file implements iterator facade classes for writing stl conformant iterators.
Dune namespace.
Definition: alignedallocator.hh:14
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 12, 23:30, 2024)