vbvector.hh

Go to the documentation of this file.
00001 #ifndef DUNE_VBVECTOR_HH
00002 #define DUNE_VBVECTOR_HH
00003 
00004 #include<cmath>
00005 #include<complex>
00006 #include<iostream>
00007 
00008 #include "istlexception.hh"
00009 #include "allocator.hh"
00010 #include "bvector.hh"
00011 
00016 namespace Dune {
00017    
00033   template<class B, class A=ISTLAllocator>
00034   class VariableBlockVector : public block_vector_unmanaged<B,A> 
00035   // this derivation gives us all the blas level 1 and norms
00036   // on the large array. However, access operators have to be 
00037   // overwritten.
00038   {
00039   public:
00040 
00041         //===== type definitions and constants
00042 
00044         typedef typename B::field_type field_type;
00045 
00047         typedef A allocator_type;
00048 
00053         typedef BlockVector<B,A> block_type;
00054 
00058         enum {
00060           blocklevel = B::blocklevel+2};
00061 
00062         // just a shorthand
00063         typedef BlockVectorWindow<B,A> window_type;
00064 
00065 
00066         //===== constructors and such
00067 
00071         VariableBlockVector () : block_vector_unmanaged<B,A>()
00072         {
00073           // nothing is known ...
00074           nblocks = 0;
00075           block = 0;
00076           initialized = false;
00077         }
00078 
00082         VariableBlockVector (int _nblocks) : block_vector_unmanaged<B,A>()
00083         {
00084           // we can allocate the windows now
00085           nblocks = _nblocks;
00086           if (nblocks>0)
00087                 { 
00088                   block = A::template malloc<window_type>(nblocks);
00089                 }
00090           else
00091                 {
00092                   nblocks = 0;
00093                   block = 0;;
00094                 }
00095 
00096           // Note: memory in base class still not allocated
00097           // the vector not usable
00098           initialized = false;
00099         }
00100 
00104         VariableBlockVector (int _nblocks, int m) : block_vector_unmanaged<B,A>()
00105         {
00106           // and we can allocate the big array in the base class
00107           this->n = _nblocks*m;
00108           if (this->n>0) 
00109                 {
00110                   this->p = A::template malloc<B>(this->n);
00111                 }
00112           else
00113                 {
00114                   this->n = 0;
00115                   this->p = 0;
00116                 }
00117 
00118           // we can allocate the windows now
00119           nblocks = _nblocks;
00120           if (nblocks>0)
00121                 { 
00122                   // alloc
00123                   block = A::template malloc<window_type>(nblocks);
00124 
00125                   // set the windows into the big array
00126                   for (int i=0; i<nblocks; ++i)
00127                         block[i].set(m,this->p+(i*m));
00128                 }
00129           else
00130                 {
00131                   nblocks = 0;
00132                   block = 0;;
00133                 }
00134 
00135           // and the vector is usable
00136           initialized = true;
00137         }
00138 
00140         VariableBlockVector (const VariableBlockVector& a)
00141         {
00142           // allocate the big array in the base class
00143           this->n = a.n;
00144           if (this->n>0) 
00145                 {
00146                   // alloc
00147                   this->p = A::template malloc<B>(this->n);
00148 
00149                   // copy data
00150                   for (int i=0; i<this->n; i++) this->p[i]=a.p[i];
00151                 }
00152           else
00153                 {
00154                   this->n = 0;
00155                   this->p = 0;
00156                 }
00157 
00158           // we can allocate the windows now
00159           nblocks = a.nblocks;
00160           if (nblocks>0)
00161                 { 
00162                   // alloc
00163                   block = A::template malloc<window_type>(nblocks);
00164 
00165                   // and we must set the windows
00166                   block[0].set(a.block[0].getsize(),this->p); // first block
00167                   for (int i=1; i<nblocks; ++i)               // and the rest
00168                         block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
00169                 }
00170           else
00171                 {
00172                   nblocks = 0;
00173                   block = 0;;
00174                 }
00175 
00176           // and we have a usable vector
00177           initialized = true;
00178         }
00179 
00181         ~VariableBlockVector () 
00182         { 
00183           if (this->n>0) A::template free<B>(this->p); 
00184           if (nblocks>0) A::template free<window_type>(block);
00185         }
00186 
00187 
00189         void resize (int _nblocks) 
00190         { 
00191           // deallocate memory if necessary
00192           if (this->n>0) A::template free<B>(this->p); 
00193           if (nblocks>0) A::template free<window_type>(block);
00194           this->n = 0;
00195           this->p = 0;
00196 
00197           // we can allocate the windows now
00198           nblocks = _nblocks;
00199           if (nblocks>0)
00200                 { 
00201                   block = A::template malloc<window_type>(nblocks);
00202                 }
00203           else
00204                 {
00205                   nblocks = 0;
00206                   block = 0;;
00207                 }
00208 
00209           // and the vector not fully usable
00210           initialized = false;
00211         }
00212 
00214         void resize (int _nblocks, int m) 
00215         { 
00216           // deallocate memory if necessary
00217           if (this->n>0) A::template free<B>(this->p); 
00218           if (nblocks>0) A::template free<window_type>(block);
00219 
00220           // and we can allocate the big array in the base class
00221           this->n = _nblocks*m;
00222           if (this->n>0) 
00223                 {
00224                   this->p = A::template malloc<B>(this->n);
00225                 }
00226           else
00227                 {
00228                   this->n = 0;
00229                   this->p = 0;
00230                 }
00231 
00232           // we can allocate the windows now
00233           nblocks = _nblocks;
00234           if (nblocks>0)
00235                 { 
00236                   // alloc
00237                   block = A::template malloc<window_type>(nblocks);
00238 
00239                   // set the windows into the big array
00240                   for (int i=0; i<nblocks; ++i)
00241                         block[i].set(m,this->p+(i*m));
00242                 }
00243           else
00244                 {
00245                   nblocks = 0;
00246                   block = 0;;
00247                 }
00248 
00249           // and the vector is usable
00250           initialized = true;
00251         }
00252 
00254         VariableBlockVector& operator= (const VariableBlockVector& a)
00255         {
00256           if (&a!=this) // check if this and a are different objects
00257                 {
00258                   // reallocate arrays if necessary
00259                   // Note: still the block sizes may vary !
00260                   if (this->n!=a.n || nblocks!=a.nblocks)
00261                         {
00262                           // deallocate memory if necessary
00263                           if (this->n>0) A::template free<B>(this->p); 
00264                           if (nblocks>0) A::template free<window_type>(block);
00265 
00266                           // allocate the big array in the base class
00267                           this->n = a.n;
00268                           if (this->n>0) 
00269                                 {
00270                                   // alloc
00271                                   this->p = A::template malloc<B>(this->n);
00272                                 }
00273                           else
00274                                 {
00275                                   this->n = 0;
00276                                   this->p = 0;
00277                                 }
00278 
00279                           // we can allocate the windows now
00280                           nblocks = a.nblocks;
00281                           if (nblocks>0)
00282                                 { 
00283                                   // alloc
00284                                   block = A::template malloc<window_type>(nblocks);
00285                                 }
00286                           else
00287                                 {
00288                                   nblocks = 0;
00289                                   block = 0;;
00290                                 }
00291                         }
00292 
00293                   // copy block structure, might be different although
00294                   // sizes are the same !
00295                   if (nblocks>0)
00296                         {
00297                           block[0].set(a.block[0].getsize(),this->p); // first block
00298                           for (int i=1; i<nblocks; ++i)               // and the rest
00299                                 block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
00300                         }
00301 
00302                   // and copy the data
00303                   for (int i=0; i<this->n; i++) this->p[i]=a.p[i];
00304                 }
00305 
00306           // and we have a usable vector
00307           initialized = true;
00308 
00309           return *this; // Gebe Referenz zurueck damit a=b=c; klappt
00310         }
00311 
00312 
00313         //===== assignment from scalar
00314 
00316         VariableBlockVector& operator= (const field_type& k)
00317         {
00318           (static_cast<block_vector_unmanaged<B,A>&>(*this)) = k;
00319           return *this;   
00320         }
00321 
00322 
00323         //===== the creation interface
00324 
00326         class CreateIterator 
00327         {
00328         public:
00330           CreateIterator (VariableBlockVector& _v, int _i) : v(_v)
00331           {
00332                 i = _i;
00333                 k = 0;
00334                 n = 0;
00335           }
00336 
00338           CreateIterator& operator++()
00339           {
00340                 // we are at block i and the blocks size is known
00341 
00342                 // set the blocks size to current k
00343                 v.block[i].setsize(k);
00344 
00345                 // accumulate total size
00346                 n += k;
00347 
00348                 // go to next block
00349                 ++i;
00350 
00351                 // reset block size
00352                 k = 0;
00353 
00354                 // if we are past the last block, finish off
00355                 if (i==v.nblocks) 
00356                   {
00357                         // now we can allocate the big array in the base class of v
00358                         v.n = n;
00359                         if (n>0) 
00360                           {
00361                                 // alloc
00362                                 v.p = A::template malloc<B>(n);
00363                           }
00364                         else
00365                           {
00366                                 v.n = 0;
00367                                 v.p = 0;
00368                           }
00369                         
00370                         // and we set the window pointer
00371                         if (v.nblocks>0)
00372                         {
00373                           v.block[0].setptr(v.p);         // pointer tofirst block
00374                           for (int j=1; j<v.nblocks; ++j) // and the rest
00375                                 v.block[j].setptr(v.block[j-1].getptr()+v.block[j-1].getsize());
00376                         }
00377 
00378                         // and the vector is ready
00379                         v.initialized = true;
00380 
00381                         //std::cout << "made vbvector with " << v.n << " components" << std::endl;
00382                   }
00383 
00384                 return *this;
00385           }
00386           
00388           bool operator!= (const CreateIterator& it) const
00389           {
00390         return (i!=it.i) || (&v!=&it.v);
00391           }
00392 
00394           bool operator== (const CreateIterator& it) const
00395           {
00396         return (i==it.i) && (&v==&it.v);
00397           }
00398 
00400           int index () const
00401           {
00402         return i;
00403           }
00404 
00406           void setblocksize (int _k)
00407           {
00408                 k = _k;
00409           }
00410 
00411         private:
00412           VariableBlockVector& v; // my vector
00413           int i;                  // current block to be defined
00414           int k;                  // size of current block to be defined
00415           int n;                  // total number of elements to be allocated
00416         };
00417 
00418         // CreateIterator wants to set all the arrays ...
00419         friend class CreateIterator;
00420 
00422         CreateIterator createbegin ()
00423         {
00424 #ifdef DUNE_ISTL_WITH_CHECKING
00425           if (initialized) DUNE_THROW(ISTLError,"no CreateIterator in initialized state");
00426 #endif
00427           return CreateIterator(*this,0);
00428         }
00429 
00431         CreateIterator createend ()
00432         {
00433           return CreateIterator(*this,nblocks);
00434         }
00435 
00436 
00437         //===== access to components
00438         // has to be overwritten from base class because it must
00439         // return access to the windows
00440 
00442         window_type& operator[] (int i)
00443         {
00444 #ifdef DUNE_ISTL_WITH_CHECKING
00445           if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
00446 #endif
00447           return block[i];
00448         }
00449 
00451         const window_type& operator[] (int i) const
00452         {
00453 #ifdef DUNE_ISTL_WITH_CHECKING
00454           if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
00455 #endif
00456           return block[i];
00457         }
00458 
00459         // forward declaration
00460         class ConstIterator;
00461 
00463         class Iterator 
00464         {
00465         public:
00467           Iterator ()
00468           {       
00469                 p = 0;
00470                 i = 0;
00471           }
00472 
00474           Iterator (window_type* _p, int _i) : p(_p), i(_i)
00475           {       }
00476 
00478           Iterator& operator++()
00479           {
00480         ++i;
00481                 return *this;
00482           }
00483           
00485           Iterator& operator--()
00486           {
00487         --i;
00488                 return *this;
00489           }
00490           
00492           bool operator== (const Iterator& it) const
00493           {
00494         return (p+i)==(it.p+it.i);
00495           }
00496 
00498           bool operator!= (const Iterator& it) const
00499           {
00500         return (p+i)!=(it.p+it.i);
00501           }
00502 
00504           bool operator== (const ConstIterator& it) const
00505           {
00506                 return (p+i)==(it.p+it.i);
00507           }
00508 
00510           bool operator!= (const ConstIterator& it) const
00511           {
00512         return (p+i)!=(it.p+it.i);
00513           }
00514 
00516           window_type& operator* () const
00517           {
00518         return p[i];
00519           }
00520 
00522           window_type* operator-> () const
00523           {
00524         return p+i;
00525           }
00526 
00527           // return index corresponding to pointer
00528           int index () const
00529           {
00530                 return i;
00531           }
00532 
00533           friend class ConstIterator;
00534 
00535         private:
00536           window_type* p;
00537           int i;
00538         };
00539 
00541         Iterator begin ()
00542         {
00543           return Iterator(block,0);
00544         }
00545 
00547         Iterator end ()
00548         {
00549           return Iterator(block,nblocks);
00550         }
00551 
00553         Iterator rbegin ()
00554         {
00555           return Iterator(block,nblocks-1);
00556         }
00557 
00559         Iterator rend ()
00560         {
00561           return Iterator(block,-1);
00562         }
00563 
00565         Iterator find (int i)
00566         {
00567           if (i>=0 && i<nblocks)
00568                 return Iterator(block,i);
00569           else
00570                 return Iterator(block,nblocks);
00571         }
00572 
00574         class ConstIterator 
00575         {
00576         public:
00578           ConstIterator ()
00579           {
00580                 p = 0;
00581                 i = 0;
00582           }
00583 
00585           ConstIterator (const window_type* _p, int _i) : p(_p), i(_i)
00586           {       }
00587 
00589           ConstIterator (const Iterator& it) : p(it.p), i(it.i)
00590           {       }
00591 
00593           ConstIterator& operator++()
00594           {
00595         ++i;
00596                 return *this;
00597           }
00598           
00600           ConstIterator& operator--()
00601           {
00602         --i;
00603                 return *this;
00604           }
00605           
00607           bool operator== (const ConstIterator& it) const
00608           {
00609         return (p+i)==(it.p+it.i);
00610           }
00611 
00613           bool operator!= (const ConstIterator& it) const
00614           {
00615         return (p+i)!=(it.p+it.i);
00616           }
00617 
00619           bool operator== (const Iterator& it) const
00620           {
00621         return (p+i)==(it.p+it.i);
00622           }
00623 
00625           bool operator!= (const Iterator& it) const
00626           {
00627                 return (p+i)!=(it.p+it.i);
00628           }
00629 
00631           const window_type& operator* () const
00632           {
00633         return p[i];
00634           }
00635 
00637           const window_type* operator-> () const
00638           {
00639         return p+i;
00640           }
00641 
00642           // return index corresponding to pointer
00643           int index () const
00644           {
00645                 return i;
00646           }
00647 
00648           friend class Iterator;
00649 
00650         private:
00651           const window_type* p;
00652           int i;
00653         };
00654 
00656         ConstIterator begin () const
00657         {
00658           return ConstIterator(block,0);
00659         }
00660 
00662         ConstIterator end () const
00663         {
00664           return ConstIterator(block,nblocks);
00665         }
00666 
00668         ConstIterator rbegin () const
00669         {
00670           return ConstIterator(block,nblocks-1);
00671         }
00672 
00674         ConstIterator rend () const
00675         {
00676           return ConstIterator(block,-1);
00677         }
00678 
00679 
00680         //===== sizes
00681 
00683         int N () const
00684         {
00685           return nblocks;
00686         }
00687 
00688 
00689   private:
00690         int nblocks;        // number of blocks in vector
00691         window_type* block; // array of blocks pointing to the array in the base class
00692         bool initialized;   // true if vector has been initialized
00693   };
00694 
00695 
00696 
00699 } // end namespace
00700 
00701 #endif

Generated on 9 Apr 2008 with Doxygen (ver 1.5.2) [logfile].