dune-istl  2.1.1
basearray.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 #ifndef DUNE_BASEARRAY_HH
00004 #define DUNE_BASEARRAY_HH
00005 
00006 #include "assert.h"
00007 #include<cmath>
00008 #include<complex>
00009 #include<cstddef>
00010 #include<memory>
00011 
00012 #include "istlexception.hh"
00013 #include <dune/common/iteratorfacades.hh>
00014 
00019 namespace Dune {
00020    
00039   template<class B, class A=std::allocator<B> >
00040   class base_array_unmanaged
00041   {
00042   public:
00043 
00044         //===== type definitions and constants
00045 
00047         typedef B member_type;
00048 
00050         typedef A allocator_type;
00051 
00053     typedef typename A::size_type size_type;
00054     
00055 
00056         //===== access to components
00057 
00059         B& operator[] (size_type i)
00060         {
00061 #ifdef DUNE_ISTL_WITH_CHECKING
00062           if (i>=n) DUNE_THROW(ISTLError,"index out of range");
00063 #endif
00064           return p[i];
00065         }
00066 
00068         const B& operator[] (size_type i) const
00069         {
00070 #ifdef DUNE_ISTL_WITH_CHECKING
00071           if (i>=n) DUNE_THROW(ISTLError,"index out of range");
00072 #endif
00073           return p[i];
00074         }
00075 
00077     template<class T>
00078     class RealIterator 
00079       :  public RandomAccessIteratorFacade<RealIterator<T>, T>
00080     {
00081     public:
00083       typedef typename remove_const<T>::type ValueType;
00084       
00085       friend class RandomAccessIteratorFacade<RealIterator<const ValueType>, const ValueType>;
00086       friend class RandomAccessIteratorFacade<RealIterator<ValueType>, ValueType>;
00087       friend class RealIterator<const ValueType>;
00088       friend class RealIterator<ValueType>;
00089       
00091       RealIterator ()
00092         : p(0), i(0)
00093       {}
00094       
00095       RealIterator (const B* _p, B* _i) : p(_p), i(_i)
00096       {   }
00097       
00098       RealIterator(const RealIterator<ValueType>& it)
00099         : p(it.p), i(it.i)
00100       {}
00101            
00103       size_type index () const
00104       {
00105         return i-p;
00106       }
00107             
00109       bool equals (const RealIterator<ValueType>& other) const
00110       {
00111         assert(other.p==p);
00112         return i==other.i;
00113       }
00114       
00116       bool equals (const RealIterator<const ValueType>& other) const
00117       {
00118         assert(other.p==p);
00119         return i==other.i;
00120       }
00121 
00122       std::ptrdiff_t distanceTo(const RealIterator& o) const
00123       {
00124         return o.i-i;
00125       }
00126 
00127     private:
00129       void increment()
00130       {
00131         ++i;
00132       }
00133       
00135       void decrement()
00136       {
00137         --i;
00138       }
00139 
00141       B& dereference () const
00142       {
00143         return *i;
00144       }
00145 
00146       void advance(std::ptrdiff_t d)
00147       {
00148         i+=d;
00149       }
00150       
00151       const B* p;
00152       B* i;
00153     };
00154 
00156     typedef RealIterator<B> iterator;
00157     
00158     
00160         iterator begin ()
00161         {
00162           return iterator(p,p);
00163         }
00164 
00166         iterator end ()
00167         {
00168           return iterator(p,p+n);
00169         }
00170 
00175     iterator rbegin() DUNE_DEPRECATED
00176     {
00177       return beforeEnd();
00178     }
00179 
00180 
00183         iterator beforeEnd ()
00184         {
00185           return iterator(p,p+n-1);
00186         }
00187 
00192     iterator rend ()  DUNE_DEPRECATED
00193     {
00194       return beforeBegin();
00195     }
00196 
00199         iterator beforeBegin ()
00200         {
00201           return iterator(p,p-1);
00202         }
00203 
00205         iterator find (size_type i)
00206         {
00207           if (i<n)
00208                 return iterator(p,p+i);
00209           else
00210                 return iterator(p,p+n);
00211         }
00212 
00214     typedef RealIterator<const B> const_iterator;
00215 
00217         const_iterator begin () const
00218         {
00219           return const_iterator(p,p+0);
00220         }
00221 
00223         const_iterator end () const
00224         {
00225           return const_iterator(p,p+n);
00226         }
00227 
00232     const_iterator rbegin() const DUNE_DEPRECATED
00233     {
00234       return beforeEnd();
00235     }
00236 
00239         const_iterator beforeEnd () const
00240         {
00241           return const_iterator(p,p+n-1);
00242         }
00243 
00248     const_iterator rend () const DUNE_DEPRECATED
00249     {
00250       return beforeBegin();
00251     }
00252     
00255         const_iterator beforeBegin () const
00256         {
00257           return const_iterator(p,p-1);
00258         }
00259 
00261         const_iterator find (size_type i) const
00262         {
00263           if (i<n)
00264                 return const_iterator(p,p+i);
00265           else
00266                 return const_iterator(p,p+n);
00267         }
00268 
00269 
00270         //===== sizes
00271 
00273         size_type size () const
00274         {
00275           return n;
00276         }
00277 
00278   protected:
00280     base_array_unmanaged ()
00281       : n(0), p(0)
00282     {}
00284     base_array_unmanaged (size_type n_, B* p_)
00285       : n(n_), p(p_)
00286     {}
00287         size_type n; // number of elements in array
00288         B *p;  // pointer to dynamically allocated built-in array
00289   };
00290 
00291 
00292 
00307   template<class B, class A=std::allocator<B> >
00308   class base_array_window : public base_array_unmanaged<B,A>
00309   {
00310   public:
00311 
00312         //===== type definitions and constants
00313 
00315         typedef B member_type;
00316 
00318         typedef A allocator_type;
00319 
00321         typedef typename base_array_unmanaged<B,A>::iterator iterator;
00322 
00324         typedef typename base_array_unmanaged<B,A>::const_iterator const_iterator;
00325 
00327     typedef typename base_array_unmanaged<B,A>::size_type size_type;
00328 
00330     typedef typename A::difference_type difference_type;
00331     
00332         //===== constructors and such
00333 
00335     base_array_window ()
00336       : base_array_unmanaged<B,A>()
00337     {   }
00338 
00340     base_array_window (B* _p, size_type _n)
00341       : base_array_unmanaged<B,A>(_n ,_p)
00342     {}
00343 
00344         //===== window manipulation methods
00345 
00347         void set (size_type _n, B* _p)
00348         {
00349           this->n = _n;
00350           this->p = _p;
00351         }
00352 
00354         void advance (difference_type newsize)
00355         {
00356           this->p += this->n;
00357           this->n = newsize;
00358         }
00359 
00361         void move (difference_type offset, size_type newsize)
00362         {
00363           this->p += offset;
00364           this->n = newsize;
00365         }
00366 
00368         void move (difference_type offset)
00369         {
00370           this->p += offset;
00371         }
00372 
00374         B* getptr ()
00375         {
00376           return this->p;
00377         }
00378   };
00379 
00380 
00381 
00397   template<class B, class A=std::allocator<B> >
00398   class base_array : public base_array_unmanaged<B,A>
00399   {
00400   public:
00401 
00402         //===== type definitions and constants
00403 
00405         typedef B member_type;
00406 
00408         typedef A allocator_type;
00409 
00411         typedef typename base_array_unmanaged<B,A>::iterator iterator;
00412 
00414         typedef typename base_array_unmanaged<B,A>::const_iterator const_iterator;
00415    
00417     typedef typename base_array_unmanaged<B,A>::size_type size_type;
00418 
00420     typedef typename A::difference_type difference_type;
00421     
00422         //===== constructors and such
00423 
00425     base_array ()
00426       : base_array_unmanaged<B,A>()
00427     {}
00428 
00430         base_array (size_type _n)
00431           : base_array_unmanaged<B,A>(_n, 0)
00432         {
00433             if (this->n>0) {
00434                 this->p = allocator_.allocate(this->n);
00435                 new (this->p) B[this->n];
00436             } else
00437                 {
00438                   this->n = 0;
00439                   this->p = 0;
00440                 }
00441         }
00442 
00444         base_array (const base_array& a)
00445         {
00446           // allocate memory with same size as a
00447           this->n = a.n;
00448 
00449           if (this->n>0) {
00450               this->p = allocator_.allocate(this->n);
00451               new (this->p) B[this->n];
00452           } else
00453                 {
00454                   this->n = 0;
00455                   this->p = 0;
00456                 }
00457 
00458           // and copy elements
00459           for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00460         }
00461 
00463         base_array (const base_array_unmanaged<B,A>& _a) 
00464         {
00465           const base_array& a = static_cast<const base_array&>(_a);
00466 
00467           // allocate memory with same size as a
00468           this->n = a.n;
00469           if (this->n>0) {
00470                 this->p = allocator_.allocate(this->n);
00471                 new (this->p) B[this->n];
00472           } else
00473                 {
00474                   this->n = 0;
00475                   this->p = 0;
00476                 }
00477 
00478           // and copy elements
00479           for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00480         }
00481 
00482 
00484         ~base_array () 
00485         { 
00486             if (this->n>0) {
00487                 int i=this->n;
00488                 while (i)
00489                     this->p[--i].~B();
00490                 allocator_.deallocate(this->p,this->n);
00491             }
00492         }
00493 
00495         void resize (size_type _n)
00496         {
00497           if (this->n==_n) return;
00498 
00499           if (this->n>0) {
00500               int i=this->n;
00501               while (i)
00502                   this->p[--i].~B();
00503               allocator_.deallocate(this->p,this->n); 
00504           }
00505           this->n = _n;
00506           if (this->n>0) {
00507                 this->p = allocator_.allocate(this->n);
00508                 new (this->p) B[this->n];
00509           } else
00510                 {
00511                   this->n = 0;
00512                   this->p = 0;
00513                 }
00514         }
00515 
00517         base_array& operator= (const base_array& a)
00518         {
00519           if (&a!=this) // check if this and a are different objects
00520                 {
00521                   // adjust size of array
00522                   if (this->n!=a.n) // check if size is different
00523                         {
00524                             if (this->n>0) {
00525                                 int i=this->n;
00526                                 while (i)
00527                                     this->p[--i].~B();
00528                                 allocator_.deallocate(this->p,this->n); // delete old memory
00529                             }
00530                           this->n = a.n;
00531                           if (this->n>0) {
00532                                 this->p = allocator_.allocate(this->n);
00533                                 new (this->p) B[this->n];
00534                           } else
00535                                 {
00536                                   this->n = 0;
00537                                   this->p = 0;
00538                                 }
00539                         }
00540                   // copy data
00541                   for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
00542                 }
00543           return *this;
00544         }
00545 
00547         base_array& operator= (const base_array_unmanaged<B,A>& a)
00548         {
00549           return this->operator=(static_cast<const base_array&>(a));
00550         }
00551 
00552         protected:
00553 
00554         A allocator_;
00555   };
00556 
00557 
00558 
00559 
00579   template<class B, class A=std::allocator<B> >
00580   class compressed_base_array_unmanaged
00581   {
00582   public:
00583 
00584         //===== type definitions and constants
00585 
00587         typedef B member_type;
00588 
00590         typedef A allocator_type;
00591 
00593     typedef typename A::size_type size_type;
00594 
00595         //===== access to components
00596 
00598         B& operator[] (size_type i)
00599         {
00600           size_type l=0, r=n-1;
00601           while (l<r)
00602                 {
00603                   size_type q = (l+r)/2;
00604                   if (i <= j[q]) r=q;
00605                   else l = q+1;
00606                 }
00607           if (j[l]!=i){
00608              DUNE_THROW(ISTLError,"index "<<i<<" not in compressed array");
00609           }       
00610           return p[l];
00611         }
00612 
00614         const B& operator[] (size_type i) const
00615         {
00616           size_type l=0, r=n-1;
00617           while (l<r)
00618                 {
00619                   size_type q = (l+r)/2;
00620                   if (i <= j[q]) r=q;
00621                   else l = q+1;
00622                 }
00623           if (j[l]!=i){
00624              DUNE_THROW(ISTLError,"index "<<i<<" not in compressed array");
00625           }
00626           return p[l];
00627         }
00628 
00630     template<class T>
00631     class RealIterator
00632       : public BidirectionalIteratorFacade<RealIterator<T>, T>
00633         {
00634         public:
00636           typedef typename remove_const<T>::type ValueType;
00637 
00638           friend class BidirectionalIteratorFacade<RealIterator<const ValueType>, const ValueType>;
00639           friend class BidirectionalIteratorFacade<RealIterator<ValueType>, ValueType>;
00640           friend class RealIterator<const ValueType>;
00641           friend class RealIterator<ValueType>;
00642 
00644           RealIterator ()
00645             : p(0), j(0), i(0)
00646           {}
00647 
00649           RealIterator (B* _p, size_type* _j, size_type _i) 
00650             : p(_p), j(_j), i(_i)
00651           {       }
00652 
00656           RealIterator(const RealIterator<ValueType>& it)
00657             : p(it.p), j(it.j), i(it.i)
00658           {}
00659           
00660           
00662           bool equals (const RealIterator<ValueType>& it) const
00663           {
00664                 assert(p==it.p);
00665                 return (i)==(it.i);
00666           }
00667 
00669           bool equals (const RealIterator<const ValueType>& it) const
00670           {
00671                 assert(p==it.p);
00672                 return (i)==(it.i);
00673           }
00674 
00675 
00677           size_type index () const
00678           {
00679                 return j[i];
00680           }
00681 
00683           void setindex (size_type k)
00684           {
00685                 return j[i] = k;
00686           }
00687           
00695           size_type offset () const
00696           {
00697             return i;
00698           }
00699           
00700         private:
00702           void increment()
00703           {
00704             ++i;
00705           }
00706           
00708           void decrement()
00709           {
00710             --i;
00711           }
00712 
00714           B& dereference () const
00715           {
00716             return p[i];
00717           }
00718 
00719           B* p;
00720           size_type* j;
00721           size_type i;
00722         };
00723 
00725     typedef RealIterator<B> iterator;
00726     
00728         iterator begin ()
00729         {
00730           return iterator(p,j,0);
00731         }
00732 
00734         iterator end ()
00735         {
00736           return iterator(p,j,n);
00737         }
00738 
00743     iterator rbegin() DUNE_DEPRECATED
00744     {
00745       return beforeEnd();
00746     }
00747 
00750         iterator beforeEnd ()
00751         {
00752           return iterator(p,j,n-1);
00753         }
00754 
00759     iterator rend ()  DUNE_DEPRECATED
00760     {
00761       return beforeBegin();
00762     }
00763 
00766         iterator beforeBegin ()
00767         {
00768           return iterator(p,j,-1);
00769         }
00770 
00772         iterator find (size_type i)
00773         {
00774           size_type l=0, r=n-1;
00775           while (l<r)
00776                 {
00777                   size_type q = (l+r)/2;
00778                   if (i <= j[q]) r=q;
00779                   else l = q+1;
00780                 }
00781 
00782           if (n && i==j[l])
00783                 return iterator(p,j,l);
00784           else
00785                 return iterator(p,j,n);
00786         }
00787 
00789     typedef RealIterator<const B> const_iterator;
00790     
00792         const_iterator begin () const
00793         {
00794           return const_iterator(p,j,0);
00795         }
00796 
00798         const_iterator end () const
00799         {
00800           return const_iterator(p,j,n);
00801         }
00802 
00807     const_iterator rbegin() const DUNE_DEPRECATED
00808     {
00809       return beforeEnd();
00810     }
00811 
00814         const_iterator beforeEnd () const
00815         {
00816           return const_iterator(p,j,n-1);
00817         }
00818 
00823     const_iterator rend () const DUNE_DEPRECATED
00824     {
00825       return beforeBegin();
00826     }
00827     
00830         const_iterator beforeBegin () const
00831         {
00832           return const_iterator(p,j,-1);
00833         }
00834 
00836         const_iterator find (size_type i) const
00837         {
00838           size_type l=0, r=n-1;
00839           while (l<r)
00840                 {
00841                   size_type q = (l+r)/2;
00842                   if (i <= j[q]) r=q;
00843                   else l = q+1;
00844                 }
00845 
00846           if (n && i==j[l])
00847                 return const_iterator(p,j,l);
00848           else
00849                 return const_iterator(p,j,n);
00850         }
00851 
00852         //===== sizes
00853 
00855         size_type size () const
00856         {
00857           return n;
00858         }
00859 
00860   protected:
00862         compressed_base_array_unmanaged ()
00863           : n(0), p(0), j(0)
00864         {}
00865 
00866         size_type n;  // number of elements in array
00867         B *p;   // pointer to dynamically allocated built-in array
00868         size_type* j; // the index set
00869   };
00870 
00871 } // end namespace
00872 
00873 #endif