dune-istl  2.2.1
bvector.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 
4 #ifndef DUNE_BVECTOR_HH
5 #define DUNE_BVECTOR_HH
6 
7 #include<cmath>
8 #include<complex>
9 #include<memory>
10 
11 #include "istlexception.hh"
12 #include "basearray.hh"
13 
21 namespace Dune {
22 
23 
35  template<class B, class A=std::allocator<B> >
37  {
38  public:
39 
40  //===== type definitions and constants
41 
43  typedef typename B::field_type field_type;
44 
46  typedef B block_type;
47 
49  typedef A allocator_type;
50 
52  typedef typename A::size_type size_type;
53 
56 
59 
61  typedef B value_type;
62 
63  //===== assignment from scalar
65 
67  {
68  for (size_type i=0; i<this->n; i++)
69  (*this)[i] = k;
70  return *this;
71  }
72 
73  //===== vector space arithmetic
76  {
77 #ifdef DUNE_ISTL_WITH_CHECKING
78  if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
79 #endif
80  for (size_type i=0; i<this->n; ++i) (*this)[i] += y[i];
81  return *this;
82  }
83 
86  {
87 #ifdef DUNE_ISTL_WITH_CHECKING
88  if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
89 #endif
90  for (size_type i=0; i<this->n; ++i) (*this)[i] -= y[i];
91  return *this;
92  }
93 
96  {
97  for (size_type i=0; i<this->n; ++i) (*this)[i] *= k;
98  return *this;
99  }
100 
103  {
104  for (size_type i=0; i<this->n; ++i) (*this)[i] /= k;
105  return *this;
106  }
107 
110  {
111 #ifdef DUNE_ISTL_WITH_CHECKING
112  if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
113 #endif
114  for (size_type i=0; i<this->n; ++i) (*this)[i].axpy(a,y[i]);
115  return *this;
116  }
117 
118 
119  //===== Euclidean scalar product
120 
123  {
124 #ifdef DUNE_ISTL_WITH_CHECKING
125  if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
126 #endif
127  field_type sum=0;
128  for (size_type i=0; i<this->n; ++i) sum += (*this)[i]*y[i];
129  return sum;
130  }
131 
132 
133  //===== norms
134 
136  double one_norm () const
137  {
138  double sum=0;
139  for (size_type i=0; i<this->n; ++i) sum += (*this)[i].one_norm();
140  return sum;
141  }
142 
144  double one_norm_real () const
145  {
146  double sum=0;
147  for (size_type i=0; i<this->n; ++i) sum += (*this)[i].one_norm_real();
148  return sum;
149  }
150 
152  double two_norm () const
153  {
154  double sum=0;
155  for (size_type i=0; i<this->n; ++i) sum += (*this)[i].two_norm2();
156  return sqrt(sum);
157  }
158 
160  double two_norm2 () const
161  {
162  double sum=0;
163  for (size_type i=0; i<this->n; ++i) sum += (*this)[i].two_norm2();
164  return sum;
165  }
166 
168  double infinity_norm () const
169  {
170  double max=0;
171  for (size_type i=0; i<this->n; ++i) max = std::max(max,(*this)[i].infinity_norm());
172  return max;
173  }
174 
176  double infinity_norm_real () const
177  {
178  double max=0;
179  for (size_type i=0; i<this->n; ++i) max = std::max(max,(*this)[i].infinity_norm_real());
180  return max;
181  }
182 
183  //===== sizes
184 
186  size_type N () const
187  {
188  return this->n;
189  }
190 
192  size_type dim () const
193  {
194  size_type d=0;
195  for (size_type i=0; i<this->n; i++)
196  d += (*this)[i].dim();
197  return d;
198  }
199 
200  protected:
203  { }
204  };
205 
221  template<class B, class A=std::allocator<B> >
223  {
224  public:
225 
226  //===== type definitions and constants
227 
229  typedef typename B::field_type field_type;
230 
232  typedef B block_type;
233 
235  typedef A allocator_type;
236 
238  typedef typename A::size_type size_type;
239 
241  enum {
243  blocklevel = B::blocklevel+1};
244 
247 
250 
251  //===== constructors and such
252 
255  capacity_(0)
256  {}
257 
259  explicit BlockVector (size_type _n)
260  {
261  this->n = _n;
262  capacity_ = _n;
263  if (capacity_>0) {
264  this->p = this->allocator_.allocate(capacity_);
265  // actually construct the objects
266  new(this->p) B[capacity_];
267  } else
268  {
269  this->p = 0;
270  this->n = 0;
271  capacity_ = 0;
272  }
273  }
274 
287  {
288  this->n = _n;
289  if(this->n > capacity)
290  capacity_ = _n;
291  else
293 
294  if (capacity_>0) {
295  this->p = this->allocator_.allocate(capacity_);
296  new (this->p) B[capacity_];
297  } else
298  {
299  this->p = 0;
300  this->n = 0;
301  capacity_ = 0;
302  }
303  }
304 
305 
322  void reserve(size_type capacity, bool copyOldValues=true)
323  {
324  if(capacity >= block_vector_unmanaged<B,A>::N() && capacity != capacity_){
325  // save the old data
326  B* pold = this->p;
327 
328  if(capacity>0){
329  // create new array with capacity
330  this->p = this->allocator_.allocate(capacity);
331  new (this->p) B[capacity];
332 
333  if(copyOldValues){
334  // copy the old values
335  B* to = this->p;
336  B* from = pold;
337 
338  for(size_type i=0; i < block_vector_unmanaged<B,A>::N(); ++i, ++from, ++to)
339  *to = *from;
340 
341  if(capacity_ > 0) {
342  // Destruct old objects and free memory
343  int i=capacity_;
344  while (i)
345  pold[--i].~B();
346  this->allocator_.deallocate(pold,capacity_);
347  }
348  }
349  }else{
350  if(capacity_ > 0)
351  // free old data
352  this->p = 0;
353  capacity_ = 0;
354  }
355 
357  }
358  }
359 
367  {
368  return capacity_;
369  }
370 
385  void resize(size_type size, bool copyOldValues=true)
386  {
387  if(size > block_vector_unmanaged<B,A>::N())
388  if(capacity_ < size)
389  this->reserve(size, copyOldValues);
390 
391  if(size >=0)
392  this->n=size;
393  }
394 
395 
396 
397 
401  {
402  // allocate memory with same size as a
403  this->n = a.n;
404  capacity_ = a.capacity_;
405 
406  if (capacity_>0) {
407  this->p = this->allocator_.allocate(capacity_);
408  new (this->p) B[capacity_];
409  } else
410  {
411  this->n = 0;
412  this->p = 0;
413  }
414 
415  // and copy elements
416  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
417  }
418 
421  {
422  // upcast, because protected data inaccessible
423  const BlockVector& a = static_cast<const BlockVector&>(_a);
424 
425  // allocate memory with same size as a
426  this->n = a.n;
427  capacity_ = a.capacity_;
428 
429  if (capacity_>0) {
430  this->p = this->allocator_.allocate(capacity_);
431  new (this->p) B[capacity_];
432  } else
433  {
434  this->n = 0;
435  this->p = 0;
436  capacity_ = 0;
437  }
438 
439  // and copy elements
440  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
441  }
442 
445  {
446  if (capacity_>0) {
447  int i=capacity_;
448  while (i)
449  this->p[--i].~B();
450  this->allocator_.deallocate(this->p,capacity_);
451  }
452  }
453 
456  {
457  if (&a!=this) // check if this and a are different objects
458  {
459  // adjust size of vector
460  if (capacity_!=a.capacity_) // check if size is different
461  {
462  if (capacity_>0) {
463  int i=capacity_;
464  while (i)
465  this->p[--i].~B();
466  this->allocator_.deallocate(this->p,capacity_); // free old memory
467  }
468  capacity_ = a.capacity_;
469  if (capacity_>0) {
470  this->p = this->allocator_.allocate(capacity_);
471  new (this->p) B[capacity_];
472  } else
473  {
474  this->p = 0;
475  capacity_ = 0;
476  }
477  }
478  this->n = a.n;
479  // copy data
480  for (size_type i=0; i<this->n; i++)
481  this->p[i]=a.p[i];
482  }
483  return *this;
484  }
485 
488  {
489  // forward to regular assignement operator
490  return this->operator=(static_cast<const BlockVector&>(a));
491  }
492 
495  {
496  // forward to operator= in base class
497  (static_cast<block_vector_unmanaged<B,A>&>(*this)) = k;
498  return *this;
499  }
500  protected:
502 
504 
505  };
506 
508 
509  template<class K, class A>
510  std::ostream& operator<< (std::ostream& s, const BlockVector<K, A>& v)
511  {
512  typedef typename BlockVector<K, A>::size_type size_type;
513 
514  for (size_type i=0; i<v.size(); i++)
515  s << v[i] << std::endl;
516 
517  return s;
518  }
519 
536  template<class B, class A=std::allocator<B> >
538  {
539  public:
540 
541  //===== type definitions and constants
542 
544  typedef typename B::field_type field_type;
545 
547  typedef B block_type;
548 
550  typedef A allocator_type;
551 
553  typedef typename A::size_type size_type;
554 
556  enum {
558  blocklevel = B::blocklevel+1
559  };
560 
563 
566 
567 
568  //===== constructors and such
571  { }
572 
575  {
576  this->n = _n;
577  this->p = _p;
578  }
579 
582  {
583  this->n = a.n;
584  this->p = a.p;
585  }
586 
589  {
590  // cast needed to access protected data
591  const BlockVectorWindow& a = static_cast<const BlockVectorWindow&>(_a);
592 
593  // make me point to the other's data
594  this->n = a.n;
595  this->p = a.p;
596  }
597 
598 
601  {
602  // check correct size
603 #ifdef DUNE_ISTL_WITH_CHECKING
604  if (this->n!=a.N()) DUNE_THROW(ISTLError,"vector size mismatch");
605 #endif
606 
607  if (&a!=this) // check if this and a are different objects
608  {
609  // copy data
610  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
611  }
612  return *this;
613  }
614 
617  {
618  // forward to regular assignment operator
619  return this->operator=(static_cast<const BlockVectorWindow&>(a));
620  }
621 
624  {
625  (static_cast<block_vector_unmanaged<B,A>&>(*this)) = k;
626  return *this;
627  }
628 
629 
630  //===== window manipulation methods
631 
633  void set (size_type _n, B* _p)
634  {
635  this->n = _n;
636  this->p = _p;
637  }
638 
640  void setsize (size_type _n)
641  {
642  this->n = _n;
643  }
644 
646  void setptr (B* _p)
647  {
648  this->p = _p;
649  }
650 
652  B* getptr ()
653  {
654  return this->p;
655  }
656 
659  {
660  return this->n;
661  }
662  };
663 
664 
665 
674  template<class B, class A=std::allocator<B> >
676  {
677  public:
678 
679  //===== type definitions and constants
680 
682  typedef typename B::field_type field_type;
683 
685  typedef B block_type;
686 
688  typedef A allocator_type;
689 
692 
695 
697  typedef typename A::size_type size_type;
698 
699  //===== assignment from scalar
700 
702  {
703  for (size_type i=0; i<this->n; i++)
704  (this->p)[i] = k;
705  return *this;
706  }
707 
708 
709  //===== vector space arithmetic
710 
712  template<class V>
714  {
715 #ifdef DUNE_ISTL_WITH_CHECKING
716  if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch");
717 #endif
718  for (size_type i=0; i<y.n; ++i) this->operator[](y.j[i]) += y.p[i];
719  return *this;
720  }
721 
723  template<class V>
725  {
726 #ifdef DUNE_ISTL_WITH_CHECKING
727  if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch");
728 #endif
729  for (size_type i=0; i<y.n; ++i) this->operator[](y.j[i]) -= y.p[i];
730  return *this;
731  }
732 
734  template<class V>
736  {
737 #ifdef DUNE_ISTL_WITH_CHECKING
738  if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch");
739 #endif
740  for (size_type i=0; i<y.n; ++i) (this->operator[](y.j[i])).axpy(a,y.p[i]);
741  return *this;
742  }
743 
746  {
747  for (size_type i=0; i<this->n; ++i) (this->p)[i] *= k;
748  return *this;
749  }
750 
753  {
754  for (size_type i=0; i<this->n; ++i) (this->p)[i] /= k;
755  return *this;
756  }
757 
758 
759  //===== Euclidean scalar product
760 
763  {
764 #ifdef DUNE_ISTL_WITH_CHECKING
765  if (!includesindexset(y) || !y.includesindexset(*this) )
766  DUNE_THROW(ISTLError,"index set mismatch");
767 #endif
768  field_type sum=0;
769  for (size_type i=0; i<this->n; ++i)
770  sum += (this->p)[i] * y[(this->j)[i]];
771  return sum;
772  }
773 
774 
775  //===== norms
776 
778  double one_norm () const
779  {
780  double sum=0;
781  for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].one_norm();
782  return sum;
783  }
784 
786  double one_norm_real () const
787  {
788  double sum=0;
789  for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].one_norm_real();
790  return sum;
791  }
792 
794  double two_norm () const
795  {
796  double sum=0;
797  for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].two_norm2();
798  return sqrt(sum);
799  }
800 
802  double two_norm2 () const
803  {
804  double sum=0;
805  for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].two_norm2();
806  return sum;
807  }
808 
810  double infinity_norm () const
811  {
812  double max=0;
813  for (size_type i=0; i<this->n; ++i) max = std::max(max,(this->p)[i].infinity_norm());
814  return max;
815  }
816 
818  double infinity_norm_real () const
819  {
820  double max=0;
821  for (size_type i=0; i<this->n; ++i) max = std::max(max,(this->p)[i].infinity_norm_real());
822  return max;
823  }
824 
825 
826  //===== sizes
827 
829  size_type N () const
830  {
831  return this->n;
832  }
833 
835  size_type dim () const
836  {
837  size_type d=0;
838  for (size_type i=0; i<this->n; i++)
839  d += (this->p)[i].dim();
840  return d;
841  }
842 
843  protected:
846  { }
847 
849  template<class V>
850  bool includesindexset (const V& y)
851  {
852  typename V::ConstIterator e=this->end();
853  for (size_type i=0; i<y.n; i++)
854  if (find(y.j[i])==e)
855  return false;
856  return true;
857  }
858  };
859 
860 
877  template<class B, class A=std::allocator<B> >
879  {
880  public:
881 
882  //===== type definitions and constants
883 
885  typedef typename B::field_type field_type;
886 
888  typedef B block_type;
889 
891  typedef A allocator_type;
892 
894  typedef typename A::size_type size_type;
895 
897  enum {
899  blocklevel = B::blocklevel+1};
900 
903 
906 
907 
908  //===== constructors and such
911  { }
912 
915  {
916  this->n = _n;
917  this->p = _p;
918  this->j = _j;
919  }
920 
923  {
924  this->n = a.n;
925  this->p = a.p;
926  this->j = a.j;
927  }
928 
931  {
932  // cast needed to access protected data (upcast)
933  const CompressedBlockVectorWindow& a = static_cast<const CompressedBlockVectorWindow&>(_a);
934 
935  // make me point to the other's data
936  this->n = a.n;
937  this->p = a.p;
938  this->j = a.j;
939  }
940 
941 
944  {
945  // check correct size
946 #ifdef DUNE_ISTL_WITH_CHECKING
947  if (this->n!=a.N()) DUNE_THROW(ISTLError,"vector size mismatch");
948 #endif
949 
950  if (&a!=this) // check if this and a are different objects
951  {
952  // copy data
953  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
954  for (size_type i=0; i<this->n; i++) this->j[i]=a.j[i];
955  }
956  return *this;
957  }
958 
961  {
962  // forward to regular assignment operator
963  return this->operator=(static_cast<const CompressedBlockVectorWindow&>(a));
964  }
965 
968  {
969  (static_cast<compressed_block_vector_unmanaged<B,A>&>(*this)) = k;
970  return *this;
971  }
972 
973 
974  //===== window manipulation methods
975 
977  void set (size_type _n, B* _p, size_type* _j)
978  {
979  this->n = _n;
980  this->p = _p;
981  this->j = _j;
982  }
983 
985  void setsize (size_type _n)
986  {
987  this->n = _n;
988  }
989 
991  void setptr (B* _p)
992  {
993  this->p = _p;
994  }
995 
998  {
999  this->j = _j;
1000  }
1001 
1003  B* getptr ()
1004  {
1005  return this->p;
1006  }
1007 
1010  {
1011  return this->j;
1012  }
1013 
1015  const B* getptr () const
1016  {
1017  return this->p;
1018  }
1019 
1021  const size_type* getindexptr () const
1022  {
1023  return this->j;
1024  }
1027  {
1028  return this->n;
1029  }
1030  };
1031 
1032 } // end namespace
1033 
1034 #endif