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     explicit 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         ConstIterator find (int i) const
00575         {
00576           if (i>=0 && i<nblocks)
00577                 return ConstIterator(block,i);
00578           else
00579                 return ConstIterator(block,nblocks);
00580         }
00581 
00583         class ConstIterator 
00584         {
00585         public:
00587           ConstIterator ()
00588           {
00589                 p = 0;
00590                 i = 0;
00591           }
00592 
00594           ConstIterator (const window_type* _p, int _i) : p(_p), i(_i)
00595           {       }
00596 
00598           ConstIterator (const Iterator& it) : p(it.p), i(it.i)
00599           {       }
00600 
00602           ConstIterator& operator++()
00603           {
00604         ++i;
00605                 return *this;
00606           }
00607           
00609           ConstIterator& operator--()
00610           {
00611         --i;
00612                 return *this;
00613           }
00614           
00616           bool operator== (const ConstIterator& it) const
00617           {
00618         return (p+i)==(it.p+it.i);
00619           }
00620 
00622           bool operator!= (const ConstIterator& it) const
00623           {
00624         return (p+i)!=(it.p+it.i);
00625           }
00626 
00628           bool operator== (const Iterator& it) const
00629           {
00630         return (p+i)==(it.p+it.i);
00631           }
00632 
00634           bool operator!= (const Iterator& it) const
00635           {
00636                 return (p+i)!=(it.p+it.i);
00637           }
00638 
00640           const window_type& operator* () const
00641           {
00642         return p[i];
00643           }
00644 
00646           const window_type* operator-> () const
00647           {
00648         return p+i;
00649           }
00650 
00651           // return index corresponding to pointer
00652           int index () const
00653           {
00654                 return i;
00655           }
00656 
00657           friend class Iterator;
00658 
00659         private:
00660           const window_type* p;
00661           int i;
00662         };
00663 
00665         ConstIterator begin () const
00666         {
00667           return ConstIterator(block,0);
00668         }
00669 
00671         ConstIterator end () const
00672         {
00673           return ConstIterator(block,nblocks);
00674         }
00675 
00677         ConstIterator rbegin () const
00678         {
00679           return ConstIterator(block,nblocks-1);
00680         }
00681 
00683         ConstIterator rend () const
00684         {
00685           return ConstIterator(block,-1);
00686         }
00687 
00688 
00689         //===== sizes
00690 
00692         int N () const
00693         {
00694           return nblocks;
00695         }
00696 
00697 
00698   private:
00699         int nblocks;        // number of blocks in vector
00700         window_type* block; // array of blocks pointing to the array in the base class
00701         bool initialized;   // true if vector has been initialized
00702   };
00703 
00704 
00705 
00708 } // end namespace
00709 
00710 #endif

Generated on Thu Apr 2 10:40:16 2009 for dune-istl by  doxygen 1.5.6