Main Page   Class Hierarchy   Compound List   File List   Compound Members  

matrix.cpp

00001 /*=============================================================================
00002         File: matrix.cpp
00003      Purpose:
00004     Revision: $Id: matrix.cpp,v 1.2 2002/05/13 21:07:45 philosophil Exp $
00005   Created by:    Philippe Lavoie          (3 Oct, 1996)
00006  Modified by: 
00007 
00008  Copyright notice:
00009           Copyright (C) 1996-1998 Philippe Lavoie
00010  
00011           This library is free software; you can redistribute it and/or
00012           modify it under the terms of the GNU Library General Public
00013           License as published by the Free Software Foundation; either
00014           version 2 of the License, or (at your option) any later version.
00015  
00016           This library is distributed in the hope that it will be useful,
00017           but WITHOUT ANY WARRANTY; without even the implied warranty of
00018           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019           Library General Public License for more details.
00020  
00021           You should have received a copy of the GNU Library General Public
00022           License along with this library; if not, write to the Free
00023           Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00024 =============================================================================*/
00025 
00026 #ifndef MATRIX_SOURCES_
00027 #define MATRIX_SOURCES_
00028 
00029 #include "matrix_global.h"
00030 #include <fstream>
00031 #include <string.h>
00032 
00033 #include "matrix.h"
00034 
00035 
00038 namespace PLib {
00039 
00050 template <class T>
00051 Matrix<T>& Matrix<T>::operator=(const Matrix<T> &a){
00052   int i;
00053   
00054   if ( this == &a )
00055     return *this;
00056   
00057   if ( a.rows() != rows() || a.cols() != cols() ){
00058     resize(a.rows(),a.cols()) ;
00059   }
00060   
00061   int sze = rows()*cols() ;
00062   T *ptr, *aptr ;
00063   ptr = m-1 ;
00064   aptr = a.m-1 ;
00065   
00066   for (i = sze; i > 0; --i)
00067     *(++ptr) = *(++aptr) ;
00068   
00069   by_columns = a.by_columns;
00070   
00071   return *this;
00072 }
00073 
00098 template <class T>
00099 void Matrix<T>::submatrix(int sr, int sc, Matrix<T> &a)
00100 {
00101   int rwz,coz,i,j;
00102   
00103   if ( rows() % a.rows() != 0 || cols() % a.cols() != 0 || rows() < a.rows() || cols() < a.cols() )
00104     {
00105 #ifdef USE_EXCEPTION
00106       throw WrongSize2D(rows(),cols(),a.rows(),a.cols()) ;
00107 #else
00108       Error error("Matrix<T>::submatrix");
00109       error << "Matrix and submatrix incommensurate" ;
00110       error.fatal() ;
00111 #endif
00112     }
00113   
00114   if ( sr >= rows()/a.rows() || sr < 0 || sc >= cols()/a.cols() || sc < 0 )
00115     {
00116 #ifdef USE_EXCEPTION
00117       throw OutOfBound2D(sr,sc,0,rows()/a.rows()-1,0,cols()/a.cols()-1) ;
00118 #else
00119       Error error("Matrix<T>::submatrix");
00120       error << "Submatrix location out of bounds.\nrowblock " << sr << ", " << rows()/a.rows() << " colblock " << sc << ", " << a.cols() << endl ;
00121       error.fatal() ;
00122 #endif
00123     }
00124   rwz = sr*a.rows();
00125   coz = sc*a.cols();
00126   
00127 #ifdef COLUMN_ORDER
00128   for ( i = a.rows()-1; i >= 0; --i )
00129     for(j=a.cols()-1;j>=0;--j)
00130       elem(i+rwz,j+coz) = a(i,j) ;
00131 #else
00132   T *ptr, *aptr ;
00133   aptr = a.m - 1;
00134   for ( i = a.rows()-1; i >= 0; --i )
00135     {
00136       ptr = &m[(i+rwz)*cols()+coz]-1 ;
00137       for ( j = a.cols(); j > 0; --j)
00138         *(++ptr) = *(++aptr) ;
00139     }  
00140 #endif
00141 }
00142 
00156 template <class T> 
00157 void Matrix<T>::as(int rw, int cl, Matrix<T>& a)
00158 {
00159   // Assign matrix a to this matrix at (i,j)
00160   int i, j;
00161   
00162   if ( (rw + a.rows()) > rows() || ( cl + a.cols()) > cols()) {
00163 #ifdef USE_EXCEPTION
00164     throw MatrixErr();
00165 #else
00166     Error error("Matrix<T>::as") ;
00167     error << "Matrix A will not fit in this Matrix at " << rw << ", " << cl << endl ;
00168     error.fatal() ;
00169 #endif
00170   }
00171 
00172 #ifdef COLUMN_ORDER
00173   for(i=0;i<a.rows();++i)
00174     for(j=0;j<a.cols();++j)
00175       elem(i+rw,j+cl) = a(i,j) ;
00176 #else
00177   T *pptr,*aptr ;
00178   aptr = a.m-1 ;
00179   for ( i = 0; i<a.rows(); ++i) {
00180     pptr = &m[(i+rw)*cols()+cl]-1 ;
00181     for ( j = 0; j < a.cols(); ++j)
00182       *(++pptr) = *(++aptr);
00183   }
00184 #endif
00185 }
00186 
00207 template <class T> 
00208 Matrix<T> Matrix<T>::get(int rw, int cl, int nr, int nc) const
00209 {
00210   Matrix<T> getmat(nr,nc) ;
00211   if ( (rw+nr) > rows() || (cl+nc) > cols()) {
00212 #ifdef USE_EXCEPTION
00213     throw MatrixErr();
00214 #else
00215     Error error("Matrix<T>::get") ;
00216     error << "Matrix of size "<< nr << ", " << nc << " not available at " << rw << ", " << cl << endl ;
00217     error.fatal() ;
00218 #endif
00219   }
00220   
00221   int i, j;
00222 
00223 #ifdef COLUMN_ORDER
00224   for(i=0;i<nr;++i)
00225     for(j=0;j<nc;++j)
00226       getmat(i,j) = elem(i+rw,j+cl) ;
00227 #else
00228   T *pptr,*aptr ;
00229   aptr = getmat.m-1;
00230   for (i = 0; i < nr; ++i) {
00231     pptr = &m[(i+rw)*cols()+cl]-1 ;
00232     for ( j = 0; j < nc; ++j)
00233       *(++aptr) = *(++pptr) ;
00234   }
00235 #endif
00236   return getmat ;
00237 }
00238 
00239 
00240 
00249 template <class T> 
00250 double Matrix<T>::norm(void){
00251   int i,j ;
00252   double sum, maxsum;
00253   int init=0 ;
00254   T *pptr ;
00255   pptr = m-1 ;
00256   maxsum = 0 ; // Silence the warning message
00257   for(i=0;i<rows();++i){
00258     sum = 0 ;
00259     for ( j = 0; j < cols(); ++j) 
00260       sum += *(++pptr) ;
00261     if(init)
00262       maxsum = (maxsum>sum) ? maxsum : sum;
00263     else{
00264       maxsum = sum ;
00265       init = 1;
00266     }
00267   }
00268   return maxsum;
00269 }
00270 
00271 
00283 template <class T>
00284 void Matrix<T>::diag(const T a)
00285 {
00286   int i, iend;
00287   
00288   iend = rows();
00289   if ( iend > cols() )
00290     iend = cols();
00291   
00292   for (i = iend-1; i >=0; --i)
00293     elem(i,i) = a;
00294 
00295 }
00296 
00308 template <class T>
00309 Vector<T> Matrix<T>::getDiag(){
00310   int i, iend;
00311   Vector<T> vec(minimum(rows(),cols())) ;
00312   iend = minimum(rows(),cols());
00313   for (i = iend-1; i >=0; --i)
00314       vec[i] = elem(i,i);
00315   return vec ;
00316 }
00317 
00327 template <class T> 
00328 Matrix<T>& Matrix<T>::operator+=(double a)
00329 {
00330   T *p1 ;
00331   p1 = m-1 ;
00332   const int size = rows()*cols() ;
00333   for(int i=size; i>0; --i)
00334     *(++p1) += a ;  
00335   return *this ;
00336 }
00337 
00347 template <class T> 
00348 Matrix<T>& Matrix<T>::operator-=(double a)
00349 {
00350   T *p1 ;
00351   p1 = m-1 ;
00352   const int size = rows()*cols() ;
00353   for(int i=size; i>0; --i)
00354     *(++p1) -= a ;  
00355   return *this ;
00356 }
00357 
00367 template <class T> 
00368 Matrix<T>& Matrix<T>::operator*=(double a)
00369 {
00370   T *p1 ;
00371   p1 = m-1 ;
00372   const int size = rows()*cols() ;
00373   for(int i=size; i>0; --i)
00374     *(++p1) *= a ;  
00375   return *this ;
00376 }
00377 
00387 template <class T> 
00388 Matrix<T>& Matrix<T>::operator/=(double a)
00389 {
00390   T *p1 ;
00391   p1 = m-1 ;
00392   const int size = rows()*cols() ;
00393   for(int i=size; i>0; --i)
00394     *(++p1) /= a ;  
00395   return *this ;
00396 }
00397 
00408 template <class T> 
00409 Matrix<T>& Matrix<T>::operator+=(const Matrix<T> &a)
00410 {
00411   if ( a.rows() != rows() || a.cols() != cols() )
00412     {
00413 #ifdef USE_EXCEPTION
00414       throw WrongSize2D(rows(),cols(),a.rows(),a.cols());
00415 #else
00416       Error error("Matrix<T>::operator+=") ;
00417       if ( rows() != a.rows() )
00418         error << "Matrices are of diferent size, a.rows() = " << rows() << " and b.rows() = " << a.rows() << endl ;
00419       if ( cols() != a.cols())
00420         error << "Matrices are of diferent size, a.cols() = " << cols() << " and b.cols() = " << a.cols() << endl ;
00421       error.fatal() ;
00422 #endif
00423     }
00424 
00425   int i, sze ;
00426   T *aptr,*sptr ;
00427   aptr = a.m - 1 ;
00428   sptr = m - 1 ;
00429   sze = rows()*cols() ;
00430   for (i = sze; i > 0; --i){
00431       *(++sptr) += *(++aptr) ;
00432   }
00433   return *this ;
00434 }
00435 
00446 template <class T>
00447 Matrix<T> operator+(const Matrix<T> &a,const Matrix<T> &b)
00448 {
00449   Matrix<T> sum(a) ;
00450   sum += b ;
00451   return sum;
00452 }
00453 
00468 template <class T> 
00469 Matrix<T>& Matrix<T>::operator-=(const Matrix<T> &a)
00470 {
00471   if ( a.rows() != rows() || a.cols() != cols() )
00472     {
00473 #ifdef USE_EXCEPTION
00474       throw WrongSize2D(rows(),cols(),a.rows(),a.cols());
00475 #else
00476       Error error("Matrix<T>::operator-=") ;
00477       if ( rows() != a.rows() )
00478         error << "Matrices are of diferent size, a.rows() = " << rows() << " and b.rows() = " << a.rows() << endl ;
00479       if ( cols() != a.cols())
00480         error << "Matrices are of diferent size, a.cols() = " << cols() << " and b.cols() = " << a.cols() << endl ;
00481       error.fatal() ;
00482 #endif
00483     }
00484 
00485   int i, size;
00486   T *aptr,*sptr ;
00487   aptr = a.m - 1 ;
00488   sptr = m - 1 ;
00489   size = rows()*cols() ;
00490   for (i = size; i > 0; --i){
00491       *(++sptr) -= *(++aptr) ;
00492   }
00493   return *this ;
00494 }
00495 
00496 
00497 
00510 template <class T>
00511 Matrix<T> operator-(const Matrix<T> &a,const Matrix<T> &b)
00512 {
00513   Matrix<T> diff(a) ;
00514   diff -= b ;
00515   return diff;
00516 }
00517 
00531 template <class T>
00532 Matrix<T> operator*(const Matrix<T> &a,const Matrix<T> &b)
00533 {
00534   if ( a.cols() != b.rows() )
00535     {
00536 #ifdef USE_EXCEPTION
00537       throw WrongSize2D(a.rows(),a.cols(),b.rows(),b.cols()) ;
00538 #else
00539       Error error("Matrix<T> operator*(Matrix<T>&,Matrix<T>&)");
00540       error << "Matrix<T> a * Matrix<T> b incommensurate, a.cols() = " << a.cols() << ", b.rows() = " << b.rows() << endl ;
00541       error.fatal() ;
00542 #endif
00543     }
00544 
00545   int i, j, k, row=a.rows(), col=b.cols(),size = a.cols();
00546   Matrix<T> prod(row,col);
00547   T zero = (T)0;
00548   
00549 #ifdef COLUMN_ORDER
00550   for(i=row-1;i>=0;--i)
00551     for(j=size-1;j>=0;--j)
00552       if(a(i,j) != zero){
00553         for(k=col-1;k>=0; --k)
00554           prod(i,k) += a(i,j)* b(j,k) ;
00555       }
00556 #else
00557   T *pptr,*aptr,*bptr ;
00558   aptr = a.m ;
00559   for (i = 0; i < row; ++i)
00560     for (j = 0; j < size; ++j){
00561       if ( *aptr != zero )
00562         {
00563           pptr = prod[i]-1;
00564           bptr = b[j]-1;
00565           for (k = col; k > 0; --k){
00566             *(++pptr) += *aptr * *(++bptr);
00567           }
00568         }
00569       ++aptr;
00570     }
00571 #endif
00572   return prod;
00573   
00574 }
00575 
00576 
00587 template <class T>
00588 Matrix<T>  operator*(const double d, const Matrix<T> &a)
00589 {
00590   int i, size=a.rows()*a.cols() ;
00591   Matrix<T> b(a.rows(),a.cols());
00592   
00593   T *bptr,*aptr ;
00594   bptr = b.m - 1 ;
00595   aptr = a.m - 1 ;
00596   for (i = size; i > 0; --i)
00597     *(++bptr) = (T)(d * (*(++aptr))) ;
00598   return b;
00599   
00600 }
00601 
00613 template <class T>
00614 Matrix<T>  operator*(const Complex &d, const Matrix<T> &a)
00615 {
00616   int i, size=a.rows()*a.cols() ;
00617   Matrix<T> b(a.rows(),a.cols());
00618   
00619   T *bptr,*aptr ;
00620   bptr = b.m - 1 ;
00621   aptr = a.m - 1 ;
00622   for (i = size; i > 0; --i)
00623     *(++bptr) = (T)real(d) * *(++aptr) ;
00624   return b;
00625 }
00626 
00639 template <class T>
00640 Vector<T> operator*(const Matrix<T> &a, const Vector<T> &x)
00641 {
00642   if ( a.cols() != x.size() )
00643     {
00644 #ifdef USE_EXCEPTION
00645       throw WrongSize2D(a.rows(),a.cols(),x.size(),1);
00646 #else
00647       Error error("Matrix<T> operator*(Matrix<T>& a,Vector<T>& b)");
00648       error << "a * b incommensurate, a.cols() = " << a.cols() << ", b.rows() = " << x.size() << endl ;
00649       error.fatal() ;
00650 #endif
00651     }
00652   
00653   int i, k, row = a.rows(), size = a.cols();
00654   Vector<T> prod(row);
00655   T zero = (T)0;
00656   
00657   T *pptr,*aptr,*xptr ;
00658   aptr = a.m - 1 ;
00659   pptr = &prod[0] ;
00660   for (i = row; i > 0; --i){
00661     xptr = x.memory()-1 ;
00662     for (k = size, *pptr = zero; k > 0 ; --k)
00663       *pptr += *(++aptr) * *(++xptr) ;
00664     ++pptr ;
00665   }
00666   
00667   return prod;
00668 }
00669 
00670 
00687 template <class T>
00688 int operator==(const Matrix<T> &a,const Matrix<T> &b)
00689 {
00690   if ( a.rows() != b.rows() || a.cols() != b.cols() )
00691     {
00692 #ifdef USE_EXCEPTION
00693       throw WrongSize2D(a.rows(),a.cols(),b.rows(),b.cols()) ;
00694 #else
00695       Error error("operator==(const Matrix<T>&,const Matrix<T>&)");
00696       if ( b.rows() != a.rows() )
00697         error << "Matrices are of diferent size, a.rows() = " << a.rows() << " and b.rows() = " << b.rows() << endl ;
00698       if ( b.cols() != a.cols())
00699         error << "Matrices are of diferent size, a.cols() = " << a.cols() << " and b.cols() = " << b.cols() << endl ;
00700       error.fatal() ;
00701 #endif
00702     }
00703   
00704   int i, j, row = a.rows(), col = a.cols();
00705   int l = 1;
00706   
00707   for (i = 0; i < row; ++i)
00708     for (j = 0; j < col; ++j)
00709       l = l && ( a.elem(i,j) == b.elem(i,j) );
00710   
00711   return l;
00712 }
00713 
00725 template <class T>
00726 Matrix<T> comm(const Matrix<T> &a,const Matrix<T> &b)
00727 {
00728   Matrix<T> r = a * b - b * a;
00729   
00730   return r;
00731 }
00732 
00742 template <class T>
00743 T Matrix<T>::trace() const
00744 {
00745   int size = rows();
00746   T sum = (T)0;
00747   
00748   if ( size > cols() )
00749     size = cols();
00750   
00751   for (int d = 0; d < size; ++d)
00752     sum += elem(d,d) ;
00753   
00754   return sum;
00755 }
00756 
00757 
00770 template <class T>
00771 Matrix<T> Matrix<T>::herm() const
00772 {
00773   int i, j, r = cols(), c = rows();
00774   Matrix<T> adj(r,c);
00775   
00776   for (i = 0; i < r; ++i)
00777     for (j = 0; j < c; ++j)
00778       adj.elem(i,j) = elem(j,i) ;
00779 
00780   return adj;
00781 
00782 }
00783 
00794 template <class T>
00795 Matrix<T> Matrix<T>::flop() const
00796 {                                       
00797   Matrix<T> f(rows(),cols()) ;
00798   for(int i=rows()-1;i>=0;--i)
00799     for(int j=cols()-1;j>=0;--j)
00800       {
00801         f(i,j) = elem(i,cols()-j-1);
00802       }
00803   return f; 
00804 }
00805 
00815 template <class T>
00816 Matrix<T> Matrix<T>::transpose() const
00817 {                                       
00818   // same as hermitian for real Matrix<T>
00819   int i, j;
00820   const int& r = cols();
00821   const int& c = rows();
00822   Matrix<T> adj(r,c);
00823   
00824   for (i = r-1; i >=0; --i)
00825     for (j = c-1; j >=0; --j)
00826       adj.elem(i,j) = elem(j,i) ;
00827   
00828   
00829   return adj; 
00830 }
00831 
00832 
00843 template <class T>
00844 int Matrix<T>::read(char* filename) {
00845   ifstream fin(filename) ;
00846   if(!fin) {
00847     resize(1,1) ;
00848     return 0 ;
00849   }
00850   int r,c ;
00851   char *type ;
00852   type = new char[6] ;
00853   if(!fin.read(type,sizeof(char)*6)) return 0 ;
00854   r = strncmp(type,"matrix",6) ;
00855   if(r) return 0 ;
00856   if(!fin.read((char*)&r,sizeof(int))) return 0 ;
00857   if(!fin.read((char*)&c,sizeof(int))) return 0 ;
00858   resize(r,c) ;
00859   if(!fin.read((char*)m,sizeof(T)*r*c)) return 0 ;
00860 
00861   delete []type ;
00862   return 1 ;
00863 }
00864 
00876 template <class T>
00877 int Matrix<T>::read(char* filename,int r, int c) {
00878   ifstream fin(filename) ;
00879   if(!fin) {
00880     resize(1,1) ;
00881     return 0 ;
00882   }
00883   resize(r,c) ;
00884   if(!fin.read((char*)m,sizeof(T)*r*c)) return 0 ;
00885 
00886   return 1 ;
00887 }
00888 
00889 
00901 template <class T>
00902 int Matrix<T>::write(char* filename) {
00903   ofstream fout(filename) ;
00904   if(!fout)
00905     return 0 ;
00906   int r,c ;
00907   r = rows() ; c = cols() ;
00908   if(!fout.write((char*)&"matrix",sizeof(char)*6)) return 0 ;
00909   if(!fout.write((char*)&r,sizeof(int))) return 0 ;
00910   if(!fout.write((char*)&c,sizeof(int))) return 0 ;
00911   if(!fout.write((char*)m,sizeof(T)*r*c)) return 0 ;
00912   return 1;
00913 }
00914 
00925 template <class T>
00926 int Matrix<T>::writeRaw(char* filename) {
00927   ofstream fout(filename) ;
00928   if(!fout)
00929     return 0 ;
00930   if(!fout.write((char*)m,sizeof(T)*rows()*cols())) return 0 ;
00931   return 1;
00932 }
00933 
00934 
00935 template <class T>
00936 void Matrix<T>::qSort(){
00937 #ifdef USE_EXCEPTION
00938   throw MatrixErr();
00939 #else
00940   Error error("Matrix<T>::qSort()");
00941   error << "qSort is not defined for that type.\nPlease defined it in your .cpp file!";
00942   error.fatal() ;
00943 #endif
00944 }
00945 
00946 
00947 }
00948 
00949 
00950 #endif

Generated on Tue Jun 24 13:26:55 2003 for NURBS++ by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002