synaps/linalg/MATRIX.m

00001 /*********************************************************************
00002 *      This file is part of the source code of SYNAPS kernel.        *
00003 *   Author(s): B. Mourrain, GALAAD, INRIA                            *
00004 **********************************************************************
00005 History: 
00006 $Id: MATRIX.h,v 1.2 2005/09/28 06:40:50 mourrain Exp $
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 // namespace let 
00020 // {
00021 //   template<class A, class B> inline void assign(A& a, const B& b);
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     //    linalg::rep1d<value_type> r(b.nbcol());
00330     for(size_type i=0; i<a.nbrow(); i++) 
00331       {
00332         //      for(size_type j=0; j< b.nbcol(); j++) r[j]=0;
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         //      for(size_type j=0; j< b.nbcol(); j++) a(i,j)=r[j];
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   /* This SVD routine is based on pgs 30-48 of "Compact Numerical Methods
00417      for Computers" by J.C. Nash (1990), used to compute the pseudoinverse.
00418      First implementation by bryant@sioux.stanford.edu (Bryant Marks).
00419      Modification by Bernard.Mourrain@sophia.inria.fr for genericity.
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;  // Copy of A in Us;
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     //  if (SweepCount > slimit)
00530     //    fprintf(stderr, "Sweeps = %d\n", SweepCount);
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;// t;
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;// t;
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 } //MATRIX
00712 //--------------------------------------------------------------------
00713 __END_NAMESPACE_SYNAPS
00714 /********************************************************************/
00715 #endif // synaps_linalg_MATRIX_H
00716 

SYNAPS DOCUMENTATION
logo