dune-istl  2.2.0
vbvector.hh
Go to the documentation of this file.
1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 6 -*-
2 // vi: set et ts=8 sw=6 sts=6:
3 #ifndef DUNE_VBVECTOR_HH
4 #define DUNE_VBVECTOR_HH
5 
6 #include<cmath>
7 #include<complex>
8 #include<iostream>
9 #include<memory>
10 
11 #include "istlexception.hh"
12 #include "bvector.hh"
13 
18 namespace Dune {
19 
35  template<class B, class A=std::allocator<B> >
37  // this derivation gives us all the blas level 1 and norms
38  // on the large array. However, access operators have to be
39  // overwritten.
40  {
41  public:
42 
43  //===== type definitions and constants
44 
46  typedef typename B::field_type field_type;
47 
49  typedef A allocator_type;
50 
52  typedef typename A::size_type size_type;
53 
59 
63  enum {
65  blocklevel = B::blocklevel+2};
66 
67  // just a shorthand
69 
70 
71  //===== constructors and such
72 
77  {
78  // nothing is known ...
79  nblocks = 0;
80  block = 0;
81  initialized = false;
82  }
83 
88  {
89  // we can allocate the windows now
90  nblocks = _nblocks;
91  if (nblocks>0)
92  {
93  block = windowAllocator_.allocate(nblocks);
94  new (block) window_type[nblocks];
95  }
96  else
97  {
98  nblocks = 0;
99  block = 0;;
100  }
101 
102  // Note: memory in base class still not allocated
103  // the vector not usable
104  initialized = false;
105  }
106 
114  {
115  // and we can allocate the big array in the base class
116  this->n = _nblocks*m;
117  if (this->n>0)
118  {
119  this->p = allocator_.allocate(this->n);
120  new (this->p) B[this->n];
121  }
122  else
123  {
124  this->n = 0;
125  this->p = 0;
126  }
127 
128  // we can allocate the windows now
129  nblocks = _nblocks;
130  if (nblocks>0)
131  {
132  // allocate and construct the windows
133  block = windowAllocator_.allocate(nblocks);
134  new (block) window_type[nblocks];
135 
136  // set the windows into the big array
137  for (size_type i=0; i<nblocks; ++i)
138  block[i].set(m,this->p+(i*m));
139  }
140  else
141  {
142  nblocks = 0;
143  block = 0;;
144  }
145 
146  // and the vector is usable
147  initialized = true;
148  }
149 
152  {
153  // allocate the big array in the base class
154  this->n = a.n;
155  if (this->n>0)
156  {
157  // allocate and construct objects
158  this->p = allocator_.allocate(this->n);
159  new (this->p) B[this->n];
160 
161  // copy data
162  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
163  }
164  else
165  {
166  this->n = 0;
167  this->p = 0;
168  }
169 
170  // we can allocate the windows now
171  nblocks = a.nblocks;
172  if (nblocks>0)
173  {
174  // alloc
175  block = windowAllocator_.allocate(nblocks);
176  new (block) window_type[nblocks];
177 
178  // and we must set the windows
179  block[0].set(a.block[0].getsize(),this->p); // first block
180  for (size_type i=1; i<nblocks; ++i) // and the rest
181  block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
182  }
183  else
184  {
185  nblocks = 0;
186  block = 0;;
187  }
188 
189  // and we have a usable vector
190  initialized = true;
191  }
192 
195  {
196  if (this->n>0) {
197  size_type i=this->n;
198  while (i)
199  this->p[--i].~B();
200  allocator_.deallocate(this->p,this->n);
201  }
202  if (nblocks>0) {
203  size_type i=nblocks;
204  while (i)
205  block[--i].~window_type();
206  windowAllocator_.deallocate(block,nblocks);
207  }
208 
209  }
210 
211 
213  void resize (size_type _nblocks)
214  {
215  // deconstruct objects and deallocate memory if necessary
216  if (this->n>0) {
217  size_type i=this->n;
218  while (i)
219  this->p[--i].~B();
220  allocator_.deallocate(this->p,this->n);
221  }
222  if (nblocks>0) {
223  size_type i=nblocks;
224  while (i)
225  block[--i].~window_type();
226  windowAllocator_.deallocate(block,nblocks);
227  }
228  this->n = 0;
229  this->p = 0;
230 
231  // we can allocate the windows now
232  nblocks = _nblocks;
233  if (nblocks>0)
234  {
235  block = windowAllocator_.allocate(nblocks);
236  new (block) window_type[nblocks];
237  }
238  else
239  {
240  nblocks = 0;
241  block = 0;;
242  }
243 
244  // and the vector not fully usable
245  initialized = false;
246  }
247 
249  void resize (size_type _nblocks, size_type m)
250  {
251  // deconstruct objects and deallocate memory if necessary
252  if (this->n>0) {
253  size_type i=this->n;
254  while (i)
255  this->p[--i].~B();
256  allocator_.deallocate(this->p,this->n);
257  }
258  if (nblocks>0) {
259  size_type i=nblocks;
260  while (i)
261  block[--i].~window_type();
262  windowAllocator_.deallocate(block,nblocks);
263  }
264 
265  // and we can allocate the big array in the base class
266  this->n = _nblocks*m;
267  if (this->n>0)
268  {
269  this->p = allocator_.allocate(this->n);
270  new (this->p) B[this->n];
271  }
272  else
273  {
274  this->n = 0;
275  this->p = 0;
276  }
277 
278  // we can allocate the windows now
279  nblocks = _nblocks;
280  if (nblocks>0)
281  {
282  // allocate and construct objects
283  block = windowAllocator_.allocate(nblocks);
284  new (block) window_type[nblocks];
285 
286  // set the windows into the big array
287  for (size_type i=0; i<nblocks; ++i)
288  block[i].set(m,this->p+(i*m));
289  }
290  else
291  {
292  nblocks = 0;
293  block = 0;;
294  }
295 
296  // and the vector is usable
297  initialized = true;
298  }
299 
302  {
303  if (&a!=this) // check if this and a are different objects
304  {
305  // reallocate arrays if necessary
306  // Note: still the block sizes may vary !
307  if (this->n!=a.n || nblocks!=a.nblocks)
308  {
309  // deconstruct objects and deallocate memory if necessary
310  if (this->n>0) {
311  size_type i=this->n;
312  while (i)
313  this->p[--i].~B();
314  allocator_.deallocate(this->p,this->n);
315  }
316  if (nblocks>0) {
317  size_type i=nblocks;
318  while (i)
319  block[--i].~window_type();
320  windowAllocator_.deallocate(block,nblocks);
321  }
322 
323  // allocate the big array in the base class
324  this->n = a.n;
325  if (this->n>0)
326  {
327  // allocate and construct objects
328  this->p = allocator_.allocate(this->n);
329  new (this->p) B[this->n];
330  }
331  else
332  {
333  this->n = 0;
334  this->p = 0;
335  }
336 
337  // we can allocate the windows now
338  nblocks = a.nblocks;
339  if (nblocks>0)
340  {
341  // alloc
342  block = windowAllocator_.allocate(nblocks);
343  new (block) window_type[nblocks];
344  }
345  else
346  {
347  nblocks = 0;
348  block = 0;;
349  }
350  }
351 
352  // copy block structure, might be different although
353  // sizes are the same !
354  if (nblocks>0)
355  {
356  block[0].set(a.block[0].getsize(),this->p); // first block
357  for (size_type i=1; i<nblocks; ++i) // and the rest
358  block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
359  }
360 
361  // and copy the data
362  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
363  }
364 
365  // and we have a usable vector
366  initialized = true;
367 
368  return *this; // Gebe Referenz zurueck damit a=b=c; klappt
369  }
370 
371 
372  //===== assignment from scalar
373 
376  {
377  (static_cast<block_vector_unmanaged<B,A>&>(*this)) = k;
378  return *this;
379  }
380 
381 
382  //===== the creation interface
383 
386  {
387  public:
389  CreateIterator (VariableBlockVector& _v, int _i) : v(_v)
390  {
391  i = _i;
392  k = 0;
393  n = 0;
394  }
395 
398  {
399  // we are at block i and the blocks size is known
400 
401  // set the blocks size to current k
402  v.block[i].setsize(k);
403 
404  // accumulate total size
405  n += k;
406 
407  // go to next block
408  ++i;
409 
410  // reset block size
411  k = 0;
412 
413  // if we are past the last block, finish off
414  if (i==v.nblocks)
415  {
416  // now we can allocate the big array in the base class of v
417  v.n = n;
418  if (n>0)
419  {
420  // allocate and construct objects
421  v.p = v.allocator_.allocate(n);
422  new (v.p) B[n];
423  }
424  else
425  {
426  v.n = 0;
427  v.p = 0;
428  }
429 
430  // and we set the window pointer
431  if (v.nblocks>0)
432  {
433  v.block[0].setptr(v.p); // pointer tofirst block
434  for (size_type j=1; j<v.nblocks; ++j) // and the rest
435  v.block[j].setptr(v.block[j-1].getptr()+v.block[j-1].getsize());
436  }
437 
438  // and the vector is ready
439  v.initialized = true;
440 
441  //std::cout << "made vbvector with " << v.n << " components" << std::endl;
442  }
443 
444  return *this;
445  }
446 
448  bool operator!= (const CreateIterator& it) const
449  {
450  return (i!=it.i) || (&v!=&it.v);
451  }
452 
454  bool operator== (const CreateIterator& it) const
455  {
456  return (i==it.i) && (&v==&it.v);
457  }
458 
460  size_type index () const
461  {
462  return i;
463  }
464 
467  {
468  k = _k;
469  }
470 
471  private:
472  VariableBlockVector& v; // my vector
473  size_type i; // current block to be defined
474  size_type k; // size of current block to be defined
475  size_type n; // total number of elements to be allocated
476  };
477 
478  // CreateIterator wants to set all the arrays ...
479  friend class CreateIterator;
480 
483  {
484 #ifdef DUNE_ISTL_WITH_CHECKING
485  if (initialized) DUNE_THROW(ISTLError,"no CreateIterator in initialized state");
486 #endif
487  return CreateIterator(*this,0);
488  }
489 
492  {
493  return CreateIterator(*this,nblocks);
494  }
495 
496 
497  //===== access to components
498  // has to be overwritten from base class because it must
499  // return access to the windows
500 
503  {
504 #ifdef DUNE_ISTL_WITH_CHECKING
505  if (i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
506 #endif
507  return block[i];
508  }
509 
512  {
513 #ifdef DUNE_ISTL_WITH_CHECKING
514  if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
515 #endif
516  return block[i];
517  }
518 
519  // forward declaration
520  class ConstIterator;
521 
523  class Iterator
524  {
525  public:
528  {
529  p = 0;
530  i = 0;
531  }
532 
534  Iterator (window_type* _p, size_type _i) : p(_p), i(_i)
535  { }
536 
539  {
540  ++i;
541  return *this;
542  }
543 
546  {
547  --i;
548  return *this;
549  }
550 
552  bool operator== (const Iterator& it) const
553  {
554  return (p+i)==(it.p+it.i);
555  }
556 
558  bool operator!= (const Iterator& it) const
559  {
560  return (p+i)!=(it.p+it.i);
561  }
562 
564  bool operator== (const ConstIterator& it) const
565  {
566  return (p+i)==(it.p+it.i);
567  }
568 
570  bool operator!= (const ConstIterator& it) const
571  {
572  return (p+i)!=(it.p+it.i);
573  }
574 
577  {
578  return p[i];
579  }
580 
583  {
584  return p+i;
585  }
586 
587  // return index corresponding to pointer
588  size_type index () const
589  {
590  return i;
591  }
592 
593  friend class ConstIterator;
594 
595  private:
596  window_type* p;
597  size_type i;
598  };
599 
602  {
603  return Iterator(block,0);
604  }
605 
608  {
609  return Iterator(block,nblocks);
610  }
611 
615  {
616  return Iterator(block,nblocks-1);
617  }
618 
622  {
623  return Iterator(block,-1);
624  }
625 
628  {
629  if (i>=0 && i<nblocks)
630  return Iterator(block,i);
631  else
632  return Iterator(block,nblocks);
633  }
634 
637  {
638  if (i>=0 && i<nblocks)
639  return ConstIterator(block,i);
640  else
641  return ConstIterator(block,nblocks);
642  }
643 
646  {
647  public:
650  {
651  p = 0;
652  i = 0;
653  }
654 
656  ConstIterator (const window_type* _p, size_type _i) : p(_p), i(_i)
657  { }
658 
660  ConstIterator (const Iterator& it) : p(it.p), i(it.i)
661  { }
662 
665  {
666  ++i;
667  return *this;
668  }
669 
672  {
673  --i;
674  return *this;
675  }
676 
678  bool operator== (const ConstIterator& it) const
679  {
680  return (p+i)==(it.p+it.i);
681  }
682 
684  bool operator!= (const ConstIterator& it) const
685  {
686  return (p+i)!=(it.p+it.i);
687  }
688 
690  bool operator== (const Iterator& it) const
691  {
692  return (p+i)==(it.p+it.i);
693  }
694 
696  bool operator!= (const Iterator& it) const
697  {
698  return (p+i)!=(it.p+it.i);
699  }
700 
702  const window_type& operator* () const
703  {
704  return p[i];
705  }
706 
708  const window_type* operator-> () const
709  {
710  return p+i;
711  }
712 
713  // return index corresponding to pointer
714  size_type index () const
715  {
716  return i;
717  }
718 
719  friend class Iterator;
720 
721  private:
722  const window_type* p;
723  size_type i;
724  };
725 
728  {
729  return ConstIterator(block,0);
730  }
731 
734  {
735  return ConstIterator(block,nblocks);
736  }
737 
741  {
742  return ConstIterator(block,nblocks-1);
743  }
744 
747  {
748  return ConstIterator(block,-1);
749  }
750 
751 
752  //===== sizes
753 
755  size_type N () const
756  {
757  return nblocks;
758  }
759 
760 
761  private:
762  size_type nblocks; // number of blocks in vector
763  window_type* block; // array of blocks pointing to the array in the base class
764  bool initialized; // true if vector has been initialized
765 
766  A allocator_;
767 
768  typename A::template rebind<window_type>::other windowAllocator_;
769  };
770 
771 
772 
775 } // end namespace
776 
777 #endif