dune-istl
2.1.1
|
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