dune-istl  2.1.1
vbvector.hh
Go to the documentation of this file.
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 6 -*-
00002 // vi: set et ts=8 sw=6 sts=6:
00003 #ifndef DUNE_VBVECTOR_HH
00004 #define DUNE_VBVECTOR_HH
00005 
00006 #include<cmath>
00007 #include<complex>
00008 #include<iostream>
00009 #include<memory>
00010 
00011 #include "istlexception.hh"
00012 #include "bvector.hh"
00013 
00018 namespace Dune {
00019    
00035   template<class B, class A=std::allocator<B> >
00036   class VariableBlockVector : public block_vector_unmanaged<B,A> 
00037   // this derivation gives us all the blas level 1 and norms
00038   // on the large array. However, access operators have to be 
00039   // overwritten.
00040   {
00041   public:
00042 
00043         //===== type definitions and constants
00044 
00046         typedef typename B::field_type field_type;
00047 
00049         typedef A allocator_type;
00050 
00052       typedef typename A::size_type size_type;
00053 
00058         typedef BlockVector<B,A> block_type;
00059 
00063         enum {
00065           blocklevel = B::blocklevel+2};
00066 
00067         // just a shorthand
00068         typedef BlockVectorWindow<B,A> window_type;
00069 
00070 
00071         //===== constructors and such
00072 
00076         VariableBlockVector () : block_vector_unmanaged<B,A>()
00077         {
00078           // nothing is known ...
00079           nblocks = 0;
00080           block = 0;
00081           initialized = false;
00082         }
00083 
00087     explicit VariableBlockVector (size_type _nblocks) : block_vector_unmanaged<B,A>()
00088         {
00089           // we can allocate the windows now
00090           nblocks = _nblocks;
00091           if (nblocks>0)
00092                 { 
00093                   block = windowAllocator_.allocate(nblocks);
00094                   new (block) window_type[nblocks];
00095                 }
00096           else
00097                 {
00098                   nblocks = 0;
00099                   block = 0;;
00100                 }
00101 
00102           // Note: memory in base class still not allocated
00103           // the vector not usable
00104           initialized = false;
00105         }
00106 
00113         VariableBlockVector (size_type _nblocks, size_type m) : block_vector_unmanaged<B,A>()
00114         {
00115           // and we can allocate the big array in the base class
00116           this->n = _nblocks*m;
00117           if (this->n>0) 
00118                 {
00119                   this->p = allocator_.allocate(this->n);
00120                   new (this->p) B[this->n];
00121                 }
00122           else
00123                 {
00124                   this->n = 0;
00125                   this->p = 0;
00126                 }
00127 
00128           // we can allocate the windows now
00129           nblocks = _nblocks;
00130           if (nblocks>0)
00131                 { 
00132                   // allocate and construct the windows
00133                   block = windowAllocator_.allocate(nblocks);
00134                   new (block) window_type[nblocks];
00135 
00136                   // set the windows into the big array
00137                   for (size_type i=0; i<nblocks; ++i)
00138                         block[i].set(m,this->p+(i*m));
00139                 }
00140           else
00141                 {
00142                   nblocks = 0;
00143                   block = 0;;
00144                 }
00145 
00146           // and the vector is usable
00147           initialized = true;
00148         }
00149 
00151         VariableBlockVector (const VariableBlockVector& a)
00152         {
00153           // allocate the big array in the base class
00154           this->n = a.n;
00155           if (this->n>0) 
00156                 {
00157                   // allocate and construct objects
00158                   this->p = allocator_.allocate(this->n);
00159                   new (this->p) B[this->n];
00160 
00161                   // copy data
00162                   for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00163                 }
00164           else
00165                 {
00166                   this->n = 0;
00167                   this->p = 0;
00168                 }
00169 
00170           // we can allocate the windows now
00171           nblocks = a.nblocks;
00172           if (nblocks>0)
00173                 { 
00174                   // alloc
00175                   block = windowAllocator_.allocate(nblocks);
00176                   new (block) window_type[nblocks];
00177 
00178                   // and we must set the windows
00179                   block[0].set(a.block[0].getsize(),this->p); // first block
00180                   for (size_type i=1; i<nblocks; ++i)               // and the rest
00181                         block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
00182                 }
00183           else
00184                 {
00185                   nblocks = 0;
00186                   block = 0;;
00187                 }
00188 
00189           // and we have a usable vector
00190           initialized = true;
00191         }
00192 
00194         ~VariableBlockVector () 
00195         { 
00196             if (this->n>0) {
00197                 size_type i=this->n;
00198                 while (i)
00199                     this->p[--i].~B();
00200                 allocator_.deallocate(this->p,this->n); 
00201             }
00202             if (nblocks>0) {
00203                 size_type i=nblocks;
00204                 while (i)
00205                     block[--i].~window_type();
00206                 windowAllocator_.deallocate(block,nblocks);
00207             }
00208 
00209         }
00210 
00211 
00213         void resize (size_type _nblocks) 
00214         { 
00215           // deconstruct objects and deallocate memory if necessary
00216             if (this->n>0) {
00217                 size_type i=this->n;
00218                 while (i)
00219                     this->p[--i].~B();
00220                 allocator_.deallocate(this->p,this->n); 
00221             }
00222             if (nblocks>0) {
00223                 size_type i=nblocks;
00224                 while (i)
00225                     block[--i].~window_type();
00226                 windowAllocator_.deallocate(block,nblocks);
00227             }
00228           this->n = 0;
00229           this->p = 0;
00230 
00231           // we can allocate the windows now
00232           nblocks = _nblocks;
00233           if (nblocks>0)
00234                 { 
00235                   block = windowAllocator_.allocate(nblocks);
00236                   new (block) window_type[nblocks];
00237                 }
00238           else
00239                 {
00240                   nblocks = 0;
00241                   block = 0;;
00242                 }
00243 
00244           // and the vector not fully usable
00245           initialized = false;
00246         }
00247 
00249         void resize (size_type _nblocks, size_type m) 
00250         { 
00251           // deconstruct objects and deallocate memory if necessary
00252             if (this->n>0) {
00253                 size_type i=this->n;
00254                 while (i)
00255                     this->p[--i].~B();
00256                 allocator_.deallocate(this->p,this->n); 
00257             }
00258             if (nblocks>0) {
00259                 size_type i=nblocks;
00260                 while (i)
00261                     block[--i].~window_type();
00262                 windowAllocator_.deallocate(block,nblocks);
00263             }
00264 
00265           // and we can allocate the big array in the base class
00266           this->n = _nblocks*m;
00267           if (this->n>0) 
00268                 {
00269                   this->p = allocator_.allocate(this->n);
00270                   new (this->p) B[this->n];
00271                 }
00272           else
00273                 {
00274                   this->n = 0;
00275                   this->p = 0;
00276                 }
00277 
00278           // we can allocate the windows now
00279           nblocks = _nblocks;
00280           if (nblocks>0)
00281                 { 
00282                   // allocate and construct objects
00283                   block = windowAllocator_.allocate(nblocks);
00284                   new (block) window_type[nblocks];
00285 
00286                   // set the windows into the big array
00287                   for (size_type i=0; i<nblocks; ++i)
00288                         block[i].set(m,this->p+(i*m));
00289                 }
00290           else
00291                 {
00292                   nblocks = 0;
00293                   block = 0;;
00294                 }
00295 
00296           // and the vector is usable
00297           initialized = true;
00298         }
00299 
00301         VariableBlockVector& operator= (const VariableBlockVector& a)
00302         {
00303           if (&a!=this) // check if this and a are different objects
00304                 {
00305                   // reallocate arrays if necessary
00306                   // Note: still the block sizes may vary !
00307                   if (this->n!=a.n || nblocks!=a.nblocks)
00308                         {
00309                           // deconstruct objects and deallocate memory if necessary
00310                           if (this->n>0) {
00311                               size_type i=this->n;
00312                               while (i)
00313                                   this->p[--i].~B();
00314                               allocator_.deallocate(this->p,this->n); 
00315                           }
00316                           if (nblocks>0) {
00317                               size_type i=nblocks;
00318                               while (i)
00319                                   block[--i].~window_type();
00320                               windowAllocator_.deallocate(block,nblocks);
00321                           }
00322 
00323                           // allocate the big array in the base class
00324                           this->n = a.n;
00325                           if (this->n>0) 
00326                                 {
00327                                   // allocate and construct objects
00328                                   this->p = allocator_.allocate(this->n);
00329                                   new (this->p) B[this->n];
00330                                 }
00331                           else
00332                                 {
00333                                   this->n = 0;
00334                                   this->p = 0;
00335                                 }
00336 
00337                           // we can allocate the windows now
00338                           nblocks = a.nblocks;
00339                           if (nblocks>0)
00340                                 { 
00341                                   // alloc
00342                                   block = windowAllocator_.allocate(nblocks);
00343                                   new (block) window_type[nblocks];
00344                                 }
00345                           else
00346                                 {
00347                                   nblocks = 0;
00348                                   block = 0;;
00349                                 }
00350                         }
00351 
00352                   // copy block structure, might be different although
00353                   // sizes are the same !
00354                   if (nblocks>0)
00355                         {
00356                           block[0].set(a.block[0].getsize(),this->p); // first block
00357                           for (size_type i=1; i<nblocks; ++i)               // and the rest
00358                                 block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
00359                         }
00360 
00361                   // and copy the data
00362                   for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00363                 }
00364 
00365           // and we have a usable vector
00366           initialized = true;
00367 
00368           return *this; // Gebe Referenz zurueck damit a=b=c; klappt
00369         }
00370 
00371 
00372         //===== assignment from scalar
00373 
00375         VariableBlockVector& operator= (const field_type& k)
00376         {
00377           (static_cast<block_vector_unmanaged<B,A>&>(*this)) = k;
00378           return *this;   
00379         }
00380 
00381 
00382         //===== the creation interface
00383 
00385         class CreateIterator 
00386         {
00387         public:
00389           CreateIterator (VariableBlockVector& _v, int _i) : v(_v)
00390           {
00391                 i = _i;
00392                 k = 0;
00393                 n = 0;
00394           }
00395 
00397           CreateIterator& operator++()
00398           {
00399                 // we are at block i and the blocks size is known
00400 
00401                 // set the blocks size to current k
00402                 v.block[i].setsize(k);
00403 
00404                 // accumulate total size
00405                 n += k;
00406 
00407                 // go to next block
00408                 ++i;
00409 
00410                 // reset block size
00411                 k = 0;
00412 
00413                 // if we are past the last block, finish off
00414                 if (i==v.nblocks) 
00415                   {
00416                         // now we can allocate the big array in the base class of v
00417                         v.n = n;
00418                         if (n>0) 
00419                           {
00420                                 // allocate and construct objects
00421                                 v.p = v.allocator_.allocate(n);
00422                                 new (v.p) B[n];
00423                           }
00424                         else
00425                           {
00426                                 v.n = 0;
00427                                 v.p = 0;
00428                           }
00429                         
00430                         // and we set the window pointer
00431                         if (v.nblocks>0)
00432                         {
00433                           v.block[0].setptr(v.p);         // pointer tofirst block
00434                           for (size_type j=1; j<v.nblocks; ++j) // and the rest
00435                                 v.block[j].setptr(v.block[j-1].getptr()+v.block[j-1].getsize());
00436                         }
00437 
00438                         // and the vector is ready
00439                         v.initialized = true;
00440 
00441                         //std::cout << "made vbvector with " << v.n << " components" << std::endl;
00442                   }
00443 
00444                 return *this;
00445           }
00446           
00448           bool operator!= (const CreateIterator& it) const
00449           {
00450         return (i!=it.i) || (&v!=&it.v);
00451           }
00452 
00454           bool operator== (const CreateIterator& it) const
00455           {
00456         return (i==it.i) && (&v==&it.v);
00457           }
00458 
00460           size_type index () const
00461           {
00462         return i;
00463           }
00464 
00466           void setblocksize (size_type _k)
00467           {
00468                 k = _k;
00469           }
00470 
00471         private:
00472           VariableBlockVector& v; // my vector
00473           size_type i;                  // current block to be defined
00474           size_type k;                  // size of current block to be defined
00475           size_type n;                  // total number of elements to be allocated
00476         };
00477 
00478         // CreateIterator wants to set all the arrays ...
00479         friend class CreateIterator;
00480 
00482         CreateIterator createbegin ()
00483         {
00484 #ifdef DUNE_ISTL_WITH_CHECKING
00485           if (initialized) DUNE_THROW(ISTLError,"no CreateIterator in initialized state");
00486 #endif
00487           return CreateIterator(*this,0);
00488         }
00489 
00491         CreateIterator createend ()
00492         {
00493           return CreateIterator(*this,nblocks);
00494         }
00495 
00496 
00497         //===== access to components
00498         // has to be overwritten from base class because it must
00499         // return access to the windows
00500 
00502         window_type& operator[] (size_type i)
00503         {
00504 #ifdef DUNE_ISTL_WITH_CHECKING
00505           if (i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
00506 #endif
00507           return block[i];
00508         }
00509 
00511         const window_type& operator[] (size_type i) const
00512         {
00513 #ifdef DUNE_ISTL_WITH_CHECKING
00514           if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
00515 #endif
00516           return block[i];
00517         }
00518 
00519         // forward declaration
00520         class ConstIterator;
00521 
00523         class Iterator 
00524         {
00525         public:
00527           Iterator ()
00528           {       
00529                 p = 0;
00530                 i = 0;
00531           }
00532 
00534           Iterator (window_type* _p, size_type _i) : p(_p), i(_i)
00535           {       }
00536 
00538           Iterator& operator++()
00539           {
00540         ++i;
00541                 return *this;
00542           }
00543           
00545           Iterator& operator--()
00546           {
00547         --i;
00548                 return *this;
00549           }
00550           
00552           bool operator== (const Iterator& it) const
00553           {
00554         return (p+i)==(it.p+it.i);
00555           }
00556 
00558           bool operator!= (const Iterator& it) const
00559           {
00560         return (p+i)!=(it.p+it.i);
00561           }
00562 
00564           bool operator== (const ConstIterator& it) const
00565           {
00566                 return (p+i)==(it.p+it.i);
00567           }
00568 
00570           bool operator!= (const ConstIterator& it) const
00571           {
00572         return (p+i)!=(it.p+it.i);
00573           }
00574 
00576           window_type& operator* () const
00577           {
00578         return p[i];
00579           }
00580 
00582           window_type* operator-> () const
00583           {
00584         return p+i;
00585           }
00586 
00587           // return index corresponding to pointer
00588           size_type index () const
00589           {
00590                 return i;
00591           }
00592 
00593           friend class ConstIterator;
00594 
00595         private:
00596           window_type* p;
00597           size_type i;
00598         };
00599 
00601         Iterator begin ()
00602         {
00603           return Iterator(block,0);
00604         }
00605 
00607         Iterator end ()
00608         {
00609           return Iterator(block,nblocks);
00610         }
00611 
00616         Iterator rbegin() DUNE_DEPRECATED
00617         {
00618           return beforeEnd();
00619         }
00620 
00623         Iterator beforeEnd ()
00624         {
00625           return Iterator(block,nblocks-1);
00626         }
00627 
00632         Iterator rend ()  DUNE_DEPRECATED
00633         {
00634            return beforeBegin();
00635         }
00636 
00639         Iterator beforeBegin ()
00640         {
00641           return Iterator(block,-1);
00642         }
00643 
00645         Iterator find (size_type i)
00646         {
00647           if (i>=0 && i<nblocks)
00648                 return Iterator(block,i);
00649           else
00650                 return Iterator(block,nblocks);
00651         }
00652 
00654         ConstIterator find (size_type i) const
00655         {
00656           if (i>=0 && i<nblocks)
00657                 return ConstIterator(block,i);
00658           else
00659                 return ConstIterator(block,nblocks);
00660         }
00661 
00663         class ConstIterator 
00664         {
00665         public:
00667           ConstIterator ()
00668           {
00669                 p = 0;
00670                 i = 0;
00671           }
00672 
00674           ConstIterator (const window_type* _p, size_type _i) : p(_p), i(_i)
00675           {       }
00676 
00678           ConstIterator (const Iterator& it) : p(it.p), i(it.i)
00679           {       }
00680 
00682           ConstIterator& operator++()
00683           {
00684         ++i;
00685                 return *this;
00686           }
00687           
00689           ConstIterator& operator--()
00690           {
00691         --i;
00692                 return *this;
00693           }
00694           
00696           bool operator== (const ConstIterator& it) const
00697           {
00698         return (p+i)==(it.p+it.i);
00699           }
00700 
00702           bool operator!= (const ConstIterator& it) const
00703           {
00704         return (p+i)!=(it.p+it.i);
00705           }
00706 
00708           bool operator== (const Iterator& it) const
00709           {
00710         return (p+i)==(it.p+it.i);
00711           }
00712 
00714           bool operator!= (const Iterator& it) const
00715           {
00716                 return (p+i)!=(it.p+it.i);
00717           }
00718 
00720           const window_type& operator* () const
00721           {
00722         return p[i];
00723           }
00724 
00726           const window_type* operator-> () const
00727           {
00728         return p+i;
00729           }
00730 
00731           // return index corresponding to pointer
00732           size_type index () const
00733           {
00734                 return i;
00735           }
00736 
00737           friend class Iterator;
00738 
00739         private:
00740           const window_type* p;
00741           size_type i;
00742         };
00743 
00745         ConstIterator begin () const
00746         {
00747           return ConstIterator(block,0);
00748         }
00749 
00751         ConstIterator end () const
00752         {
00753           return ConstIterator(block,nblocks);
00754         }
00755 
00760         ConstIterator rbegin() const DUNE_DEPRECATED
00761         {
00762            return beforeEnd();
00763         }
00764 
00767         ConstIterator beforeEnd() const
00768         {
00769           return ConstIterator(block,nblocks-1);
00770         }
00771 
00773         ConstIterator rend () const
00774         {
00775           return ConstIterator(block,-1);
00776         }
00777 
00778 
00779         //===== sizes
00780 
00782         size_type N () const
00783         {
00784           return nblocks;
00785         }
00786 
00787 
00788   private:
00789         size_type nblocks;        // number of blocks in vector
00790         window_type* block; // array of blocks pointing to the array in the base class
00791         bool initialized;   // true if vector has been initialized
00792 
00793       A allocator_;
00794 
00795       typename A::template rebind<window_type>::other windowAllocator_;
00796   };
00797 
00798 
00799 
00802 } // end namespace
00803 
00804 #endif