fmatrix.hh

Go to the documentation of this file.
00001 // $Id: fmatrix.hh 5004 2007-10-05 09:55:44Z christi $
00002 #ifndef DUNE_FMATRIX_HH
00003 #define DUNE_FMATRIX_HH
00004 
00005 #include<cmath>
00006 #include<cstddef>
00007 #include<complex>
00008 #include<iostream>
00009 #include "exceptions.hh"
00010 #include "fvector.hh"
00011 #include "precision.hh"
00012 
00013 namespace Dune {
00014    
00026   template<class K, int n, int m> class FieldMatrix;
00027   
00029   class FMatrixError : public Exception {};
00030 
00031   // conjugate komplex does nothing for non-complex types
00032   template<class K>
00033   inline K fm_ck (const K& k)
00034   {
00035         return k;
00036   }
00037 
00038   // conjugate komplex
00039   template<class K>
00040   inline std::complex<K> fm_ck (const std::complex<K>& c)
00041   {
00042         return std::complex<K>(c.real(),-c.imag());
00043   }
00044 
00055   template<class K, int n, int m>
00056   class FieldMatrix
00057   {
00058   public:
00059         // standard constructor and everything is sufficient ...
00060 
00061         //===== type definitions and constants
00062 
00064         typedef K field_type;
00065 
00067         typedef K block_type;
00068     
00070     typedef std::size_t size_type;
00071     
00073         enum {
00075           blocklevel = 1
00076         };
00077 
00079         typedef FieldVector<K,m> row_type; 
00080 
00082         enum {
00084           rows = n, 
00086           cols = m
00087         };
00088 
00089         //===== constructors
00092         FieldMatrix () {}
00093 
00096         FieldMatrix (const K& k)
00097         {
00098           for (size_type i=0; i<n; i++) p[i] = k;
00099         }
00100 
00101         //===== random access interface to rows of the matrix
00102 
00104         row_type& operator[] (size_type i)
00105         {
00106 #ifdef DUNE_FMatrix_WITH_CHECKING
00107           if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00108 #endif
00109           return p[i];
00110         }
00111 
00113         const row_type& operator[] (size_type i) const
00114         {
00115 #ifdef DUNE_FMatrix_WITH_CHECKING
00116           if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00117 #endif
00118           return p[i];
00119         }
00120 
00121 
00122         //===== iterator interface to rows of the matrix
00124     typedef FieldIterator<FieldMatrix<K,n,m>,row_type> Iterator;
00126     typedef Iterator iterator;
00128         typedef Iterator RowIterator;
00130         typedef typename row_type::Iterator ColIterator;
00131 
00133         Iterator begin ()
00134         {
00135           return Iterator(*this,0);
00136         }
00137           
00139         Iterator end ()
00140         {
00141           return Iterator(*this,n);
00142         }
00143 
00145         Iterator rbegin ()
00146         {
00147           return Iterator(*this,n-1);
00148         }
00149           
00151         Iterator rend ()
00152         {
00153           return Iterator(*this,-1);
00154         }
00155 
00157     typedef FieldIterator<const FieldMatrix<K,n,m>,const row_type> ConstIterator;
00159     typedef ConstIterator const_iterator;
00161         typedef ConstIterator ConstRowIterator;
00163         typedef typename row_type::ConstIterator ConstColIterator;
00164 
00166         ConstIterator begin () const
00167         {
00168           return ConstIterator(*this,0);
00169         }
00170           
00172         ConstIterator end () const
00173         {
00174           return ConstIterator(*this,n);
00175         }
00176 
00178         ConstIterator rbegin () const
00179         {
00180           return ConstIterator(*this,n-1);
00181         }
00182           
00184         ConstIterator rend () const
00185         {
00186           return ConstIterator(*this,-1);
00187         }
00188 
00189         //===== assignment from scalar
00190         FieldMatrix& operator= (const K& k)
00191         {
00192             for (size_type i=0; i<n; i++)
00193                 p[i] = k;
00194           return *this;   
00195         }
00196 
00197         //===== vector space arithmetic
00198 
00200         FieldMatrix& operator+= (const FieldMatrix& y)
00201         {
00202             for (size_type i=0; i<n; i++)
00203                 p[i] += y.p[i];
00204           return *this;
00205         }
00206 
00208         FieldMatrix& operator-= (const FieldMatrix& y)
00209         {
00210             for (size_type i=0; i<n; i++)
00211                 p[i] -= y.p[i];
00212           return *this;
00213         }
00214 
00216         FieldMatrix& operator*= (const K& k)
00217         {
00218             for (size_type i=0; i<n; i++)
00219                 p[i] *= k;
00220           return *this;
00221         }
00222 
00224         FieldMatrix& operator/= (const K& k)
00225         {
00226             for (int i=0; i<n; i++)
00227                 p[i] /= k;
00228           return *this;
00229         }
00230 
00231         //===== linear maps
00232    
00234         template<class X, class Y>
00235         void umv (const X& x, Y& y) const
00236         {
00237 #ifdef DUNE_FMatrix_WITH_CHECKING
00238           if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00239           if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00240 #endif
00241           for (size_type i=0; i<n; i++)
00242               for (size_type j=0; j<m; j++)
00243                   y[i] += (*this)[i][j] * x[j];
00244         }
00245 
00247         template<class X, class Y>
00248         void umtv (const X& x, Y& y) const
00249         {
00250 #ifdef DUNE_FMatrix_WITH_CHECKING
00251           if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00252           if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00253 #endif
00254           
00255           for (size_type i=0; i<n; i++)
00256                   for (size_type j=0; j<m; j++)
00257                         y[j] += p[i][j]*x[i];
00258         }
00259 
00261         template<class X, class Y>
00262         void umhv (const X& x, Y& y) const
00263         {
00264 #ifdef DUNE_FMatrix_WITH_CHECKING
00265           if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00266           if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00267 #endif
00268           
00269           for (size_type i=0; i<n; i++)
00270                   for (size_type j=0; j<m; j++)
00271                         y[j] += fm_ck(p[i][j])*x[i];
00272         }
00273 
00275         template<class X, class Y>
00276         void mmv (const X& x, Y& y) const
00277         {
00278 #ifdef DUNE_FMatrix_WITH_CHECKING
00279           if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00280           if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00281 #endif
00282           for (size_type i=0; i<n; i++)
00283               for (size_type j=0; j<m; j++)
00284                   y[i] -= (*this)[i][j] * x[j];
00285         }
00286 
00288         template<class X, class Y>
00289         void mmtv (const X& x, Y& y) const
00290         {
00291 #ifdef DUNE_FMatrix_WITH_CHECKING
00292           if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00293           if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00294 #endif
00295           
00296           for (size_type i=0; i<n; i++)
00297                   for (size_type j=0; j<m; j++)
00298                         y[j] -= p[i][j]*x[i];
00299         }
00300 
00302         template<class X, class Y>
00303         void mmhv (const X& x, Y& y) const
00304         {
00305 #ifdef DUNE_FMatrix_WITH_CHECKING
00306           if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00307           if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00308 #endif
00309           
00310           for (size_type i=0; i<n; i++)
00311                   for (size_type j=0; j<m; j++)
00312                         y[j] -= fm_ck(p[i][j])*x[i];
00313         }
00314 
00316         template<class X, class Y>
00317         void usmv (const K& alpha, const X& x, Y& y) const
00318         {
00319 #ifdef DUNE_FMatrix_WITH_CHECKING
00320           if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00321           if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00322 #endif
00323           for (size_type i=0; i<n; i++)
00324               for (size_type j=0; j<m; j++)
00325                   y[i] += alpha * (*this)[i][j] * x[j];
00326         }
00327 
00329         template<class X, class Y>
00330         void usmtv (const K& alpha, const X& x, Y& y) const
00331         {
00332 #ifdef DUNE_FMatrix_WITH_CHECKING
00333           if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00334           if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00335 #endif
00336           
00337           for (size_type i=0; i<n; i++)
00338                   for (size_type j=0; j<m; j++)
00339                         y[j] += alpha*p[i][j]*x[i];
00340         }
00341 
00343         template<class X, class Y>
00344         void usmhv (const K& alpha, const X& x, Y& y) const
00345         {
00346 #ifdef DUNE_FMatrix_WITH_CHECKING
00347           if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00348           if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00349 #endif
00350           
00351           for (size_type i=0; i<n; i++)
00352                   for (size_type j=0; j<m; j++)
00353                         y[j] += alpha*fm_ck(p[i][j])*x[i];
00354         }
00355 
00356         //===== norms
00357 
00359     double frobenius_norm () const
00360         {
00361           double sum=0;
00362           for (size_type i=0; i<n; ++i) sum += p[i].two_norm2();
00363           return sqrt(sum);
00364         }
00365 
00367     double frobenius_norm2 () const
00368         {
00369           double sum=0;
00370           for (size_type i=0; i<n; ++i) sum += p[i].two_norm2();
00371           return sum;
00372         }
00373 
00375     double infinity_norm () const
00376         {
00377           double max=0;
00378           for (size_type i=0; i<n; ++i) max = std::max(max,p[i].one_norm());
00379           return max;
00380         }
00381 
00383         double infinity_norm_real () const
00384         {
00385           double max=0;
00386           for (size_type i=0; i<n; ++i) max = std::max(max,p[i].one_norm_real());
00387           return max;
00388         }
00389 
00390         //===== solve
00391 
00396         template<class V>
00397         void solve (V& x, const V& b) const;
00398 
00403       void invert();
00404 
00406       K determinant () const;
00407 
00409         FieldMatrix& leftmultiply (const FieldMatrix<K,n,n>& M)
00410         {
00411             FieldMatrix<K,n,m> C(*this);
00412             
00413             for (size_type i=0; i<n; i++)
00414                 for (size_type j=0; j<m; j++) {
00415                     (*this)[i][j] = 0;
00416                     for (size_type k=0; k<n; k++)
00417                         (*this)[i][j] += M[i][k]*C[k][j];
00418                 }
00419 
00420           return *this;
00421         }
00422 
00424         FieldMatrix& rightmultiply (const FieldMatrix<K,m,m>& M)
00425         {
00426             FieldMatrix<K,n,m> C(*this);
00427 
00428             for (size_type i=0; i<n; i++)
00429                 for (size_type j=0; j<m; j++) {
00430                     (*this)[i][j] = 0;
00431                     for (size_type k=0; k<m; k++)
00432                         (*this)[i][j] += C[i][k]*M[k][j];
00433                 }
00434             return *this;
00435         }
00436 
00437 
00438         //===== sizes
00439 
00441         size_type N () const
00442         {
00443           return n;
00444         }
00445 
00447         size_type M () const
00448         {
00449           return m;
00450         }
00451 
00453         size_type rowdim (size_type r) const
00454         {
00455           return 1;
00456         }
00457 
00459         size_type coldim (size_type c) const
00460         {
00461           return 1;
00462         }
00463 
00465         size_type rowdim () const
00466         {
00467           return n;
00468         }
00469 
00471         size_type coldim () const
00472         {
00473           return m;
00474         }
00475 
00476         //===== query
00477         
00479         bool exists (size_type i, size_type j) const
00480         {
00481 #ifdef DUNE_FMatrix_WITH_CHECKING
00482           if (i<0 || i>=n) DUNE_THROW(FMatrixError,"row index out of range");
00483           if (j<0 || j>=m) DUNE_THROW(FMatrixError,"column index out of range");
00484 #endif
00485           return true;
00486         }
00487 
00488         //===== conversion operator
00489 
00491       friend std::ostream& operator<< (std::ostream& s, const FieldMatrix<K,n,m>& a)
00492       {
00493           for (size_type i=0; i<n; i++)
00494               s << a.p[i] << std::endl;
00495           return s;
00496       }
00497 
00498   private:
00499         // the data, very simply a built in array with row-wise ordering
00500         row_type p[(n > 0) ? n : 1]; 
00501 
00502     struct ElimPivot
00503     {
00504       ElimPivot(size_type pivot[n]);
00505       
00506       void swap(int i, int j);
00507       
00508       template<typename T>
00509       void operator()(const T&, int k, int i)
00510       {}
00511       
00512       size_type* pivot_;
00513     };
00514 
00515     template<typename V>
00516     struct Elim
00517     {
00518       Elim(V& rhs);
00519       
00520       void swap(int i, int j);
00521       
00522       void operator()(const typename V::field_type& factor, int k, int i);
00523 
00524       V* rhs_;
00525     };
00526     
00527     template<class Func>
00528     void luDecomposition(FieldMatrix<K,n,n>& A, Func func) const;
00529   };
00530 
00531   template<typename K, int n, int m>
00532   FieldMatrix<K,n,m>::ElimPivot::ElimPivot(size_type pivot[n])
00533     : pivot_(pivot)
00534   {
00535     for(int i=0; i < n; ++i) pivot[i]=i;
00536   }
00537 
00538   template<typename K, int n, int m>
00539   void FieldMatrix<K,n,m>::ElimPivot::swap(int i, int j)
00540   {
00541     pivot_[i]=j;
00542   }
00543   
00544   template<typename K, int n, int m>
00545   template<typename V>
00546   FieldMatrix<K,n,m>::Elim<V>::Elim(V& rhs)
00547     : rhs_(&rhs)
00548   {}
00549   
00550    template<typename K, int n, int m>
00551    template<typename V>
00552    void FieldMatrix<K,n,m>::Elim<V>::swap(int i, int j)
00553    {
00554      std::swap((*rhs_)[i], (*rhs_)[j]);
00555    }
00556 
00557   template<typename K, int n, int m>
00558   template<typename V>
00559   void FieldMatrix<K,n,m>::
00560   Elim<V>::operator()(const typename V::field_type& factor, int k, int i)
00561   {
00562     (*rhs_)[k] -= factor*(*rhs_)[i];
00563   }
00564   template<typename K, int n, int m>
00565   template<typename Func>
00566   inline void FieldMatrix<K,n,m>::luDecomposition(FieldMatrix<K,n,n>& A, Func func) const
00567   {
00568     double norm=A.infinity_norm_real(); // for relative thresholds
00569     double pivthres = std::max(FMatrixPrecision<>::absolute_limit(),norm*FMatrixPrecision<>::pivoting_limit());
00570     double singthres = std::max(FMatrixPrecision<>::absolute_limit(),norm*FMatrixPrecision<>::singular_limit());
00571   
00572     // LU decomposition of A in A
00573     for (int i=0; i<n; i++)  // loop over all rows
00574       {
00575         double pivmax=fvmeta_absreal(A[i][i]);
00576       
00577         // pivoting ?
00578         if (pivmax<pivthres)
00579           {
00580             // compute maximum of column
00581             int imax=i; double abs;
00582             for (int k=i+1; k<n; k++)
00583               if ((abs=fvmeta_absreal(A[k][i]))>pivmax)
00584                 {
00585                   pivmax = abs; imax = k;
00586                 }
00587             // swap rows
00588             if (imax!=i){
00589               for (int j=0; j<n; j++)
00590                 std::swap(A[i][j],A[imax][j]);
00591               func.swap(i, imax); // swap the pivot or rhs
00592             }
00593           }
00594         
00595         // singular ?
00596         if (pivmax<singthres)
00597           DUNE_THROW(FMatrixError,"matrix is singular");                  
00598         
00599         // eliminate
00600         for (int k=i+1; k<n; k++)
00601           {
00602             K factor = A[k][i]/A[i][i];
00603             A[k][i] = factor;
00604             for (int j=i+1; j<n; j++)
00605               A[k][j] -= factor*A[i][j];
00606             func(factor, k, i);
00607           }
00608       }
00609   }
00610 
00611     template <class K, int n, int m>
00612     template <class V>
00613     inline void FieldMatrix<K,n,m>::solve(V& x, const V& b) const
00614     {
00615         // never mind those ifs, because they get optimized away
00616         if (n!=m)
00617             DUNE_THROW(FMatrixError, "Can't solve for a " << n << "x" << m << " matrix!");
00618 
00619         // no need to implement the case 1x1, because the whole matrix class is
00620         // specialized for this
00621         
00622         if (n==2) {
00623             
00624 #ifdef DUNE_FMatrix_WITH_CHECKING
00625             K detinv = p[0][0]*p[1][1]-p[0][1]*p[1][0];
00626             if (fvmeta_absreal(detinv)<FMatrixPrecision<>::absolute_limit())
00627                 DUNE_THROW(FMatrixError,"matrix is singular");
00628             detinv = 1/detinv;
00629 #else
00630             K detinv = 1.0/(p[0][0]*p[1][1]-p[0][1]*p[1][0]);
00631 #endif
00632             
00633             x[0] = detinv*(p[1][1]*b[0]-p[0][1]*b[1]);
00634             x[1] = detinv*(p[0][0]*b[1]-p[1][0]*b[0]);
00635 
00636         } else {
00637           V& rhs = x; // use x to store rhs
00638           rhs = b; // copy data
00639           Elim<V> elim(rhs);
00640           FieldMatrix<K,n,n> A(*this);
00641           
00642           luDecomposition(A, elim);
00643           
00644           // backsolve
00645           for(int i=n-1; i>=0; i--){
00646             for (int j=i+1; j<n; j++)
00647               rhs[i] -= A[i][j]*x[j];
00648             x[i] = rhs[i]/A[i][i];
00649           }
00650         }       
00651     }
00652 
00653     template <class K, int n, int m>
00654     inline void FieldMatrix<K,n,m>::invert()
00655     {
00656         // never mind those ifs, because they get optimized away
00657         if (n!=m)
00658             DUNE_THROW(FMatrixError, "Can't invert a " << n << "x" << m << " matrix!");
00659 
00660         // no need to implement the case 1x1, because the whole matrix class is
00661         // specialized for this
00662 
00663         if (n==2) {
00664 
00665             K detinv = p[0][0]*p[1][1]-p[0][1]*p[1][0];
00666 #ifdef DUNE_FMatrix_WITH_CHECKING
00667             if (fvmeta_absreal(detinv)<FMatrixPrecision<>::absolute_limit())
00668                 DUNE_THROW(FMatrixError,"matrix is singular");            
00669 #endif
00670             detinv = 1/detinv;
00671 
00672             K temp=p[0][0];
00673             p[0][0] =  p[1][1]*detinv;
00674             p[0][1] = -p[0][1]*detinv;
00675             p[1][0] = -p[1][0]*detinv;
00676             p[1][1] =  temp*detinv;
00677 
00678         } else {
00679 
00680             FieldMatrix<K,n,n> A(*this);
00681             size_type pivot[n];
00682             luDecomposition(A, ElimPivot(pivot));
00683             FieldMatrix<K,n,m>& L=A;
00684             FieldMatrix<K,n,m>& U=A;
00685             
00686             // initialize inverse
00687             *this=0;
00688             
00689             for(size_type i=0; i<n; ++i)
00690               p[i][i]=1;
00691             
00692             // L Y = I; multiple right hand sides
00693             for (size_type i=0; i<n; i++){
00694               for (size_type j=0; j<i; j++)
00695                 for (size_type k=0; k<n; k++)
00696                   p[i][k] -= L[i][j]*p[j][k];
00697             }
00698   
00699             // U A^{-1} = Y
00700             for (size_type i=n; i>0;){
00701               --i;
00702               for (size_type k=0; k<n; k++){
00703                 for (size_type j=i+1; j<n; j++)
00704                   p[i][k] -= U[i][j]*p[j][k];
00705                 p[i][k] /= U[i][i];
00706               }
00707             }
00708 
00709             for(size_type i=n; i>0; ){
00710               --i;
00711               if(i!=pivot[i])
00712                 for(size_type j=0; j<n; ++j)
00713                   std::swap(p[j][pivot[i]], p[j][i]);
00714             }
00715         }
00716     }
00717 
00718     // implementation of the determinant 
00719     template <class K, int n, int m>
00720     inline K FieldMatrix<K,n,m>::determinant() const
00721     {
00722         // never mind those ifs, because they get optimized away
00723         if (n!=m)
00724             DUNE_THROW(FMatrixError, "There is no determinant for a " << n << "x" << m << " matrix!");
00725 
00726         // no need to implement the case 1x1, because the whole matrix class is
00727         // specialized for this
00728 
00729         if (n==2)
00730             return p[0][0]*p[1][1] - p[0][1]*p[1][0]; 
00731 
00732         if (n==3) {
00733              // code generated by maple 
00734             K t4  = p[0][0] * p[1][1];
00735             K t6  = p[0][0] * p[1][2];
00736             K t8  = p[0][1] * p[1][0];
00737             K t10 = p[0][2] * p[1][0];
00738             K t12 = p[0][1] * p[2][0];
00739             K t14 = p[0][2] * p[2][0];
00740         
00741             return (t4*p[2][2]-t6*p[2][1]-t8*p[2][2]+
00742                     t10*p[2][1]+t12*p[1][2]-t14*p[1][1]);
00743 
00744         }
00745         
00746         DUNE_THROW(FMatrixError, "No implementation of determinantMatrix "
00747                    << "for FieldMatrix<" << n << "," << m << "> !");
00748 
00749     }
00750 
00751 
00754   template<class K>
00755   class FieldMatrix<K,1,1>
00756   {
00757   public:
00758         // standard constructor and everything is sufficient ...
00759 
00760         //===== type definitions and constants
00761 
00763         typedef K field_type;
00764 
00766         typedef K block_type;
00767 
00769     typedef std::size_t size_type;
00770     
00772         enum {
00775           blocklevel = 1
00776         };
00777 
00779         typedef FieldVector<K,1> row_type; 
00780 
00782         enum {
00785           rows = 1,
00786       n = 1,
00789           cols = 1,
00790       m = 1
00791         };
00792 
00793         //===== constructors
00796         FieldMatrix () {}
00797 
00800         FieldMatrix (const K& k)
00801         {
00802             a = k;
00803         }
00804 
00805         //===== random access interface to rows of the matrix
00806 
00808         row_type& operator[] (size_type i)
00809         {
00810 #ifdef DUNE_FMatrix_WITH_CHECKING
00811           if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00812 #endif
00813           return a;
00814         }
00815 
00817         const row_type& operator[] (size_type i) const
00818         {
00819 #ifdef DUNE_FMatrix_WITH_CHECKING
00820           if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00821 #endif
00822           return a;
00823         }
00824 
00825         //===== iterator interface to rows of the matrix
00827     typedef FieldIterator<FieldMatrix<K,n,m>,row_type> Iterator;
00829     typedef Iterator iterator;
00831         typedef Iterator RowIterator;
00833         typedef typename row_type::Iterator ColIterator;
00834 
00836         Iterator begin ()
00837         {
00838           return Iterator(*this,0);
00839         }
00840           
00842         Iterator end ()
00843         {
00844           return Iterator(*this,n);
00845         }
00846 
00848         Iterator rbegin ()
00849         {
00850           return Iterator(*this,n-1);
00851         }
00852           
00854         Iterator rend ()
00855         {
00856           return Iterator(*this,-1);
00857         }
00858 
00860     typedef FieldIterator<const FieldMatrix<K,n,m>,const row_type> ConstIterator;
00862     typedef ConstIterator const_iterator;
00864         typedef ConstIterator ConstRowIterator;
00866         typedef typename row_type::ConstIterator ConstColIterator;
00867 
00869         ConstIterator begin () const
00870         {
00871           return ConstIterator(*this,0);
00872         }
00873           
00875         ConstIterator end () const
00876         {
00877           return ConstIterator(*this,n);
00878         }
00879 
00881         ConstIterator rbegin () const
00882         {
00883           return ConstIterator(*this,n-1);
00884         }
00885           
00887         ConstIterator rend () const
00888         {
00889           return ConstIterator(*this,-1);
00890         }
00891 
00892         //===== assignment from scalar
00893 
00894         FieldMatrix& operator= (const K& k)
00895         {
00896           a[0] = k;
00897           return *this;   
00898         }
00899 
00900         //===== vector space arithmetic
00901 
00903         FieldMatrix& operator+= (const K& y)
00904         {
00905           a[0] += y;
00906           return *this;
00907         }
00908 
00910         FieldMatrix& operator-= (const K& y)
00911         {
00912           a[0] -= y;
00913           return *this;
00914         }
00915 
00917         FieldMatrix& operator*= (const K& k)
00918         {
00919           a[0] *= k;
00920           return *this;
00921         }
00922 
00924         FieldMatrix& operator/= (const K& k)
00925         {
00926           a[0] /= k;
00927           return *this;
00928         }
00929 
00930         //===== linear maps
00931    
00933         void umv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00934         {
00935           y.p += a[0] * x.p;
00936         }
00937 
00939         void umtv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00940         {
00941           y.p += a[0] * x.p;
00942         }
00943 
00945         void umhv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00946         {
00947           y.p += fm_ck(a[0]) * x.p;
00948         }
00949 
00951         void mmv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00952         {
00953           y.p -= a[0] * x.p;
00954         }
00955 
00957         void mmtv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00958         {
00959           y.p -= a[0] * x.p;
00960         }
00961 
00963         void mmhv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00964         {
00965           y.p -= fm_ck(a[0]) * x.p;
00966         }
00967 
00969         void usmv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00970         {
00971           y.p += alpha * a[0] * x.p;
00972         }
00973 
00975         void usmtv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00976         {
00977           y.p += alpha * a[0] * x.p;
00978         }
00979 
00981         void usmhv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00982         {
00983           y.p += alpha * fm_ck(a[0]) * x.p;
00984         }
00985 
00986         //===== norms
00987 
00989     double frobenius_norm () const
00990         {
00991           return sqrt(fvmeta_abs2(a[0]));
00992         }
00993 
00995     double frobenius_norm2 () const
00996         {
00997           return fvmeta_abs2(a[0]);
00998         }
00999 
01001     double infinity_norm () const
01002         {
01003             return std::abs(a[0]);
01004         }
01005 
01007         double infinity_norm_real () const
01008         {
01009           return fvmeta_abs_real(a[0]);
01010         }
01011 
01012         //===== solve
01013 
01015         void solve (FieldVector<K,1>& x, const FieldVector<K,1>& b) const
01016         {
01017 #ifdef DUNE_FMatrix_WITH_CHECKING
01018         if (fvmeta_absreal(a[0][0])<FMatrixPrecision<>::absolute_limit())
01019           DUNE_THROW(FMatrixError,"matrix is singular");                  
01020 #endif
01021           x.p = b.p/a[0];
01022         }
01023 
01025         void invert ()
01026         {
01027 #ifdef DUNE_FMatrix_WITH_CHECKING
01028             if (fvmeta_absreal(a[0][0])<FMatrixPrecision<>::absolute_limit())
01029                 DUNE_THROW(FMatrixError,"matrix is singular");            
01030 #endif
01031           a[0] = 1/a[0];
01032         }
01033 
01035     K determinant () const
01036     {
01037       return std::abs(a[0]);
01038     }
01039 
01041         FieldMatrix& leftmultiply (const FieldMatrix& M)
01042         {
01043           a[0] *= M.a[0];
01044           return *this;
01045         }
01046 
01048         FieldMatrix& rightmultiply (const FieldMatrix& M)
01049         {
01050           a[0] *= M.a[0];
01051           return *this;
01052         }
01053 
01054 
01055         //===== sizes
01056 
01058         size_type N () const
01059         {
01060           return 1;
01061         }
01062 
01064         size_type M () const
01065         {
01066           return 1;
01067         }
01068 
01070         size_type rowdim (size_type r) const
01071         {
01072           return 1;
01073         }
01074 
01076         size_type coldim (size_type c) const
01077         {
01078           return 1;
01079         }
01080 
01082         size_type rowdim () const
01083         {
01084           return 1;
01085         }
01086 
01088         size_type coldim () const
01089         {
01090           return 1;
01091         }
01092 
01093         //===== query
01094         
01096         bool exists (size_type i, size_type j) const 
01097         {
01098           return i==0 && j==0;
01099         }
01100 
01101         //===== conversion operator
01102 
01103         operator K () const {return a[0];}
01104 
01105         private:
01106         // the data, just a single row with a single scalar
01107     row_type a;
01108   };
01109 
01110 namespace FMatrixHelp {
01111 
01112 
01114 template <typename K>
01115 static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
01116 {
01117   inverse[0][0] = 1.0/matrix[0][0];
01118   return matrix[0][0];
01119 }
01120 
01122 template <typename K>
01123 static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
01124 {
01125   return invertMatrix(matrix,inverse); 
01126 }
01127 
01128 
01130 template <typename K>
01131 static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
01132 {
01133   // code generated by maple 
01134   K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
01135   K det_1 = 1.0/det;
01136   inverse[0][0] =   matrix[1][1] * det_1;
01137   inverse[0][1] = - matrix[0][1] * det_1;
01138   inverse[1][0] = - matrix[1][0] * det_1;
01139   inverse[1][1] =   matrix[0][0] * det_1;
01140   return det;
01141 }
01142 
01145 template <typename K>
01146 static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
01147 {
01148   // code generated by maple 
01149   K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
01150   K det_1 = 1.0/det;
01151   inverse[0][0] =   matrix[1][1] * det_1;
01152   inverse[1][0] = - matrix[0][1] * det_1;
01153   inverse[0][1] = - matrix[1][0] * det_1;
01154   inverse[1][1] =   matrix[0][0] * det_1;
01155   return det;
01156 }
01157 
01159 template <typename K>
01160 static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
01161 {
01162   // code generated by maple 
01163   K t4  = matrix[0][0] * matrix[1][1];
01164   K t6  = matrix[0][0] * matrix[1][2];
01165   K t8  = matrix[0][1] * matrix[1][0];
01166   K t10 = matrix[0][2] * matrix[1][0];
01167   K t12 = matrix[0][1] * matrix[2][0];
01168   K t14 = matrix[0][2] * matrix[2][0];
01169 
01170   K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
01171            t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
01172   K t17 = 1.0/det;
01173 
01174   inverse[0][0] =  (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
01175   inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
01176   inverse[0][2] =  (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
01177   inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
01178   inverse[1][1] =  (matrix[0][0] * matrix[2][2] - t14) * t17;
01179   inverse[1][2] = -(t6-t10) * t17;
01180   inverse[2][0] =  (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
01181   inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
01182   inverse[2][2] =  (t4-t8) * t17;
01183 
01184   return det;
01185 }
01186 
01188 template <typename K>
01189 static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
01190 {
01191   // code generated by maple 
01192   K t4  = matrix[0][0] * matrix[1][1];
01193   K t6  = matrix[0][0] * matrix[1][2];
01194   K t8  = matrix[0][1] * matrix[1][0];
01195   K t10 = matrix[0][2] * matrix[1][0];
01196   K t12 = matrix[0][1] * matrix[2][0];
01197   K t14 = matrix[0][2] * matrix[2][0];
01198 
01199   K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
01200            t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
01201   K t17 = 1.0/det;
01202 
01203   inverse[0][0] =  (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
01204   inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
01205   inverse[2][0] =  (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
01206   inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
01207   inverse[1][1] =  (matrix[0][0] * matrix[2][2] - t14) * t17;
01208   inverse[2][1] = -(t6-t10) * t17;
01209   inverse[0][2] =  (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
01210   inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
01211   inverse[2][2] =  (t4-t8) * t17;
01212 
01213   return det;
01214 }
01215 
01217 template <typename K, int rows,int cols>
01218 static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
01219 {
01220   typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01221   
01222   for(size_type i=0; i<cols; i++)
01223     for(size_type j=0; j<cols; j++)
01224       { ret[i][j]=0.0;
01225         for(size_type k=0; k<rows; k++)
01226           ret[i][j]+=matrix[k][i]*matrix[k][j];
01227       }
01228 }
01229 
01231 template <typename K, int dim>
01232 static inline void multAssign(const FieldMatrix<K,dim,dim> &matrix, const FieldVector<K,dim> & x, FieldVector<K,dim> & ret) 
01233 {
01234   typedef typename FieldMatrix<K,dim,dim>::size_type size_type;
01235   
01236   for(size_type i=0; i<dim; i++)
01237   {
01238     ret[i] = 0.0;
01239     for(size_type j=0; j<dim; j++)
01240     {
01241       ret[i] += matrix[i][j]*x[j];
01242     }
01243   }
01244 }
01245 
01247 template <typename K, int rows,int cols>
01248 static inline void multAssign(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x, FieldVector<K,rows> & ret) 
01249 {
01250   typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01251   
01252   for(size_type i=0; i<rows; i++)
01253   {
01254     ret[i] = 0.0;
01255     for(size_type j=0; j<cols; j++)
01256     {
01257       ret[i] += matrix[i][j]*x[j];
01258     }
01259   }
01260 }
01261 
01263 template <typename K, int dim>
01264 static inline void multAssignTransposed( const FieldMatrix<K,dim,dim> &matrix, const FieldVector<K,dim> & x, FieldVector<K,dim> & ret) 
01265 {
01266   typedef typename FieldMatrix<K,dim,dim>::size_type size_type;
01267   
01268   for(size_type i=0; i<dim; i++)
01269   {
01270     ret[i] = 0.0;
01271     for(size_type j=0; j<dim; j++)
01272     {
01273       ret[i] += matrix[j][i]*x[j];
01274     }
01275   }
01276 }
01277 
01279 template <typename K, int dim>
01280 static inline FieldVector<K,dim> mult(const FieldMatrix<K,dim,dim> &matrix, const FieldVector<K,dim> & x) 
01281 {
01282   FieldVector<K,dim> ret;
01283   multAssign(matrix,x,ret);
01284   return ret; 
01285 }
01286 
01287 
01288 
01290 template <typename K, int rows, int cols>
01291 static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x) 
01292 {
01293   FieldVector<K,cols> ret;
01294   typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01295   for(size_type i=0; i<cols; i++)
01296   {
01297     ret[i] = 0.0;
01298     for(size_type j=0; j<rows; j++)
01299     {
01300       ret[i] += matrix[j][i]*x[j];
01301     }
01302   }
01303   return ret; 
01304 }
01305 
01306 } // end namespace FMatrixHelp 
01307 
01310 } // end namespace
01311 
01312 #endif

Generated on 12 Dec 2007 with Doxygen (ver 1.5.1)