dune-istl  2.1.1
bvector.hh
Go to the documentation of this file.
00001 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002 // vi: set et ts=4 sw=2 sts=2:
00003 
00004 #ifndef DUNE_BVECTOR_HH
00005 #define DUNE_BVECTOR_HH
00006 
00007 #include<cmath>
00008 #include<complex>
00009 #include<memory>
00010 
00011 #include "istlexception.hh"
00012 #include "basearray.hh"
00013 
00021 namespace Dune {
00022 
00023  
00035   template<class B, class A=std::allocator<B> >
00036   class block_vector_unmanaged : public base_array_unmanaged<B,A>
00037   {
00038   public:
00039 
00040         //===== type definitions and constants
00041 
00043         typedef typename B::field_type field_type;
00044 
00046         typedef B block_type;
00047 
00049         typedef A allocator_type;
00050 
00052     typedef typename A::size_type size_type;
00053     
00055         typedef typename base_array_unmanaged<B,A>::iterator Iterator;
00056 
00058         typedef typename base_array_unmanaged<B,A>::const_iterator ConstIterator;
00059 
00061         typedef B value_type;
00062 
00063         //===== assignment from scalar
00065 
00066         block_vector_unmanaged& operator= (const field_type& k)
00067         {
00068           for (size_type i=0; i<this->n; i++)
00069                 (*this)[i] = k;
00070           return *this;   
00071         }
00072 
00073         //===== vector space arithmetic
00075         block_vector_unmanaged& operator+= (const block_vector_unmanaged& y)
00076         {
00077 #ifdef DUNE_ISTL_WITH_CHECKING
00078           if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
00079 #endif
00080           for (size_type i=0; i<this->n; ++i) (*this)[i] += y[i];
00081           return *this;
00082         }
00083 
00085         block_vector_unmanaged& operator-= (const block_vector_unmanaged& y)
00086         {
00087 #ifdef DUNE_ISTL_WITH_CHECKING
00088           if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
00089 #endif
00090           for (size_type i=0; i<this->n; ++i) (*this)[i] -= y[i];
00091           return *this;
00092         }
00093 
00095         block_vector_unmanaged& operator*= (const field_type& k)
00096         {
00097           for (size_type i=0; i<this->n; ++i) (*this)[i] *= k;
00098           return *this;
00099         }
00100 
00102         block_vector_unmanaged& operator/= (const field_type& k)
00103         {
00104           for (size_type i=0; i<this->n; ++i) (*this)[i] /= k;
00105           return *this;
00106         }
00107 
00109         block_vector_unmanaged& axpy (const field_type& a, const block_vector_unmanaged& y)
00110         {
00111 #ifdef DUNE_ISTL_WITH_CHECKING
00112           if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
00113 #endif
00114           for (size_type i=0; i<this->n; ++i) (*this)[i].axpy(a,y[i]);
00115           return *this;
00116         }
00117 
00118 
00119         //===== Euclidean scalar product
00120 
00122     field_type operator* (const block_vector_unmanaged& y) const
00123         {
00124 #ifdef DUNE_ISTL_WITH_CHECKING
00125           if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch");
00126 #endif
00127           field_type sum=0;
00128           for (size_type i=0; i<this->n; ++i) sum += (*this)[i]*y[i];
00129           return sum;
00130         }
00131 
00132 
00133         //===== norms
00134 
00136     double one_norm () const
00137         {
00138           double sum=0;
00139           for (size_type i=0; i<this->n; ++i) sum += (*this)[i].one_norm();
00140           return sum;
00141         }
00142 
00144     double one_norm_real () const
00145         {
00146           double sum=0;
00147           for (size_type i=0; i<this->n; ++i) sum += (*this)[i].one_norm_real();
00148           return sum;
00149         }
00150 
00152     double two_norm () const
00153         {
00154           double sum=0;
00155           for (size_type i=0; i<this->n; ++i) sum += (*this)[i].two_norm2();
00156           return sqrt(sum);
00157         }
00158 
00160     double two_norm2 () const
00161         {
00162           double sum=0;
00163           for (size_type i=0; i<this->n; ++i) sum += (*this)[i].two_norm2();
00164           return sum;
00165         }
00166 
00168     double infinity_norm () const
00169         {
00170           double max=0;
00171           for (size_type i=0; i<this->n; ++i) max = std::max(max,(*this)[i].infinity_norm());
00172           return max;
00173         }
00174 
00176         double infinity_norm_real () const
00177         {
00178           double max=0;
00179           for (size_type i=0; i<this->n; ++i) max = std::max(max,(*this)[i].infinity_norm_real());
00180           return max;
00181         }
00182 
00183         //===== sizes
00184 
00186         size_type N () const
00187         {
00188           return this->n;
00189         }
00190 
00192         size_type dim () const
00193         {
00194           size_type d=0;
00195           for (size_type i=0; i<this->n; i++)
00196                 d += (*this)[i].dim();
00197           return d;
00198         }
00199 
00200   protected:
00202         block_vector_unmanaged () : base_array_unmanaged<B,A>()
00203         {       }
00204   };
00205    
00221   template<class B, class A=std::allocator<B> >
00222   class BlockVector : public block_vector_unmanaged<B,A>
00223   {
00224   public:
00225 
00226         //===== type definitions and constants
00227 
00229         typedef typename B::field_type field_type;
00230 
00232         typedef B block_type;
00233 
00235         typedef A allocator_type;
00236 
00238     typedef typename A::size_type size_type;
00239     
00241         enum {
00243           blocklevel = B::blocklevel+1};
00244 
00246         typedef typename block_vector_unmanaged<B,A>::Iterator Iterator;
00247 
00249         typedef typename block_vector_unmanaged<B,A>::ConstIterator ConstIterator;
00250 
00251         //===== constructors and such
00252 
00254     BlockVector () : block_vector_unmanaged<B,A>(),
00255                      capacity_(0)
00256         {}
00257 
00259         explicit BlockVector (size_type _n)
00260         {
00261           this->n = _n;
00262           capacity_ = _n;
00263           if (capacity_>0) {
00264               this->p = this->allocator_.allocate(capacity_);
00265               // actually construct the objects
00266               new(this->p) B[capacity_];
00267           } else
00268                 {
00269                   this->p = 0;
00270                   this->n = 0;
00271                   capacity_ = 0;
00272                 }
00273         }
00274 
00286     BlockVector (size_type _n, size_type capacity)
00287     {
00288           this->n = _n;
00289           if(this->n > capacity)
00290             capacity_ = _n;
00291           else
00292             capacity_ = capacity;
00293           
00294           if (capacity_>0) {
00295                 this->p = this->allocator_.allocate(capacity_);
00296                 new (this->p) B[capacity_];
00297           } else
00298                 {
00299                   this->p = 0;
00300                   this->n = 0;
00301                   capacity_ = 0;
00302                 }
00303     }
00304     
00305 
00322     void reserve(size_type capacity, bool copyOldValues=true)
00323     {
00324       if(capacity >= block_vector_unmanaged<B,A>::N() && capacity != capacity_){
00325           // save the old data
00326           B* pold = this->p;
00327 
00328         if(capacity>0){
00329           // create new array with capacity
00330           this->p = this->allocator_.allocate(capacity);
00331           new (this->p) B[capacity];
00332 
00333           if(copyOldValues){
00334             // copy the old values
00335             B* to = this->p;
00336             B* from = pold;
00337         
00338             for(size_type i=0; i < block_vector_unmanaged<B,A>::N(); ++i, ++from, ++to)
00339               *to = *from;
00340 
00341             if(capacity_ > 0) {
00342                 // Destruct old objects and free memory
00343                 int i=capacity_;
00344                 while (i)
00345                     pold[--i].~B();
00346                 this->allocator_.deallocate(pold,capacity_);
00347             }
00348           }
00349         }else{
00350           if(capacity_ > 0)
00351           // free old data
00352           this->p = 0;
00353           capacity_ = 0;
00354         }
00355         
00356         capacity_ = capacity;
00357       }
00358     }
00359     
00366     size_type capacity() const
00367     {
00368       return capacity_;
00369     }
00370         
00385     void resize(size_type size, bool copyOldValues=true)
00386     {
00387       if(size > block_vector_unmanaged<B,A>::N())
00388         if(capacity_ < size)
00389           this->reserve(size, copyOldValues);
00390 
00391       if(size >=0)
00392         this->n=size;
00393     }
00394     
00395       
00396     
00397       
00399       BlockVector (const BlockVector& a) :
00400       block_vector_unmanaged<B,A>(a)
00401         {
00402           // allocate memory with same size as a
00403           this->n = a.n;
00404           capacity_ = a.capacity_;
00405 
00406           if (capacity_>0) {
00407                 this->p = this->allocator_.allocate(capacity_);
00408                 new (this->p) B[capacity_];
00409           } else
00410                 {
00411                   this->n = 0;
00412                   this->p = 0;
00413                 }
00414 
00415           // and copy elements
00416           for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00417         }
00418 
00420         BlockVector (const block_vector_unmanaged<B,A>& _a) 
00421         {
00422           // upcast, because protected data inaccessible
00423           const BlockVector& a = static_cast<const BlockVector&>(_a);
00424 
00425           // allocate memory with same size as a
00426           this->n = a.n;
00427           capacity_ = a.capacity_;
00428 
00429           if (capacity_>0) {
00430               this->p = this->allocator_.allocate(capacity_);
00431               new (this->p) B[capacity_];
00432           } else
00433                 {
00434                   this->n = 0;
00435                   this->p = 0;
00436                   capacity_ = 0;
00437                 }
00438 
00439           // and copy elements
00440           for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00441         }
00442 
00444         ~BlockVector () 
00445         { 
00446             if (capacity_>0) {
00447                 int i=capacity_;
00448                 while (i)
00449                     this->p[--i].~B();
00450                 this->allocator_.deallocate(this->p,capacity_); 
00451             }
00452         }
00453 
00455         BlockVector& operator= (const BlockVector& a)
00456         {
00457           if (&a!=this) // check if this and a are different objects
00458                 {
00459                   // adjust size of vector
00460                   if (capacity_!=a.capacity_) // check if size is different
00461                         {
00462                             if (capacity_>0) {
00463                                 int i=capacity_;
00464                                 while (i)
00465                                     this->p[--i].~B();
00466                                 this->allocator_.deallocate(this->p,capacity_); // free old memory
00467                             }
00468                           capacity_ = a.capacity_;
00469                           if (capacity_>0) {
00470                               this->p = this->allocator_.allocate(capacity_);
00471                               new (this->p) B[capacity_];
00472                           } else
00473                                 {
00474                                   this->p = 0;
00475                                   capacity_ = 0;
00476                                 }
00477                         }
00478                   this->n = a.n;
00479                   // copy data
00480                   for (size_type i=0; i<this->n; i++) 
00481                     this->p[i]=a.p[i];
00482                 }
00483           return *this;
00484         }
00485 
00487         BlockVector& operator= (const block_vector_unmanaged<B,A>& a)
00488         {
00489           // forward to regular assignement operator
00490           return this->operator=(static_cast<const BlockVector&>(a));
00491         }
00492     
00494         BlockVector& operator= (const field_type& k)
00495         {
00496           // forward to operator= in base class
00497           (static_cast<block_vector_unmanaged<B,A>&>(*this)) = k;
00498           return *this;   
00499         }
00500   protected:
00501     size_type capacity_;
00502 
00503       A allocator_;
00504 
00505   };
00506 
00508 
00509     template<class K, class A>
00510     std::ostream& operator<< (std::ostream& s, const BlockVector<K, A>& v)
00511   {
00512     typedef typename  BlockVector<K, A>::size_type size_type;
00513     
00514       for (size_type i=0; i<v.size(); i++)
00515           s << v[i] << std::endl;
00516 
00517       return s;
00518   }
00519 
00536   template<class B, class A=std::allocator<B> >
00537   class BlockVectorWindow : public block_vector_unmanaged<B,A>
00538   {
00539   public:
00540 
00541         //===== type definitions and constants
00542 
00544         typedef typename B::field_type field_type;
00545 
00547         typedef B block_type;
00548 
00550         typedef A allocator_type;
00551 
00553     typedef typename A::size_type size_type;
00554     
00556         enum {
00558           blocklevel = B::blocklevel+1
00559         };
00560 
00562         typedef typename block_vector_unmanaged<B,A>::Iterator Iterator;
00563 
00565         typedef typename block_vector_unmanaged<B,A>::ConstIterator ConstIterator;
00566 
00567 
00568         //===== constructors and such
00570         BlockVectorWindow () : block_vector_unmanaged<B,A>()
00571         {       }
00572 
00574         BlockVectorWindow (B* _p, size_type _n)
00575         {
00576           this->n = _n;
00577           this->p = _p;
00578         }
00579 
00581         BlockVectorWindow (const BlockVectorWindow& a)
00582         {
00583           this->n = a.n;
00584           this->p = a.p;
00585         }
00586 
00588         BlockVectorWindow (const block_vector_unmanaged<B,A>& _a) 
00589         {
00590           // cast needed to access protected data
00591           const BlockVectorWindow& a = static_cast<const BlockVectorWindow&>(_a);
00592 
00593           // make me point to the other's data
00594           this->n = a.n;
00595           this->p = a.p;
00596         }
00597 
00598 
00600         BlockVectorWindow& operator= (const BlockVectorWindow& a)
00601         {
00602           // check correct size
00603 #ifdef DUNE_ISTL_WITH_CHECKING
00604           if (this->n!=a.N()) DUNE_THROW(ISTLError,"vector size mismatch");
00605 #endif
00606 
00607           if (&a!=this) // check if this and a are different objects
00608                 {
00609                   // copy data
00610                   for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00611                 }
00612           return *this;
00613         }
00614 
00616         BlockVectorWindow& operator= (const block_vector_unmanaged<B,A>& a)
00617         {
00618           // forward to regular assignment operator
00619           return this->operator=(static_cast<const BlockVectorWindow&>(a));
00620         }
00621 
00623         BlockVectorWindow& operator= (const field_type& k)
00624         {
00625           (static_cast<block_vector_unmanaged<B,A>&>(*this)) = k;
00626           return *this;   
00627         }
00628 
00629 
00630         //===== window manipulation methods
00631 
00633         void set (size_type _n, B* _p)
00634         {
00635           this->n = _n;
00636           this->p = _p;
00637         }
00638 
00640         void setsize (size_type _n)
00641         {
00642           this->n = _n;
00643         }
00644 
00646         void setptr (B* _p)
00647         {
00648           this->p = _p;
00649         }
00650 
00652         B* getptr ()
00653         {
00654           return this->p;
00655         }
00656 
00658         size_type getsize ()
00659         {
00660           return this->n;
00661         }
00662   };
00663 
00664 
00665 
00674   template<class B, class A=std::allocator<B> >
00675   class compressed_block_vector_unmanaged : public compressed_base_array_unmanaged<B,A>
00676   {
00677   public:
00678 
00679         //===== type definitions and constants
00680 
00682         typedef typename B::field_type field_type;
00683 
00685         typedef B block_type;
00686 
00688         typedef A allocator_type;
00689 
00691         typedef typename compressed_base_array_unmanaged<B,A>::iterator Iterator;
00692 
00694         typedef typename compressed_base_array_unmanaged<B,A>::const_iterator ConstIterator;
00695 
00697     typedef typename A::size_type size_type;
00698     
00699         //===== assignment from scalar
00700 
00701         compressed_block_vector_unmanaged& operator= (const field_type& k)
00702         {
00703           for (size_type i=0; i<this->n; i++)
00704                 (this->p)[i] = k;
00705           return *this;   
00706         }
00707 
00708 
00709         //===== vector space arithmetic
00710 
00712         template<class V>
00713         compressed_block_vector_unmanaged& operator+= (const V& y)
00714         {
00715 #ifdef DUNE_ISTL_WITH_CHECKING
00716           if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch");
00717 #endif
00718           for (size_type i=0; i<y.n; ++i) this->operator[](y.j[i]) += y.p[i];
00719           return *this;
00720         }
00721 
00723         template<class V>
00724         compressed_block_vector_unmanaged& operator-= (const V& y)
00725         {
00726 #ifdef DUNE_ISTL_WITH_CHECKING
00727           if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch");
00728 #endif
00729           for (size_type i=0; i<y.n; ++i) this->operator[](y.j[i]) -= y.p[i];
00730           return *this;
00731         }
00732 
00734         template<class V>
00735         compressed_block_vector_unmanaged& axpy (const field_type& a, const V& y)
00736         {
00737 #ifdef DUNE_ISTL_WITH_CHECKING
00738           if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch");
00739 #endif
00740           for (size_type i=0; i<y.n; ++i) (this->operator[](y.j[i])).axpy(a,y.p[i]);
00741           return *this;
00742         }
00743 
00745         compressed_block_vector_unmanaged& operator*= (const field_type& k)
00746         {
00747           for (size_type i=0; i<this->n; ++i) (this->p)[i] *= k;
00748           return *this;
00749         }
00750 
00752         compressed_block_vector_unmanaged& operator/= (const field_type& k)
00753         {
00754           for (size_type i=0; i<this->n; ++i) (this->p)[i] /= k;
00755           return *this;
00756         }
00757 
00758 
00759         //===== Euclidean scalar product
00760 
00762     field_type operator* (const compressed_block_vector_unmanaged& y) const
00763         {
00764 #ifdef DUNE_ISTL_WITH_CHECKING
00765           if (!includesindexset(y) || !y.includesindexset(*this) )
00766             DUNE_THROW(ISTLError,"index set mismatch");
00767 #endif
00768           field_type sum=0;
00769           for (size_type i=0; i<this->n; ++i) 
00770                 sum += (this->p)[i] * y[(this->j)[i]];
00771           return sum;
00772         }
00773 
00774 
00775         //===== norms
00776 
00778     double one_norm () const
00779         {
00780           double sum=0;
00781           for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].one_norm();
00782           return sum;
00783         }
00784 
00786     double one_norm_real () const
00787         {
00788           double sum=0;
00789           for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].one_norm_real();
00790           return sum;
00791         }
00792 
00794     double two_norm () const
00795         {
00796           double sum=0;
00797           for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].two_norm2();
00798           return sqrt(sum);
00799         }
00800 
00802     double two_norm2 () const
00803         {
00804           double sum=0;
00805           for (size_type i=0; i<this->n; ++i) sum += (this->p)[i].two_norm2();
00806           return sum;
00807         }
00808 
00810     double infinity_norm () const
00811         {
00812           double max=0;
00813           for (size_type i=0; i<this->n; ++i) max = std::max(max,(this->p)[i].infinity_norm());
00814           return max;
00815         }
00816 
00818         double infinity_norm_real () const
00819         {
00820           double max=0;
00821           for (size_type i=0; i<this->n; ++i) max = std::max(max,(this->p)[i].infinity_norm_real());
00822           return max;
00823         }
00824 
00825 
00826         //===== sizes
00827 
00829         size_type N () const
00830         {
00831           return this->n;
00832         }
00833 
00835         size_type dim () const
00836         {
00837           size_type d=0;
00838           for (size_type i=0; i<this->n; i++)
00839                 d += (this->p)[i].dim();
00840           return d;
00841         }
00842 
00843   protected:
00845         compressed_block_vector_unmanaged () : compressed_base_array_unmanaged<B,A>()
00846         {       }
00847 
00849         template<class V>
00850         bool includesindexset (const V& y)
00851         {
00852           typename V::ConstIterator e=this->end();
00853           for (size_type i=0; i<y.n; i++)
00854                 if (find(y.j[i])==e)
00855                   return false;
00856           return true;
00857         }
00858   };
00859 
00860 
00877   template<class B, class A=std::allocator<B> >
00878   class CompressedBlockVectorWindow : public compressed_block_vector_unmanaged<B,A>
00879   {
00880   public:
00881 
00882         //===== type definitions and constants
00883 
00885         typedef typename B::field_type field_type;
00886 
00888         typedef B block_type;
00889 
00891         typedef A allocator_type;
00892 
00894     typedef typename A::size_type size_type;
00895     
00897         enum {
00899           blocklevel = B::blocklevel+1};
00900 
00902         typedef typename compressed_block_vector_unmanaged<B,A>::Iterator Iterator;
00903 
00905         typedef typename compressed_block_vector_unmanaged<B,A>::ConstIterator ConstIterator;
00906 
00907 
00908         //===== constructors and such
00910         CompressedBlockVectorWindow () : compressed_block_vector_unmanaged<B,A>()
00911         {       }
00912 
00914         CompressedBlockVectorWindow (B* _p, size_type* _j, size_type _n)
00915         {
00916           this->n = _n;
00917           this->p = _p;
00918           this->j = _j;
00919         }
00920 
00922         CompressedBlockVectorWindow (const CompressedBlockVectorWindow& a)
00923         {
00924           this->n = a.n;
00925           this->p = a.p;
00926           this->j = a.j;
00927         }
00928 
00930         CompressedBlockVectorWindow (const compressed_block_vector_unmanaged<B,A>& _a) 
00931         {
00932           // cast needed to access protected data (upcast)
00933           const CompressedBlockVectorWindow& a = static_cast<const CompressedBlockVectorWindow&>(_a);
00934 
00935           // make me point to the other's data
00936           this->n = a.n;
00937           this->p = a.p;
00938           this->j = a.j;
00939         }
00940 
00941 
00943         CompressedBlockVectorWindow& operator= (const CompressedBlockVectorWindow& a)
00944         {
00945           // check correct size
00946 #ifdef DUNE_ISTL_WITH_CHECKING
00947           if (this->n!=a.N()) DUNE_THROW(ISTLError,"vector size mismatch");
00948 #endif
00949 
00950           if (&a!=this) // check if this and a are different objects
00951                 {
00952                   // copy data
00953                   for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00954                   for (size_type i=0; i<this->n; i++) this->j[i]=a.j[i];
00955                 }
00956           return *this;
00957         }
00958 
00960         CompressedBlockVectorWindow& operator= (const compressed_block_vector_unmanaged<B,A>& a)
00961         {
00962           // forward to regular assignment operator
00963           return this->operator=(static_cast<const CompressedBlockVectorWindow&>(a));
00964         }
00965 
00967         CompressedBlockVectorWindow& operator= (const field_type& k)
00968         {
00969           (static_cast<compressed_block_vector_unmanaged<B,A>&>(*this)) = k;
00970           return *this;   
00971         }
00972 
00973 
00974         //===== window manipulation methods
00975 
00977         void set (size_type _n, B* _p, size_type* _j)
00978         {
00979           this->n = _n;
00980           this->p = _p;
00981           this->j = _j;
00982         }
00983 
00985         void setsize (size_type _n)
00986         {
00987           this->n = _n;
00988         }
00989 
00991         void setptr (B* _p)
00992         {
00993           this->p = _p;
00994         }
00995 
00997         void setindexptr (size_type* _j)
00998         {
00999           this->j = _j;
01000         }
01001 
01003         B* getptr ()
01004         {
01005           return this->p;
01006         }
01007 
01009         size_type* getindexptr ()
01010         {
01011           return this->j;
01012         }
01013 
01015         const B* getptr () const
01016         {
01017           return this->p;
01018         }
01019 
01021         const size_type* getindexptr () const
01022         {
01023           return this->j;
01024         }
01026         size_type getsize () const
01027         {
01028           return this->n;
01029         }
01030   };
01031 
01032 } // end namespace
01033 
01034 #endif