Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

linalg.cpp

00001 #include "linalg.h"
00002 #include "util.h"
00003 #include "qscr.h"
00004 #include <sstream>
00005 #include <iomanip>
00006 #include <cassert>
00007 #include <cstring>
00008 #include <cstdlib>
00009 #include <cmath>
00010 
00011 
00012 matrix matrix::addcolumns()
00013 {
00014   long i,j;
00015   matrix B(rows);
00016   for(i=0;i<=rows-1;i++)
00017     {   
00018       for(j=0;j<=columns-1;j++)
00019         B.A[i][0] += A[i][j];
00020     }
00021   return(B);
00022 }
00023 
00024 matrix matrix::getrow(long i) const
00025 {
00026   long j;
00027   matrix B(1,columns);
00028   for (j=0; j<=columns-1;j++)
00029     B.A[0][j] = A[i][j];
00030   return(B);
00031 }
00032 
00033 matrix matrix::getcolumn(long i) const
00034 {
00035   long j;
00036   matrix B(rows);
00037   for (j=0; j<=rows-1; j++)
00038     B.A[j][0] = A[j][i];
00039   return(B);
00040 }
00041 
00042 void matrix::setrow(const matrix &B, long i)
00043 {
00044   long j;
00045   if (columns != B.columns)
00046     error("Wrong dimensions in matrix setrow \n");
00047   for (j=0; j<=columns-1; j++)
00048     A[i][j] = B.A[0][j];
00049 }
00050   
00051 void matrix::setcolumn(const matrix &B, long i)
00052 {
00053   long j;
00054   if (rows != B.rows)
00055     error("Wrong dimensions in matrix setcolumn \n");
00056   for (j=0; j<=rows-1; j++)
00057     A[j][i] = B.A[j][0];
00058 }
00059 
00060 long matrix::operator==(const matrix &B)
00061 {
00062   long i,j,eq=1;
00063   if ((rows != B.rows) & (columns != B.columns))
00064     error("Wrong dimensions in matrix equal \n");                           
00065   else 
00066     {
00067       for(i=0; (i<=rows-1) & eq; i++)
00068         {
00069           for(j=0; (j<=columns-1) & eq; j++)
00070             eq = (A[i][j] == B.A[i][j]);
00071         }
00072     }
00073   return(eq);
00074 }
00075         
00076 void matrix::print() const
00077 {
00078   long i,j;
00079   //  std::cerr << "\n";
00080   for(i=0;i<=rows-1;i++)
00081     {
00082       for(j=0;j<=columns-1;j++) {
00083         std::string ss = numStr(A[i][j]) + "    ";
00084         qaddstr(ss.c_str());    
00085       }
00086         qinsertln();
00087         //std::cerr << A[i][j] << " ";
00088         //      std::cerr << "\n";
00089     }
00090 }
00091 
00092 void matrix::stdprint() const
00093 {
00094   long i,j;
00095   std::cerr  << "[";
00096   for(i=0;i<=rows-1;i++)
00097     {
00098       for(j=0;j<=columns-1;j++) {
00099         std::cerr << A[i][j];
00100         if (j<columns-1)
00101           std::cerr << " ";
00102       }
00103       if (i<rows-1)
00104         std::cerr << ";" << std::endl;
00105     }
00106   std::cerr << "]";
00107 }
00108 
00109 
00110 
00111 matrix matrix::operator*(const double &x)
00112 {
00113   long i,j;
00114   matrix C(rows,columns);
00115   for(i=0;i <= C.rows-1; i++)
00116     {
00117       for(j=0; j<=C.columns-1;j++)
00118         {
00119           C.A[i][j] = x*A[i][j];
00120         }
00121     }
00122   return(C);
00123 }
00124 
00125 
00126 matrix matrix::operator*(const matrix &B)
00127 {
00128   long i,j,k;
00129   matrix C(rows,B.columns);
00130   if (columns != B.rows) 
00131     error("Wrong dimensions in matrix multiplication \n");
00132   else 
00133     { 
00134       for(i=0;i <= C.rows-1; i++)
00135         {
00136           for(j=0; j<=C.columns-1;j++)
00137             {
00138               for(k=0;k<=columns-1;k++)
00139                 C.A[i][j] += A[i][k]*B.A[k][j];
00140             }
00141         }
00142     }
00143   return(C);
00144 }
00145 
00146 matrix matrix::trans() 
00147 {
00148   long i,j;
00149   matrix B(columns,rows);
00150   for (i=0;i<=columns-1;i++)
00151     {
00152       for(j=0;j<=rows-1;j++)
00153         B.A[i][j] = A[j][i];
00154     }
00155   return(B);
00156 }
00157     
00158 matrix matrix::operator+(const matrix &B)
00159 {
00160   long i,j;
00161   matrix C(rows,columns);
00162   if ((rows != B.rows) & (columns != B.columns))
00163     error("Wrong dimensions in matrix plus \n");                            
00164   else 
00165     {
00166       for(i=0;i <= rows-1; i++)
00167         {
00168           for(j=0; j<=columns-1;j++)
00169             C.A[i][j] = A[i][j] + B.A[i][j];
00170         }
00171     }
00172   return(C);
00173 }
00174 
00175 matrix matrix::operator-(const matrix &B)
00176 {
00177   long i,j;
00178   matrix C(rows,columns);
00179   if ((rows != B.rows) & (columns != B.columns))
00180     error("Wrong dimensions in matrix minus \n");                           
00181   else 
00182     {
00183       for(i=0;i <= rows-1; i++)
00184         {
00185           for(j=0; j<=columns-1;j++)
00186             C.A[i][j] = A[i][j] - B.A[i][j];
00187         }
00188     }
00189   return(C);
00190 }
00191 
00192 double matrix::twonorm()
00193 {
00194   long i,j;
00195   double norm=0;
00196   for(i=0;i<=rows-1;i++)
00197     {
00198       for(j=0;j<=columns-1;j++)
00199         norm += A[i][j]*A[i][j];
00200     }
00201   norm = sqrt(norm);
00202   return(norm);
00203 }
00204 
00205 double matrix::onenorm()
00206 {
00207   long i,j;
00208   double norm=0;
00209   for(i=0;i<=rows-1;i++)
00210     {
00211       for(j=0;j<=columns-1;j++)
00212         norm += num(A[i][j]);
00213     }
00214   return(norm);
00215 }
00216 
00217 safevector<double> matrix::mean() const {
00218   safevector<double> m(columns);
00219   for (long s=0; s<columns; s++) {
00220     double sum = 0;
00221     for (long r=0; r<rows; r++) {
00222       sum += A[r][s];
00223     }
00224     m[s] = sum/(double)rows;
00225   }
00226   return m;
00227 }
00228 
00229 safevector<double> matrix::var() const {
00230   safevector<double> mu = mean();
00231   safevector<double> v(columns);
00232   for (long s=0; s<columns; s++) {
00233     double sum = 0;
00234     for (long r=0; r<rows; r++) {
00235       double xe = A[r][s]-mu[s];
00236       sum +=  xe*xe;
00237     }
00238     v[s] = sum/((double)rows-1);
00239   }
00240   return v;
00241 }
00242 
00243 matrix matrix::covar() const {
00244   safevector <double> m = mean();
00245   matrix res(columns, columns);
00246   for (int x=0; x<columns; x++) {
00247     for (int y=x; y<columns; y++) {
00248       double sum = 0;
00249       for (int i=0; i<rows; i++) {
00250         sum += (A[i][x]-m[x])*(A[i][y]-m[y]);
00251       }
00252       double val = sum/(double)(rows-1);
00253       res.set(val,x,y);
00254       res.set(val,y,x);
00255     }
00256   }
00257   return res;
00258 }
00259 
00260 
00261 matrix matrix::inv()
00262 {
00263   long *indxc =new long[rows];
00264   long *indxr = new long[rows];
00265   long *ipiv = new long[rows];
00266   long i, icol = 0, irow = 0, j, k, l, ll;
00267   double big, dum, pivinv;
00268   matrix B(rows,columns);
00269 
00270   for(i=0;i<=rows-1;i++)
00271     {
00272       indxc[i]=0;
00273       indxr[i]=0;
00274       ipiv[i]=0;
00275     }
00276 
00277   if (columns != rows) 
00278     error("Cannot invert non-square matrix \n");
00279   else
00280     for(i=0;i<=rows-1;i++)
00281       {
00282         for(j=0;j<=columns-1;j++)
00283           B.A[i][j] = A[i][j];
00284       }
00285  
00286       
00287   for (i=0;i<=columns-1;i++)
00288     {
00289       big = 0.0;
00290       for (j=0;j<=rows-1;j++)
00291         {
00292           if (ipiv[j] != 1)
00293             for (k=0;k<=columns-1;k++)
00294               {
00295                 if (ipiv[k] == 0)
00296                   {
00297                     if (fabs(B.A[j][k]) >=big)
00298                       {
00299                         big = fabs(B.A[j][k]);
00300                         irow = j;
00301                         icol = k;
00302                       }
00303                   } 
00304                 else if (ipiv[k] > 1) error("inv: Singular Matrix-1");
00305               }
00306         }
00307       ++(ipiv[icol]);
00308       if (irow != icol)
00309         {
00310           for (l=0;l<=columns-1;l++) B.swap(irow,icol);
00311         }
00312       indxr[i] = irow;
00313       indxc[i] = icol;
00314       if (B.A[icol][icol] == 0.0) error("inv: Singular Matrix-2");
00315       pivinv = 1.0/B.A[icol][icol]; 
00316       B.A[icol][icol] = 1.0;
00317       for (l=0;l<=columns-1;l++) B.A[icol][l] *= pivinv;
00318       for (ll=0;ll<=rows-1;ll++)
00319         if (ll != icol)
00320           {
00321             dum = B.A[ll][icol];
00322             B.A[ll][icol] = 0.0;
00323             for (l=0;l<=columns-1;l++) 
00324               B.A[ll][l] -= B.A[icol][l]*dum;
00325       
00326           }
00327     }
00328   for(l=columns-1;l>=0;l--)
00329     {
00330       if (indxr[l] != indxc[l])
00331         B.swapc(indxr[l],indxc[l]);
00332     }
00333   delete(ipiv);
00334   delete(indxr);
00335   delete(indxc);
00336   return(B);
00337 }
00338 
00339 matrix matrix::map(double(*f)(double)) {
00340   matrix res(rows,columns);
00341   for (int r=0; r<rows; r++)
00342     for (int s=0; s<columns; s++)
00343       res.set(f(A[r][s]),r,s);
00344 
00345   return res;
00346 }
00347 
00348 double matrix::maxvalue(){
00349 
00350   double max=A[0][0];  
00351   for(int i=0; i<rows;i++){
00352     for(int j=0; j<columns; j++)
00353       if (A[i][j]>max) max=A[i][j];
00354   }
00355   return(max);
00356 
00357 }
00358 
00359 
00360 
00361 const char* matrix::row2string(int r) {
00362   assert(r>=0 && r<rows);
00363 
00364   std::ostringstream mstr;
00365   mstr.setf(std::ios::fixed);
00366   std::string res;
00367   for (int i=0; i<columns; i++) {
00368     mstr << std::setw(9) << A[r][i] << " ";
00369   }
00370   
00371   std::string ss = mstr.str();    
00372 
00373   return ss.c_str();
00374 }
00375 
00376 
00377 matrix covar2(matrix const& X, matrix const& Y) {
00378   assert(X.row()==Y.row() && (X.column()==Y.column() || Y.column()==1));
00379 
00380   safevector <double> mx = X.mean();
00381   safevector <double> my = Y.mean();
00382   matrix cv(X.column());
00383 
00384 
00385   // If Y is a column-vector we calculate [cov(X_1,Y),...,cov(X_n,Y)].
00386   if (Y.column()==1) {
00387     for (int s=0; s<X.column(); s++) {
00388       double sum=0;
00389       for (int i=0; i<X.row(); i++) {
00390         sum += (X.get(i,s)-mx[s])*(Y.get(i)-my[0]);
00391         //      std::cerr << "sum+=" << sum << std::endl;
00392       }
00393       cv.set(sum/(double)(X.row()-1),s);
00394     }
00395     return cv; 
00396   }
00397  
00398 
00399   // Else we calculate [cov(X_1,Y_1),....,cov(X_n,Y_n)].
00400   for (int s=0; s<X.column(); s++) {
00401     double sum=0;
00402     for (int i=0; i<X.row(); i++) {
00403       sum += (X.get(i,s)-mx[s])*(Y.get(i,s)-my[s]);
00404     }
00405     cv.set(sum/(double)(X.row()-1),s);
00406   }
00407   return cv;
00408 }
00409 
00410 
00411 //####################################################################
00412 
00413 #ifdef TEST
00414 
00415 
00416 double cubic(double x) {
00417   return x*x*x;
00418 }
00419 
00420 double square(double x) {
00421   return x*x;
00422 }
00423 
00424 double identity(double x) {
00425   return x;
00426 }
00427 
00428 int main() {
00429   try {
00430 
00431     matrix A(4,4);
00432     for (unsigned i=0; i<4; i++)
00433       for (unsigned j=0; j<4; j++)
00434         A.set(i+j, i,j);
00435     
00436     std::cerr << "A= "; A.stdprint();
00437     matrix B = A.map(cubic);
00438     std::cerr << "cubic=\n "; B.stdprint();
00439     B = A.map(square);
00440     std::cerr << "square=\n "; B.stdprint();
00441     B = A.map(identity);
00442     std::cerr << "identity=\n "; B.stdprint();
00443     
00444 
00445     matrix C(4,4);
00446     C.set(3,0,0);    C.set(2,0,1);    C.set(1,0,2);    C.set(5,0,3);
00447     C.set(4,1,0);    C.set(2,1,1);    C.set(1,1,2);    C.set(5,1,3);
00448     C.set(3,2,0);    C.set(4,2,1);    C.set(1,2,2);    C.set(4,2,3);
00449     C.set(1,3,0);    C.set(3,3,1);    C.set(1,3,2);    C.set(3,3,3);
00450 
00451     matrix vec(4);
00452     vec.set(1,0);    vec.set(4,1);    vec.set(2,2);    vec.set(9,3);
00453     std::cerr << "C="; C.stdprint(); 
00454     std::cerr << "x="; vec.stdprint(); 
00455     matrix covCx = covar2(C,vec);
00456     std::cerr << "cov(C,x)= "; covCx.stdprint();
00457 
00458 
00459     std::cerr << "Nothing to test in linalg.cpp\n";
00460   } catch(std::string const& err) {
00461     std::cerr << err << std::endl;
00462     return 1;
00463   }
00464   return 0;
00465 }
00466 
00467 
00468 #endif//TEST

Generated on Tue Feb 14 16:05:52 2006 for estfunc by doxygen 1.3.6