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