00001
00002
00003
00004
00005
00006
00007
00008 #ifndef synaps_linalg_MATRIX_H
00009 #define synaps_linalg_MATRIX_H
00010
00011 #include <iostream>
00012 #include <cassert>
00013 #include <synaps/init.h>
00014 #include <synaps/linalg/MethodName.h>
00015 #include <synaps/base/Range.h>
00016
00017 __BEGIN_NAMESPACE_SYNAPS
00018
00019
00020
00021
00022
00023 namespace linalg {template<class R> struct rep1d;}
00024 struct Bareiss;
00025 template<class C, class O, class R> struct MPol;
00026
00040 namespace MATRIX
00041 {
00042 typedef unsigned size_t;
00043 #define TOL 1.e-9
00044
00045
00050 template <class R>
00051 inline std::ostream & print(std::ostream & os,const R & m)
00052 {
00053 typedef typename R::size_type size_type;
00054 for(size_type i=0; i <m.nbrow(); ++i){
00055 os << "[ ";
00056 for(size_type j=0; j<m.nbcol(); j++) os<< m(i,j) <<" ";
00057 os << "]"<< std::endl;
00058 }
00059 return os;
00060 }
00061
00067 template<class M> inline
00068 std::istream & read( std::istream & is, M & m, ByRow br = ByRow() ){
00069 typedef typename M::size_type size_type;
00070 size_type nrw,ncl;
00071 is >> nrw >> ncl;
00072 m.resize(nrw,ncl);
00073 for( size_type i = 0; i < nrw && is.good(); i++ )
00074 for( size_type j = 0; j < ncl && is.good(); j++ )
00075 is >> m(i,j);
00076 return(is);
00077 }
00078
00079 template<class M> inline
00080 std::istream & read( std::istream & is, M & m, ByCol ){
00081 typedef typename M::size_type size_type;
00082 size_type nrw,ncl;
00083 is >> nrw >> ncl;
00084 m.resize(nrw,ncl);
00085 for( size_type j = 0; j < ncl && is.good(); j++ )
00086 for( size_type i = 0; i < nrw && is.good(); i++ )
00087 is >> m(i,j);
00088 return(is);
00089 }
00090
00091
00093 template<class R, class C> inline
00094 void init(R & a, const C & c)
00095 {
00096 typedef typename R::size_type size_type;
00097 for(size_type i=0; i<a.nbrow(); i++)
00098 for(size_type j=0; j <a.nbcol(); j++)
00099 a(i,j)=c;
00100 }
00101
00102 template<class M> inline
00103 void init( M & m, const typename M::value_type * data, ByRow )
00104 {
00105 for( int i = 0; i < m.nbrow() ; i++ )
00106 for( int j = 0; j < m.nbcol() ; m(i,j) = *data++, j++ );
00107 };
00108
00109 template<class M> inline
00110 void init( M & m, const typename M::value_type * data, ByCol )
00111 {
00112 for( int j = 0; j < m.nbcol() ; j++ )
00113 for( int i = 0; i < m.nbrow() ; m(i,j) = *data++, i++ );
00114 }
00115
00116 template<class M> inline
00117 void init( M & m, std::istream & ins, ByRow )
00118 {
00119 for( int i = 0; i < m.nbrow() ; i++ )
00120 for( int j = 0; j < m.nbcol() ; j ++ )
00121 {
00122 if ( ! ins.good() ) return;
00123 ins >> m(i,j);
00124 };
00125 };
00126
00127 template<class M> inline
00128 void init( M & m, std::istream & ins, ByCol )
00129 {
00130 for( int j = 0; j < m.nbcol() ; j++ )
00131 for( int i = 0; i < m.nbrow() ; i ++ )
00132 {
00133 if ( ! ins.good() ) return;
00134 ins >> m(i,j);
00135 };
00136 };
00137
00138 template<class M, class Data, class Order> inline
00139 void init( M & m,
00140 typename M::size_type nrw,
00141 typename M::size_type ncl,
00142 Data & data, Order )
00143 {
00144 m.resize(nrw,ncl);
00145 init(m,data,Order());
00146 };
00147
00148
00149
00151 template<class R, class Int> inline
00152 void reserve(R & a, const Int & m, const Int & n)
00153 {
00154 a.resize(m,n);
00155 }
00156
00157 template<class M, class C>
00158 void mul_ext( M & m, const C & c )
00159 {
00160 for ( int i = 0; i < m.nbrow(); i ++ )
00161 for ( int j = 0; j < m.nbcol(); j ++ )
00162 m(i,j) = m(i,j) * c;
00163 };
00164
00165 template<class V, class M>
00166 void getrow( V & v, const M & m, int i )
00167 { for ( int k = 0; k < m.nbcol(); k ++ ) let::assign(v[k],m(i,k)); };
00168
00169 template<class V, class M>
00170 void getcol( V & v, const M & m, int i )
00171 { for ( int k = 0; k < m.nbrow(); k ++ ) let::assign(v[k],m(k,i)); };
00172
00173
00174 template<class SM, class M>
00175 void submatrix( SM & sm, const M & m, const Range2d & rg )
00176 {
00177 using let::assign;
00178 typedef typename M::size_type sz_t;
00179 sz_t i1 = rg.i1, i2 = rg.i2, j1 = rg.j1, j2 = rg.j2;
00180 sm.resize(i2-i1+1,j2-j1+1);
00181 for( sz_t i = i1; i < i2+1; i++ )
00182 for( sz_t j = j1; j < j2+1; j++ )
00183 assign(sm(i-i1,j-j1),m(i,j));
00184 };
00185
00186 template<class M, class Ma, class C>
00187 void mul_ext( M & m, const Ma & a, const C & c )
00188 {
00189 m.resize( a.nbrow(), a.nbcol() );
00190 for ( int i = 0; i < m.nbrow(); i ++ )
00191 for ( int j = 0; j < m.nbcol(); j ++ )
00192 m(i,j) = a(i,j) * c;
00193 };
00194
00195 template<class M, class C>
00196 void div_ext( M & m, const C & c )
00197 {
00198 for ( int i = 0; i < m.nbrow(); i ++ )
00199 for ( int j = 0; j < m.nbcol(); j ++ )
00200 m(i,j) /= c;
00201 };
00202
00203 template<class M, class Ma, class C>
00204 void div_ext( M & m, const Ma & a, const C & c )
00205 {
00206 m.resize( a.nbrow(), a.nbcol() );
00207 for ( int i = 0; i < m.nbrow(); i ++ )
00208 for ( int j = 0; j < m.nbcol(); j ++ )
00209 m(i,j) = a(i,j) / c;
00210 };
00211
00212 template<class M>
00213 void swaprow( M & m, int i, int j )
00214 { if(i!=j) for(int l=0; l< m.nbcol();l++) std::swap(m(i,l),m(j,l)); };
00215 template<class M>
00216 void swapcol( M & m, int i, int j )
00217 { if(i!=j) for(int l=0; l< m.nbrow();l++) std::swap(m(l,i),m(l,j)); };
00218 template<class M, class C>
00219 void addrow( M & m, typename M::size_type i, typename M::size_type j, const C & c )
00220 { for( int l=0; l < m.nbcol();l++) m(i,l) += m(j,l)*c; };
00221 template<class M, class C>
00222 void addcol( M & m, int i, int j, const C & c )
00223 { for( int l=0; l < m.nbrow();l++) m(l,i) += m(l,j)*c; };
00224 template<class M, class C>
00225 void multrow( M & m, int i, const C & c )
00226 { for( int l=0; l< m.nbcol();l++) m(i,l)*=c; };
00227 template<class M, class C>
00228 void multcol( M & m, int i, const C & c )
00229 { for( int l=0; l< m.nbrow();l++) m(l,i)*=c; };
00230
00233 template <class R1, class R2>
00234 inline void assign(R1 & r, const R2 & m)
00235 {
00236 using let::assign;
00237 typedef typename R1::size_type size_type;
00238 for(size_type i=0; i <m.nbrow(); ++i)
00239 for(size_type j=0; j<m.nbcol(); j++)
00240 assign(r(i,j),m(i,j));
00241 }
00242
00244 template<class R> inline
00245 typename R::value_type trace(const R & M)
00246 {
00247 typename R::value_type tr(0);
00248 for (typename R::size_type i=0; i<M.nbrow(); i++) tr+=M(i,i);
00249 return tr;
00250 }
00251
00253 template<class R,class S> inline
00254 void add(R & a, const S & b )
00255 {
00256 typedef typename R::size_type size_type;
00257 for(size_type i=0; i<a.nbrow(); i++)
00258 for(size_type j=0; j <a.nbcol(); j++)
00259 a(i,j) += b(i,j);
00260 }
00261
00265 template<class R,class S,class T> inline
00266 void add(R & a, const S & b, const T & c)
00267 {
00268 assert((b.nbrow()==c.nbrow()) && (b.nbcol()==c.nbcol()) );
00269 typedef typename R::size_type size_type;
00270
00271 for(size_type i=0; i<a.nbrow(); i++)
00272 for(size_type j=0; j <a.nbcol(); j++)
00273 a(i,j) = b(i,j)+c(i,j);
00274 }
00275
00278 template<class R,class S> inline
00279 void sub(R & a, const S & b )
00280 {
00281 typedef typename R::size_type size_type;
00282 for(size_type i=0; i<a.nbrow(); i++)
00283 for(size_type j=0; j <a.nbcol(); j++)
00284 a(i,j) -= b(i,j);
00285 }
00286
00289 template<class R> inline
00290 void sub(R & a, const R & b, const R & c)
00291 {
00292 assert((b.nbrow()==c.nbrow()) && (b.nbcol()==c.nbcol()) );
00293 typedef typename R::size_type size_type;
00294
00295 for(size_type i=0; i<a.nbrow(); i++)
00296 for(size_type j=0; j <a.nbcol(); j++)
00297 a(i,j) = b(i,j)-c(i,j);
00298 }
00299
00303 template<class R,class S,class T> inline
00304 void mul(R & a, const S & b, const T & c)
00305 {
00306 assert((&a != &c) && (&a != &b));
00307 typedef typename R::size_type size_type;
00308 typedef typename R::value_type value_type;
00309 for(size_type i=0; i<b.nbrow(); i++)
00310 for(size_type j=0; j< c.nbcol(); j++){
00311 for(size_type k=0; k < b.nbcol(); k++) {
00312 a(i,j) += b(i,k)*c(k,j);
00313 }
00314 }
00315 }
00316
00318 template<class R,class S> inline
00319 void mul(R & a, const S & b)
00320 {
00321 assert((&a != &b));
00322 assert((a.nbcol()==b.nbrow()));
00323 typedef typename R::size_type size_type;
00324 typedef typename R::value_type value_type;
00325
00326 R at(a);
00327 a.resize(a.nbrow(),b.nbcol());
00328 init(a,0);
00329
00330 for(size_type i=0; i<a.nbrow(); i++)
00331 {
00332
00333 for(size_type j=0; j< b.nbcol(); j++)
00334 for(size_type k=0; k < at.nbcol(); k++) {
00335 a(i,j) += at(i,k)*b(k,j);
00336 }
00337
00338 }
00339 }
00340
00345 template<class V,class M,class W> inline
00346 void mul_vect(V & a, const M & b, const W & v)
00347 {
00348 assert(&a != &v);
00349 typedef typename M::size_type size_type;
00350 typedef typename V::value_type value_type;
00351 for(size_type i=0; i<b.nbrow(); i++)
00352 {
00353 a[i] = 0;
00354 for(size_type j=0; j< b.nbcol(); j++)
00355 a[i] += b(i,j)*v;
00356 };
00357 }
00358
00359
00361 template <class R>
00362 void transpose(R & M)
00363 {
00364 typedef typename R::size_type size_type;
00365
00366 if (M.nbrow()==M.nbcol())
00367 for(size_type i = 0; i < M.nbrow(); i++)
00368 for(size_type j = i+1; j < M.nbcol(); j++)
00369 std::swap(M(i, j), M(j, i));
00370 else {
00371 R tmp(M.nbcol(),M.nbrow());
00372 for(size_type i = 0; i < M.nbrow(); i++)
00373 for(size_type j = 0; j < M.nbcol(); j++)
00374 tmp(j, i)= M(i, j);
00375 M=tmp;
00376 }
00377 }
00378 template<class R>
00379 bool equal( const R & a, const R & b )
00380 {
00381 if (a.nbrow() != b.nbrow() || a.nbcol() != b.nbcol()) return false;
00382
00383 unsigned i;
00384 for(i=0;i<a.nbrow(); i++)
00385 {
00386 unsigned j;
00387 for(j=0;j<a.nbcol() && a(i,j)==b(i,j); j++);
00388 if(j!=a.nbcol()) return false;
00389 }
00390 if(i!=a.nbrow()) return false;
00391
00392 return true;
00393 };
00394
00395
00398 template<class R>
00399 void setupper(R & A)
00400 {
00401 for(unsigned j=0 ; j< A.nbcol(); j++)
00402 for(unsigned i=j+1; i < A.nbrow(); i++)
00403 A(i,j) =0;
00404 }
00405
00408 template<class R>
00409 void setlower(R & A)
00410 {
00411 for(unsigned j=0 ; j< A.nbcol(); j++)
00412 for(unsigned i=0; i < j && i < A.nbrow(); i++)
00413 A(i,j) =0;
00414 }
00415
00416
00417
00418
00419
00420
00421
00438 template<class Vect, class Mat>
00439 void svd(Vect & S, const Mat & A, Mat & Us, Mat & V)
00440 {
00441 #ifdef VERBATIM
00442 std::cout <<"Using the generic svd" << std::endl;
00443 #endif
00444 typedef typename Vect::size_type index_t;
00445 typedef typename Vect::value_type C;
00446
00447 int i, j, k, EstColRank, RotCount, SweepCount, slimit;
00448 C eps, e2, tol, vt, p, x0, y0, q, r, c0, s0=0, d1, d2;
00449 int nRow = A.nbrow(), nCol = A.nbcol();
00450 eps = C(TOL);
00451 slimit = nCol/4;
00452
00453 Us=A;
00454 V.resize(nCol,nCol);
00455
00456 if (slimit < 6.0)
00457 slimit = 6;
00458 SweepCount = 0;
00459 e2 = C(10.0)*C(nRow)*eps*eps;
00460 tol = eps*C(.1);
00461 EstColRank = nCol;
00462 for (i=0; i<nCol; i++)
00463 for (j=0; j<nCol; j++)
00464 {
00465 V(j,i) = C(0.0);
00466 V(i,i) = C(1.0);
00467 }
00468
00469 RotCount = EstColRank*(EstColRank-1)/2;
00470 while (RotCount != 0 && SweepCount <= slimit)
00471 {
00472 RotCount = EstColRank*(EstColRank-1)/2;
00473 SweepCount++;
00474 for (j=0; j<EstColRank-1; j++)
00475 {
00476 for (k=j+1; k<EstColRank; k++)
00477 {
00478 p = q = r = C(0.0);
00479 for (i=0; i<nRow; i++)
00480 {
00481 x0 = Us(i,j); y0 = Us(i,k);
00482 p += x0*y0; q += x0*x0; r += y0*y0;
00483 }
00484 S = q; S = r;
00485 if (q >= r)
00486 {
00487 if (q<=e2*S[0] || (Norm(p)<=(tol*q))) RotCount--;
00488 else
00489 {
00490 p /= q; r = -r/q+1; vt = sqrt(p*p*4+r*r);
00491 c0 = sqrt(Norm((r/vt+1)*C(.5)));
00492 s0 = p/(vt*c0);
00493 for (i=0; i<nRow; i++)
00494 {
00495 d1 = Us(i,j); d2 = Us(i,k);
00496 Us(i,j) = d1*c0+d2*s0; Us(i,k) = -d1*s0+d2*c0;
00497 }
00498 for(i=0; i<nCol; i++)
00499 {
00500 d1 = V(j,i); d2 = V(k,i);
00501 V(j,i) = d1*c0+d2*s0;
00502 V(k,i) = -d1*s0+d2*c0;
00503 }
00504 }
00505 }
00506 else
00507 {
00508 p /= r; q = q/r-C(1); vt = sqrt(p*p*4+q*q);
00509 s0 = sqrt(Norm(C(.5)*(-q/vt+1)));
00510 if (p<0) s0 = -s0;
00511 c0 = p/(vt*s0);
00512 for (i=0; i<nRow; i++)
00513 {
00514 d1 = Us(i,j); d2 = Us(i,k);
00515 Us(i,j) = d1*c0+d2*s0; Us(i,k) = -d1*s0+d2*c0;
00516 }
00517 for (i=0; i<nCol; i++)
00518 {
00519 d1 = V(j,i); d2 = V(k,i);
00520 V(j,i) = d1*c0+d2*s0; V(k,i) = -d1*s0+d2*c0;
00521 }
00522 }
00523 }
00524 }
00525 while (EstColRank>=3 && S[(EstColRank-1)]<=S[0]*tol+tol*tol)
00526 EstColRank--;
00527 }
00528 #if DEBUG
00529
00530
00531 #endif
00532 for(index_t i=0;i<S.size();i++) S[i]=sqrt(S[i]);
00533
00534 }
00535
00536
00539 template<class Vect, class Mat>
00540 void svd(Vect & S, const Mat & A)
00541 {
00542 int m=A.nbrow(), n=A.nbcol();
00543 Mat U(m,m), V(n,n);
00544 svd(S,A,U,V);
00545 }
00546
00548 template <class R>
00549 bool good_pivot(Bareiss, R & A)
00550 {
00551 return A != 0;
00552 }
00553
00557 template<class C, class O, class R>
00558 bool good_pivot(Bareiss, MPol<C,O,R> & A)
00559 {
00560 typedef typename MPol<C,O,R>::iterator iterator;
00561 bool result = false;
00562 C Precision = 1e-12;
00563 for(iterator it=A.begin(); it != A.end(); ++it)
00564 if(it->coeff() > Precision)
00565 return true;
00566 return false;
00567 }
00568
00570 template<class R>
00571 typename R::value_type decomp(LU lu, R & A)
00572 {
00573 typedef unsigned size_type ;
00574 typedef typename R::value_type value_type;
00575
00576 size_type n = A.nbrow(), m = A.nbcol();
00577 size_type rmar = m, r=0, i,j;
00578 int s = 1;
00579 value_type d=1;
00580
00581 for(size_type k=0; k< std::min(m, rmar) && r < n; k++) {
00582 for(i=r; i<n && A(i,k) == 0;i++);
00583
00584 for(j=i+1; j<n; j++) {
00585 if(A(j,k) !=0 && size(A(j, k)) < size(A(i,k))) {
00586 i=j;
00587 }
00588 }
00589 if(i < n) {
00590 if( i != r) {
00591 s *= -1;
00592 for(j=k;j<m;j++) {
00593 std::swap(A(i,j), A(r,j));
00594 }
00595 }
00596 for(i = r+1;i<n;i++) {
00597 for(j=k+1;j<m;j++) {
00598 d = A(i,k)/A(r,k);
00599 A(i,j) -= A(r,j)*d;
00600 }
00601 A(i, k) = 0;
00602 }
00603 r++;
00604 }
00605 }
00606 if(s==-1)
00607 return -A(A.nbrow()-1,A.nbcol()-1);
00608 else
00609 return A(A.nbrow()-1,A.nbcol()-1);
00610 }
00611
00612
00619 template <class R>
00620 typename R::value_type decomp(Bareiss, R & A, unsigned & r)
00621 {
00622 typedef unsigned size_t;
00623 typedef typename R::value_type value_type;
00624 r=0;
00625 size_t n = A.nbrow(), m = A.nbcol();
00626 size_t rmar = m, i,j;
00627 int s = 1;
00628 value_type d=1;
00629 for(size_t k=0; k< std::min(m, rmar) && r < n; k++) {
00630 for(i=r; i<n && (size(A(i,k)) == 0);i++);
00631
00632 for(j=i+1; j<n; j++) {
00633 if(A(j,k) !=0 && size(A(j, k)) < size(A(i,k))){
00634 i=j;
00635 }
00636 }
00637 if(i < n) {
00638 if( i != r) {
00639 s *= -1;
00640 for(j=k;j<m;j++) {
00641 std::swap(A(i,j),A(r,j));
00642 }
00643 }
00644 for(i = r+1;i<n;i++) {
00645 for(j=k+1;j<m;j++) {
00646 A(i,j) = (A(i,j)*A(r,k) - A(r,j)*A(i,k));
00647 A(i,j) /= d;
00648 }
00649 A(i, k) = 0;
00650 }
00651 d= A(r, k);
00652 r++;
00653 }
00654 }
00655 if(s==-1)
00656 return -A(A.nbrow()-1,A.nbcol()-1);
00657 else
00658 return A(A.nbrow()-1,A.nbcol()-1);
00659 }
00660
00661 template <class R>
00662 typename R::value_type decomp(const Bareiss& mth, R & A)
00663 {
00664 unsigned rk=0;
00665 return decomp(mth,A,rk);
00666 }
00667
00673 template<class R>
00674 typename R::size_type rank(const R & M)
00675 {
00676 typedef typename R::size_type size_type;
00677 typedef typename R::value_type value_type;
00678 linalg::rep1d<value_type> S(std::min(M.nbrow(),M.nbcol()));
00679 svd(S,M);
00680 size_type i= S.size()-1;
00681 for(; i>=0 && S*TOL>S;i--);
00682 return i+1;
00683 }
00684
00688 template<class R>
00689 typename R::size_type rank(const Bareiss & mth, const R & M)
00690 {
00691 unsigned rk=0;
00692 R A=M;
00693 decomp(mth,A,rk);
00694 return rk;
00695 }
00696
00697
00698
00701 template<class MAT>
00702 void kronecker(MAT& r, const MAT& a, const MAT& b)
00703 {
00704 r.resize(a.nbrow()*b.nbrow(),a.nbcol()*b.nbcol());
00705 for(unsigned i=0;i<a.nbrow();i++)
00706 for(unsigned j=0;j<a.nbcol();j++)
00707 for(unsigned k=0;k<b.nbcol();k++)
00708 for(unsigned l=0;l<b.nbcol();l++)
00709 r(i*b.nbrow()+k,j*b.nbrow()+l)=a(i,j)*b(k,l);
00710 }
00711 }
00712
00713 __END_NAMESPACE_SYNAPS
00714
00715 #endif // synaps_linalg_MATRIX_H
00716