00001
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 #include "static_assert.hh"
00013
00014 namespace Dune {
00015
00027 template<class K, int n, int m> class FieldMatrix;
00028
00029 template<class K, int n, int m, typename T>
00030 void istl_assign_to_fmatrix(FieldMatrix<K,n,m>& f, const T& t)
00031 {
00032 DUNE_THROW(NotImplemented, "You need to specialise this function for type T!");
00033 }
00034
00035 namespace
00036 {
00037 template<bool b>
00038 struct Assigner
00039 {
00040 template<class K, int n, int m, class T>
00041 static void assign(FieldMatrix<K,n,m>& fm, const T& t)
00042 {
00043 istl_assign_to_fmatrix(fm, t);
00044 }
00045
00046 };
00047
00048
00049 template<>
00050 struct Assigner<true>
00051 {
00052 template<class K, int n, int m, class T>
00053 static void assign(FieldMatrix<K,n,m>& fm, const T& t)
00054 {
00055 fm = static_cast<const K>(t);
00056 }
00057 };
00058 }
00059
00061 class FMatrixError : public Exception {};
00062
00063
00064 template<class K>
00065 inline K fm_ck (const K& k)
00066 {
00067 return k;
00068 }
00069
00070
00071 template<class K>
00072 inline std::complex<K> fm_ck (const std::complex<K>& c)
00073 {
00074 return std::complex<K>(c.real(),-c.imag());
00075 }
00076
00085 #ifdef DUNE_EXPRESSIONTEMPLATES
00086 template<class K, int n, int m>
00087 class FieldMatrix : ExprTmpl::Matrix< FieldMatrix<K,n,m> >
00088 #else
00089 template<class K, int n, int m>
00090 class FieldMatrix
00091 #endif
00092 {
00093 public:
00094
00095
00096
00097
00099 typedef K field_type;
00100
00102 typedef K block_type;
00103
00105 typedef std::size_t size_type;
00106
00108 enum {
00110 blocklevel = 1
00111 };
00112
00114 typedef FieldVector<K,m> row_type;
00115
00117 enum {
00119 rows = n,
00121 cols = m
00122 };
00123
00124
00127 FieldMatrix () {}
00128
00131 FieldMatrix (const K& k)
00132 {
00133 for (size_type i=0; i<n; i++) p[i] = k;
00134 }
00135
00136 template<typename T>
00137 explicit FieldMatrix( const T& t)
00138 {
00139 Assigner<Conversion<T,K>::exists>::assign(*this, t);
00140 }
00141
00142
00143
00145 row_type& operator[] (size_type i)
00146 {
00147 #ifdef DUNE_FMatrix_WITH_CHECKING
00148 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00149 #endif
00150 return p[i];
00151 }
00152
00154 const row_type& operator[] (size_type i) const
00155 {
00156 #ifdef DUNE_FMatrix_WITH_CHECKING
00157 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00158 #endif
00159 return p[i];
00160 }
00161
00162
00163
00165 typedef FieldIterator<FieldMatrix<K,n,m>,row_type> Iterator;
00167 typedef Iterator iterator;
00169 typedef Iterator RowIterator;
00171 typedef typename row_type::Iterator ColIterator;
00172
00174 Iterator begin ()
00175 {
00176 return Iterator(*this,0);
00177 }
00178
00180 Iterator end ()
00181 {
00182 return Iterator(*this,n);
00183 }
00184
00186 Iterator rbegin ()
00187 {
00188 return Iterator(*this,n-1);
00189 }
00190
00192 Iterator rend ()
00193 {
00194 return Iterator(*this,-1);
00195 }
00196
00198 typedef FieldIterator<const FieldMatrix<K,n,m>,const row_type> ConstIterator;
00200 typedef ConstIterator const_iterator;
00202 typedef ConstIterator ConstRowIterator;
00204 typedef typename row_type::ConstIterator ConstColIterator;
00205
00207 ConstIterator begin () const
00208 {
00209 return ConstIterator(*this,0);
00210 }
00211
00213 ConstIterator end () const
00214 {
00215 return ConstIterator(*this,n);
00216 }
00217
00219 ConstIterator rbegin () const
00220 {
00221 return ConstIterator(*this,n-1);
00222 }
00223
00225 ConstIterator rend () const
00226 {
00227 return ConstIterator(*this,-1);
00228 }
00229
00230
00231 FieldMatrix& operator= (const K& k)
00232 {
00233 for (size_type i=0; i<n; i++)
00234 p[i] = k;
00235 return *this;
00236 }
00237
00238 template<typename T>
00239 FieldMatrix& operator= ( const T& t)
00240 {
00241 Assigner<Conversion<T,K>::exists>::assign(*this, t);
00242 return *this;
00243 }
00244
00245
00247 FieldMatrix& operator+= (const FieldMatrix& y)
00248 {
00249 for (size_type i=0; i<n; i++)
00250 p[i] += y.p[i];
00251 return *this;
00252 }
00253
00255 FieldMatrix& operator-= (const FieldMatrix& y)
00256 {
00257 for (size_type i=0; i<n; i++)
00258 p[i] -= y.p[i];
00259 return *this;
00260 }
00261
00263 FieldMatrix& operator*= (const K& k)
00264 {
00265 for (size_type i=0; i<n; i++)
00266 p[i] *= k;
00267 return *this;
00268 }
00269
00271 FieldMatrix& operator/= (const K& k)
00272 {
00273 for (size_type i=0; i<n; i++)
00274 p[i] /= k;
00275 return *this;
00276 }
00277
00279 FieldMatrix &axpy ( const K &k, const FieldMatrix &y )
00280 {
00281 for( size_type i = 0; i < n; ++i )
00282 p[ i ].axpy( k, y[ i ] );
00283 return *this;
00284 }
00285
00286
00287
00289 template<class X, class Y>
00290 void mv (const X& x, Y& y) const
00291 {
00292 #ifdef DUNE_FMatrix_WITH_CHECKING
00293 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00294 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00295 #endif
00296 for (size_type i=0; i<n; ++i)
00297 {
00298 y[i] = 0;
00299 for (size_type j=0; j<m; j++)
00300 y[i] += (*this)[i][j] * x[j];
00301 }
00302 }
00303
00305 template<class X, class Y>
00306 void umv (const X& x, Y& y) const
00307 {
00308 #ifdef DUNE_FMatrix_WITH_CHECKING
00309 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00310 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00311 #endif
00312 for (size_type i=0; i<n; i++)
00313 for (size_type j=0; j<m; j++)
00314 y[i] += (*this)[i][j] * x[j];
00315 }
00316
00318 template<class X, class Y>
00319 void umtv (const X& x, Y& y) const
00320 {
00321 #ifdef DUNE_FMatrix_WITH_CHECKING
00322 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00323 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00324 #endif
00325
00326 for (size_type i=0; i<n; i++)
00327 for (size_type j=0; j<m; j++)
00328 y[j] += p[i][j]*x[i];
00329 }
00330
00332 template<class X, class Y>
00333 void umhv (const X& x, Y& y) const
00334 {
00335 #ifdef DUNE_FMatrix_WITH_CHECKING
00336 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00337 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00338 #endif
00339
00340 for (size_type i=0; i<n; i++)
00341 for (size_type j=0; j<m; j++)
00342 y[j] += fm_ck(p[i][j])*x[i];
00343 }
00344
00346 template<class X, class Y>
00347 void mmv (const X& x, Y& y) const
00348 {
00349 #ifdef DUNE_FMatrix_WITH_CHECKING
00350 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00351 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00352 #endif
00353 for (size_type i=0; i<n; i++)
00354 for (size_type j=0; j<m; j++)
00355 y[i] -= (*this)[i][j] * x[j];
00356 }
00357
00359 template<class X, class Y>
00360 void mmtv (const X& x, Y& y) const
00361 {
00362 #ifdef DUNE_FMatrix_WITH_CHECKING
00363 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00364 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00365 #endif
00366
00367 for (size_type i=0; i<n; i++)
00368 for (size_type j=0; j<m; j++)
00369 y[j] -= p[i][j]*x[i];
00370 }
00371
00373 template<class X, class Y>
00374 void mmhv (const X& x, Y& y) const
00375 {
00376 #ifdef DUNE_FMatrix_WITH_CHECKING
00377 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00378 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00379 #endif
00380
00381 for (size_type i=0; i<n; i++)
00382 for (size_type j=0; j<m; j++)
00383 y[j] -= fm_ck(p[i][j])*x[i];
00384 }
00385
00387 template<class X, class Y>
00388 void usmv (const K& alpha, const X& x, Y& y) const
00389 {
00390 #ifdef DUNE_FMatrix_WITH_CHECKING
00391 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00392 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00393 #endif
00394 for (size_type i=0; i<n; i++)
00395 for (size_type j=0; j<m; j++)
00396 y[i] += alpha * (*this)[i][j] * x[j];
00397 }
00398
00400 template<class X, class Y>
00401 void usmtv (const K& alpha, const X& x, Y& y) const
00402 {
00403 #ifdef DUNE_FMatrix_WITH_CHECKING
00404 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00405 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00406 #endif
00407
00408 for (size_type i=0; i<n; i++)
00409 for (size_type j=0; j<m; j++)
00410 y[j] += alpha*p[i][j]*x[i];
00411 }
00412
00414 template<class X, class Y>
00415 void usmhv (const K& alpha, const X& x, Y& y) const
00416 {
00417 #ifdef DUNE_FMatrix_WITH_CHECKING
00418 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00419 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00420 #endif
00421
00422 for (size_type i=0; i<n; i++)
00423 for (size_type j=0; j<m; j++)
00424 y[j] += alpha*fm_ck(p[i][j])*x[i];
00425 }
00426
00427
00428
00430 double frobenius_norm () const
00431 {
00432 double sum=0;
00433 for (size_type i=0; i<n; ++i) sum += p[i].two_norm2();
00434 return sqrt(sum);
00435 }
00436
00438 double frobenius_norm2 () const
00439 {
00440 double sum=0;
00441 for (size_type i=0; i<n; ++i) sum += p[i].two_norm2();
00442 return sum;
00443 }
00444
00446 double infinity_norm () const
00447 {
00448 double max=0;
00449 for (size_type i=0; i<n; ++i) max = std::max(max,p[i].one_norm());
00450 return max;
00451 }
00452
00454 double infinity_norm_real () const
00455 {
00456 double max=0;
00457 for (size_type i=0; i<n; ++i) max = std::max(max,p[i].one_norm_real());
00458 return max;
00459 }
00460
00461
00462
00467 template<class V>
00468 void solve (V& x, const V& b) const;
00469
00474 void invert();
00475
00477 K determinant () const;
00478
00480 FieldMatrix& leftmultiply (const FieldMatrix<K,n,n>& M)
00481 {
00482 FieldMatrix<K,n,m> C(*this);
00483
00484 for (size_type i=0; i<n; i++)
00485 for (size_type j=0; j<m; j++) {
00486 (*this)[i][j] = 0;
00487 for (size_type k=0; k<n; k++)
00488 (*this)[i][j] += M[i][k]*C[k][j];
00489 }
00490
00491 return *this;
00492 }
00493
00495 FieldMatrix& rightmultiply (const FieldMatrix<K,m,m>& M)
00496 {
00497 FieldMatrix<K,n,m> C(*this);
00498
00499 for (size_type i=0; i<n; i++)
00500 for (size_type j=0; j<m; j++) {
00501 (*this)[i][j] = 0;
00502 for (size_type k=0; k<m; k++)
00503 (*this)[i][j] += C[i][k]*M[k][j];
00504 }
00505 return *this;
00506 }
00507
00508
00509
00510
00512 size_type N () const
00513 {
00514 return n;
00515 }
00516
00518 size_type M () const
00519 {
00520 return m;
00521 }
00522
00523
00524
00526 bool exists (size_type i, size_type j) const
00527 {
00528 #ifdef DUNE_FMatrix_WITH_CHECKING
00529 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"row index out of range");
00530 if (j<0 || j>=m) DUNE_THROW(FMatrixError,"column index out of range");
00531 #endif
00532 return true;
00533 }
00534
00535
00536
00538 friend std::ostream& operator<< (std::ostream& s, const FieldMatrix<K,n,m>& a)
00539 {
00540 for (size_type i=0; i<n; i++)
00541 s << a.p[i] << std::endl;
00542 return s;
00543 }
00544
00545 private:
00546
00547 row_type p[(n > 0) ? n : 1];
00548
00549 struct ElimPivot
00550 {
00551 ElimPivot(size_type pivot[n]);
00552
00553 void swap(int i, int j);
00554
00555 template<typename T>
00556 void operator()(const T&, int k, int i)
00557 {}
00558
00559 size_type* pivot_;
00560 };
00561
00562 template<typename V>
00563 struct Elim
00564 {
00565 Elim(V& rhs);
00566
00567 void swap(int i, int j);
00568
00569 void operator()(const typename V::field_type& factor, int k, int i);
00570
00571 V* rhs_;
00572 };
00573
00574 template<class Func>
00575 void luDecomposition(FieldMatrix<K,n,n>& A, Func func) const;
00576 };
00577
00578 template<typename K, int n, int m>
00579 FieldMatrix<K,n,m>::ElimPivot::ElimPivot(size_type pivot[n])
00580 : pivot_(pivot)
00581 {
00582 for(int i=0; i < n; ++i) pivot[i]=i;
00583 }
00584
00585 template<typename K, int n, int m>
00586 void FieldMatrix<K,n,m>::ElimPivot::swap(int i, int j)
00587 {
00588 pivot_[i]=j;
00589 }
00590
00591 template<typename K, int n, int m>
00592 template<typename V>
00593 FieldMatrix<K,n,m>::Elim<V>::Elim(V& rhs)
00594 : rhs_(&rhs)
00595 {}
00596
00597 template<typename K, int n, int m>
00598 template<typename V>
00599 void FieldMatrix<K,n,m>::Elim<V>::swap(int i, int j)
00600 {
00601 std::swap((*rhs_)[i], (*rhs_)[j]);
00602 }
00603
00604 template<typename K, int n, int m>
00605 template<typename V>
00606 void FieldMatrix<K,n,m>::
00607 Elim<V>::operator()(const typename V::field_type& factor, int k, int i)
00608 {
00609 (*rhs_)[k] -= factor*(*rhs_)[i];
00610 }
00611 template<typename K, int n, int m>
00612 template<typename Func>
00613 inline void FieldMatrix<K,n,m>::luDecomposition(FieldMatrix<K,n,n>& A, Func func) const
00614 {
00615 double norm=A.infinity_norm_real();
00616 double pivthres = std::max(FMatrixPrecision<>::absolute_limit(),norm*FMatrixPrecision<>::pivoting_limit());
00617 double singthres = std::max(FMatrixPrecision<>::absolute_limit(),norm*FMatrixPrecision<>::singular_limit());
00618
00619
00620 for (int i=0; i<n; i++)
00621 {
00622 double pivmax=fvmeta_absreal(A[i][i]);
00623
00624
00625 if (pivmax<pivthres)
00626 {
00627
00628 int imax=i; double abs;
00629 for (int k=i+1; k<n; k++)
00630 if ((abs=fvmeta_absreal(A[k][i]))>pivmax)
00631 {
00632 pivmax = abs; imax = k;
00633 }
00634
00635 if (imax!=i){
00636 for (int j=0; j<n; j++)
00637 std::swap(A[i][j],A[imax][j]);
00638 func.swap(i, imax);
00639 }
00640 }
00641
00642
00643 if (pivmax<singthres)
00644 DUNE_THROW(FMatrixError,"matrix is singular");
00645
00646
00647 for (int k=i+1; k<n; k++)
00648 {
00649 K factor = A[k][i]/A[i][i];
00650 A[k][i] = factor;
00651 for (int j=i+1; j<n; j++)
00652 A[k][j] -= factor*A[i][j];
00653 func(factor, k, i);
00654 }
00655 }
00656 }
00657
00658 template <class K, int n, int m>
00659 template <class V>
00660 inline void FieldMatrix<K,n,m>::solve(V& x, const V& b) const
00661 {
00662
00663 if (n!=m)
00664 DUNE_THROW(FMatrixError, "Can't solve for a " << n << "x" << m << " matrix!");
00665
00666
00667
00668
00669 if (n==2) {
00670
00671 #ifdef DUNE_FMatrix_WITH_CHECKING
00672 K detinv = p[0][0]*p[1][1]-p[0][1]*p[1][0];
00673 if (fvmeta_absreal(detinv)<FMatrixPrecision<>::absolute_limit())
00674 DUNE_THROW(FMatrixError,"matrix is singular");
00675 detinv = 1/detinv;
00676 #else
00677 K detinv = 1.0/(p[0][0]*p[1][1]-p[0][1]*p[1][0]);
00678 #endif
00679
00680 x[0] = detinv*(p[1][1]*b[0]-p[0][1]*b[1]);
00681 x[1] = detinv*(p[0][0]*b[1]-p[1][0]*b[0]);
00682
00683 } else if (n==3) {
00684
00685 K d = determinant();
00686 #ifdef DUNE_FMatrix_WITH_CHECKING
00687 if (fvmeta_absreal(d)<FMatrixPrecision<>::absolute_limit())
00688 DUNE_THROW(FMatrixError,"matrix is singular");
00689 #endif
00690
00691 x[0] = (b[0]*p[1][1]*p[2][2] - b[0]*p[2][1]*p[1][2]
00692 - b[1] *p[0][1]*p[2][2] + b[1]*p[2][1]*p[0][2]
00693 + b[2] *p[0][1]*p[1][2] - b[2]*p[1][1]*p[0][2]) / d;
00694
00695 x[1] = (p[0][0]*b[1]*p[2][2] - p[0][0]*b[2]*p[1][2]
00696 - p[1][0] *b[0]*p[2][2] + p[1][0]*b[2]*p[0][2]
00697 + p[2][0] *b[0]*p[1][2] - p[2][0]*b[1]*p[0][2]) / d;
00698
00699 x[2] = (p[0][0]*p[1][1]*b[2] - p[0][0]*p[2][1]*b[1]
00700 - p[1][0] *p[0][1]*b[2] + p[1][0]*p[2][1]*b[0]
00701 + p[2][0] *p[0][1]*b[1] - p[2][0]*p[1][1]*b[0]) / d;
00702
00703 } else {
00704
00705 V& rhs = x;
00706 rhs = b;
00707 Elim<V> elim(rhs);
00708 FieldMatrix<K,n,n> A(*this);
00709
00710 luDecomposition(A, elim);
00711
00712
00713 for(int i=n-1; i>=0; i--){
00714 for (int j=i+1; j<n; j++)
00715 rhs[i] -= A[i][j]*x[j];
00716 x[i] = rhs[i]/A[i][i];
00717 }
00718 }
00719 }
00720
00721 template <class K, int n, int m>
00722 inline void FieldMatrix<K,n,m>::invert()
00723 {
00724
00725 if (n!=m)
00726 DUNE_THROW(FMatrixError, "Can't invert a " << n << "x" << m << " matrix!");
00727
00728
00729
00730
00731 if (n==2) {
00732
00733 K detinv = p[0][0]*p[1][1]-p[0][1]*p[1][0];
00734 #ifdef DUNE_FMatrix_WITH_CHECKING
00735 if (fvmeta_absreal(detinv)<FMatrixPrecision<>::absolute_limit())
00736 DUNE_THROW(FMatrixError,"matrix is singular");
00737 #endif
00738 detinv = 1/detinv;
00739
00740 K temp=p[0][0];
00741 p[0][0] = p[1][1]*detinv;
00742 p[0][1] = -p[0][1]*detinv;
00743 p[1][0] = -p[1][0]*detinv;
00744 p[1][1] = temp*detinv;
00745
00746 } else {
00747
00748 FieldMatrix<K,n,n> A(*this);
00749 size_type pivot[n];
00750 luDecomposition(A, ElimPivot(pivot));
00751 FieldMatrix<K,n,m>& L=A;
00752 FieldMatrix<K,n,m>& U=A;
00753
00754
00755 *this=K();
00756
00757 for(size_type i=0; i<n; ++i)
00758 p[i][i]=1;
00759
00760
00761 for (size_type i=0; i<n; i++){
00762 for (size_type j=0; j<i; j++)
00763 for (size_type k=0; k<n; k++)
00764 p[i][k] -= L[i][j]*p[j][k];
00765 }
00766
00767
00768 for (size_type i=n; i>0;){
00769 --i;
00770 for (size_type k=0; k<n; k++){
00771 for (size_type j=i+1; j<n; j++)
00772 p[i][k] -= U[i][j]*p[j][k];
00773 p[i][k] /= U[i][i];
00774 }
00775 }
00776
00777 for(size_type i=n; i>0; ){
00778 --i;
00779 if(i!=pivot[i])
00780 for(size_type j=0; j<n; ++j)
00781 std::swap(p[j][pivot[i]], p[j][i]);
00782 }
00783 }
00784 }
00785
00786
00787 template <class K, int n, int m>
00788 inline K FieldMatrix<K,n,m>::determinant() const
00789 {
00790
00791 if (n!=m)
00792 DUNE_THROW(FMatrixError, "There is no determinant for a " << n << "x" << m << " matrix!");
00793
00794
00795
00796
00797 if (n==2)
00798 return p[0][0]*p[1][1] - p[0][1]*p[1][0];
00799
00800 if (n==3) {
00801
00802 K t4 = p[0][0] * p[1][1];
00803 K t6 = p[0][0] * p[1][2];
00804 K t8 = p[0][1] * p[1][0];
00805 K t10 = p[0][2] * p[1][0];
00806 K t12 = p[0][1] * p[2][0];
00807 K t14 = p[0][2] * p[2][0];
00808
00809 return (t4*p[2][2]-t6*p[2][1]-t8*p[2][2]+
00810 t10*p[2][1]+t12*p[1][2]-t14*p[1][1]);
00811
00812 }
00813
00814 DUNE_THROW(FMatrixError, "No implementation of determinantMatrix "
00815 << "for FieldMatrix<" << n << "," << m << "> !");
00816
00817 }
00818
00819
00822 template<class K>
00823 class FieldMatrix<K,1,1>
00824 {
00825 public:
00826
00827
00828
00829
00831 typedef K field_type;
00832
00834 typedef K block_type;
00835
00837 typedef std::size_t size_type;
00838
00840 enum {
00843 blocklevel = 1
00844 };
00845
00847 typedef FieldVector<K,1> row_type;
00848
00850 enum {
00853 rows = 1,
00854 n = 1,
00857 cols = 1,
00858 m = 1
00859 };
00860
00861
00864 FieldMatrix () {}
00865
00868 FieldMatrix (const K& k)
00869 {
00870 a = k;
00871 }
00872 template<typename T>
00873 explicit FieldMatrix( const T& t)
00874 {
00875 Assigner<Conversion<T,K>::exists>::assign(*this, t);
00876 }
00877
00878
00880 row_type& operator[] (size_type i)
00881 {
00882 #ifdef DUNE_FMatrix_WITH_CHECKING
00883 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00884 #endif
00885 return a;
00886 }
00887
00889 const row_type& operator[] (size_type i) const
00890 {
00891 #ifdef DUNE_FMatrix_WITH_CHECKING
00892 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00893 #endif
00894 return a;
00895 }
00896
00897
00899 typedef FieldIterator<FieldMatrix<K,n,m>,row_type> Iterator;
00901 typedef Iterator iterator;
00903 typedef Iterator RowIterator;
00905 typedef typename row_type::Iterator ColIterator;
00906
00908 Iterator begin ()
00909 {
00910 return Iterator(*this,0);
00911 }
00912
00914 Iterator end ()
00915 {
00916 return Iterator(*this,n);
00917 }
00918
00920 Iterator rbegin ()
00921 {
00922 return Iterator(*this,n-1);
00923 }
00924
00926 Iterator rend ()
00927 {
00928 return Iterator(*this,-1);
00929 }
00930
00932 typedef FieldIterator<const FieldMatrix<K,n,m>,const row_type> ConstIterator;
00934 typedef ConstIterator const_iterator;
00936 typedef ConstIterator ConstRowIterator;
00938 typedef typename row_type::ConstIterator ConstColIterator;
00939
00941 ConstIterator begin () const
00942 {
00943 return ConstIterator(*this,0);
00944 }
00945
00947 ConstIterator end () const
00948 {
00949 return ConstIterator(*this,n);
00950 }
00951
00953 ConstIterator rbegin () const
00954 {
00955 return ConstIterator(*this,n-1);
00956 }
00957
00959 ConstIterator rend () const
00960 {
00961 return ConstIterator(*this,-1);
00962 }
00963
00964
00965
00966 FieldMatrix& operator= (const K& k)
00967 {
00968 a[0] = k;
00969 return *this;
00970 }
00971
00972 template<typename T>
00973 FieldMatrix& operator= ( const T& t)
00974 {
00975 Assigner<Conversion<T,K>::exists>::assign(*this, t);
00976 return *this;
00977 }
00978
00979
00980
00982 FieldMatrix& operator+= (const K& y)
00983 {
00984 a[0] += y;
00985 return *this;
00986 }
00987
00989 FieldMatrix& operator-= (const K& y)
00990 {
00991 a[0] -= y;
00992 return *this;
00993 }
00994
00996 FieldMatrix& operator*= (const K& k)
00997 {
00998 a[0] *= k;
00999 return *this;
01000 }
01001
01003 FieldMatrix& operator/= (const K& k)
01004 {
01005 a[0] /= k;
01006 return *this;
01007 }
01008
01010 FieldMatrix &axpy ( const K &k, const FieldMatrix &y )
01011 {
01012 a[ 0 ] += k * y.a[ 0 ];
01013 return *this;
01014 }
01015
01016
01017
01019 void mv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01020 {
01021 y.p = a[0] * x.p;
01022 }
01023
01025 void umv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01026 {
01027 y.p += a[0] * x.p;
01028 }
01029
01031 void umtv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01032 {
01033 y.p += a[0] * x.p;
01034 }
01035
01037 void umhv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01038 {
01039 y.p += fm_ck(a[0]) * x.p;
01040 }
01041
01043 void mmv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01044 {
01045 y.p -= a[0] * x.p;
01046 }
01047
01049 void mmtv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01050 {
01051 y.p -= a[0] * x.p;
01052 }
01053
01055 void mmhv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01056 {
01057 y.p -= fm_ck(a[0]) * x.p;
01058 }
01059
01061 void usmv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01062 {
01063 y.p += alpha * a[0] * x.p;
01064 }
01065
01067 void usmtv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01068 {
01069 y.p += alpha * a[0] * x.p;
01070 }
01071
01073 void usmhv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
01074 {
01075 y.p += alpha * fm_ck(a[0]) * x.p;
01076 }
01077
01078
01079
01081 double frobenius_norm () const
01082 {
01083 return sqrt(fvmeta_abs2(a[0]));
01084 }
01085
01087 double frobenius_norm2 () const
01088 {
01089 return fvmeta_abs2(a[0]);
01090 }
01091
01093 double infinity_norm () const
01094 {
01095 return std::abs(a[0]);
01096 }
01097
01099 double infinity_norm_real () const
01100 {
01101 return fvmeta_abs_real(a[0]);
01102 }
01103
01104
01105
01107 void solve (FieldVector<K,1>& x, const FieldVector<K,1>& b) const
01108 {
01109 #ifdef DUNE_FMatrix_WITH_CHECKING
01110 if (fvmeta_absreal(a[0][0])<FMatrixPrecision<>::absolute_limit())
01111 DUNE_THROW(FMatrixError,"matrix is singular");
01112 #endif
01113 x.p = b.p/a[0];
01114 }
01115
01117 void invert ()
01118 {
01119 #ifdef DUNE_FMatrix_WITH_CHECKING
01120 if (fvmeta_absreal(a[0][0])<FMatrixPrecision<>::absolute_limit())
01121 DUNE_THROW(FMatrixError,"matrix is singular");
01122 #endif
01123 a[0] = 1/a[0];
01124 }
01125
01127 K determinant () const
01128 {
01129 return std::abs(a[0]);
01130 }
01131
01133 FieldMatrix& leftmultiply (const FieldMatrix& M)
01134 {
01135 a[0] *= M.a[0];
01136 return *this;
01137 }
01138
01140 FieldMatrix& rightmultiply (const FieldMatrix& M)
01141 {
01142 a[0] *= M.a[0];
01143 return *this;
01144 }
01145
01146
01147
01148
01150 size_type N () const
01151 {
01152 return 1;
01153 }
01154
01156 size_type M () const
01157 {
01158 return 1;
01159 }
01160
01162 size_type rowdim (size_type r) const
01163 {
01164 return 1;
01165 }
01166
01168 size_type coldim (size_type c) const
01169 {
01170 return 1;
01171 }
01172
01174 size_type rowdim () const
01175 {
01176 return 1;
01177 }
01178
01180 size_type coldim () const
01181 {
01182 return 1;
01183 }
01184
01185
01186
01188 bool exists (size_type i, size_type j) const
01189 {
01190 return i==0 && j==0;
01191 }
01192
01193
01194
01195 operator K () const {return a[0];}
01196
01197 private:
01198
01199 row_type a;
01200
01201 };
01202
01203 namespace FMatrixHelp {
01204
01205
01207 template <typename K>
01208 static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
01209 {
01210 inverse[0][0] = 1.0/matrix[0][0];
01211 return matrix[0][0];
01212 }
01213
01215 template <typename K>
01216 static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
01217 {
01218 return invertMatrix(matrix,inverse);
01219 }
01220
01221
01223 template <typename K>
01224 static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
01225 {
01226
01227 K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
01228 K det_1 = 1.0/det;
01229 inverse[0][0] = matrix[1][1] * det_1;
01230 inverse[0][1] = - matrix[0][1] * det_1;
01231 inverse[1][0] = - matrix[1][0] * det_1;
01232 inverse[1][1] = matrix[0][0] * det_1;
01233 return det;
01234 }
01235
01238 template <typename K>
01239 static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
01240 {
01241
01242 K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
01243 K det_1 = 1.0/det;
01244 inverse[0][0] = matrix[1][1] * det_1;
01245 inverse[1][0] = - matrix[0][1] * det_1;
01246 inverse[0][1] = - matrix[1][0] * det_1;
01247 inverse[1][1] = matrix[0][0] * det_1;
01248 return det;
01249 }
01250
01252 template <typename K>
01253 static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
01254 {
01255
01256 K t4 = matrix[0][0] * matrix[1][1];
01257 K t6 = matrix[0][0] * matrix[1][2];
01258 K t8 = matrix[0][1] * matrix[1][0];
01259 K t10 = matrix[0][2] * matrix[1][0];
01260 K t12 = matrix[0][1] * matrix[2][0];
01261 K t14 = matrix[0][2] * matrix[2][0];
01262
01263 K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
01264 t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
01265 K t17 = 1.0/det;
01266
01267 inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
01268 inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
01269 inverse[0][2] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
01270 inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
01271 inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
01272 inverse[1][2] = -(t6-t10) * t17;
01273 inverse[2][0] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
01274 inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
01275 inverse[2][2] = (t4-t8) * t17;
01276
01277 return det;
01278 }
01279
01281 template <typename K>
01282 static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
01283 {
01284
01285 K t4 = matrix[0][0] * matrix[1][1];
01286 K t6 = matrix[0][0] * matrix[1][2];
01287 K t8 = matrix[0][1] * matrix[1][0];
01288 K t10 = matrix[0][2] * matrix[1][0];
01289 K t12 = matrix[0][1] * matrix[2][0];
01290 K t14 = matrix[0][2] * matrix[2][0];
01291
01292 K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
01293 t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
01294 K t17 = 1.0/det;
01295
01296 inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
01297 inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
01298 inverse[2][0] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
01299 inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
01300 inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
01301 inverse[2][1] = -(t6-t10) * t17;
01302 inverse[0][2] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
01303 inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
01304 inverse[2][2] = (t4-t8) * t17;
01305
01306 return det;
01307 }
01308
01310 template< class K, int m, int n, int p >
01311 static inline void multMatrix ( const FieldMatrix< K, m, n > &A,
01312 const FieldMatrix< K, n, p > &B,
01313 FieldMatrix< K, m, p > &ret )
01314 {
01315 typedef typename FieldMatrix< K, m, p > :: size_type size_type;
01316
01317 for( size_type i = 0; i < m; ++i )
01318 {
01319 for( size_type j = 0; j < p; ++j )
01320 {
01321 ret[ i ][ j ] = K( 0 );
01322 for( size_type k = 0; k < n; ++k )
01323 ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
01324 }
01325 }
01326 }
01327
01329 template <typename K, int rows,int cols>
01330 static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
01331 {
01332 typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01333
01334 for(size_type i=0; i<cols; i++)
01335 for(size_type j=0; j<cols; j++)
01336 { ret[i][j]=0.0;
01337 for(size_type k=0; k<rows; k++)
01338 ret[i][j]+=matrix[k][i]*matrix[k][j];
01339 }
01340 }
01341
01343 template <typename K, int rows,int cols>
01344 static inline void multAssign(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x, FieldVector<K,rows> & ret)
01345 {
01346 typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01347
01348 for(size_type i=0; i<rows; ++i)
01349 {
01350 ret[i] = 0.0;
01351 for(size_type j=0; j<cols; ++j)
01352 {
01353 ret[i] += matrix[i][j]*x[j];
01354 }
01355 }
01356 }
01357
01359 template <typename K, int rows, int cols>
01360 static inline void multAssignTransposed( const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x, FieldVector<K,cols> & ret)
01361 {
01362 typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01363
01364 for(size_type i=0; i<cols; ++i)
01365 {
01366 ret[i] = 0.0;
01367 for(size_type j=0; j<rows; ++j)
01368 ret[i] += matrix[j][i]*x[j];
01369 }
01370 }
01371
01373 template <typename K, int rows,int cols>
01374 static inline FieldVector<K,rows> mult(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x)
01375 {
01376 FieldVector<K,rows> ret;
01377 multAssign(matrix,x,ret);
01378 return ret;
01379 }
01380
01382 template <typename K, int rows, int cols>
01383 static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x)
01384 {
01385 FieldVector<K,cols> ret;
01386 multAssignTransposed( matrix, x, ret );
01387 return ret;
01388 }
01389
01390 }
01391
01392 #ifdef DUNE_EXPRESSIONTEMPLATES
01393 template <class K, int N, int M>
01394 struct BlockType< FieldMatrix<K,N,M> >
01395 {
01396 typedef K type;
01397 };
01398
01399 template <class K, int N, int M>
01400 struct FieldType< FieldMatrix<K,N,M> >
01401 {
01402 typedef K type;
01403 };
01404 #endif // DUNE_EXPRESSIONTEMPLATES
01405
01408 }
01409
01410 #endif