Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

doublematrix.cpp

Go to the documentation of this file.
00001 //****************************************************
00002 //  April, 1993, University of Illinois 
00003 // Copyright (C) 1993, 1994 Tianlin Wang
00004 /* Copyright (C) 1994-2003 Matvec Development Team. 
00005 
00006   This program is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU Library General Public
00008   License as published by the Free Software Foundation; either
00009   version 2 of the License, or (at your option) any later version.
00010   
00011   This program is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   Library General Public License for more details.
00015     
00016   You should have received a copy of the GNU Library General Public
00017   License along with this library; if not, write to the Free
00018   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00019   MA 02111-1307, USA 
00020 */
00021 
00022 #include <iostream>
00023 #include "session.h"
00024 #include "util.h"
00025 #include "doublematrix.h"
00026 
00027 namespace matvec {
00028 
00029 extern int nonsymm_eigen(const int job,double **A, const int n,double *rr,
00030                 double *ri, double **vr, double **vi,const int maxiter=50);
00031 extern int symm_eigen(double *vals, double **A, const int n);
00032 extern void svdcmp(double* a[], int m, int n, double w[], double* v[]);
00033 extern void ludcmp(double **a,int n,int *indx,int& d, double tol);
00034 extern void lubksb(double **a,int n,int *indx,double *b);
00035 extern void sweep(const int m, const int n, double **a, const int i0,
00036                          const int i1,const double tol);
00037 extern bool psdefinite(const double **mat,const unsigned m,const unsigned n,const double tol);
00038 
00039 doubleMatrix&  doubleMatrix::operator = (const Matrix<bool> &a)
00040 {
00041    resize(a.num_rows(),a.num_cols());
00042    for (int j,i=0; i<a.num_rows(); ++i) for (j=0; j<a.num_cols(); ++j) Matrix<double>::me[i][j] = (double)a[i][j];
00043    return *this;
00044 }
00045 
00046 
00047 bool doubleMatrix::psd(void) const
00048 {
00049    if (!this->symmetric()) return false;
00050    return psdefinite(begin(),Matrix<double>::nrow,Matrix<double>::ncol,SESSION.epsilon);
00051 }
00052 
00053 void doubleMatrix::svd(doubleMatrix& u, Vector<double>& s, doubleMatrix& v)
00054 {
00055    int nrow =  Matrix<double>::nrow;
00056    int ncol =  Matrix<double>::ncol;
00057    double** me =  Matrix<double>::me;
00058 
00059    if (nrow < ncol) throw exception("doubleMatrix::svd(), bad args");
00060 
00061    if (u.nrow != nrow || u.ncol != ncol) u.resize(nrow,ncol);
00062    if (s.size() != ncol ) s.resize(ncol);
00063    if (v.nrow != ncol || v.ncol != ncol) v.resize(ncol,ncol);
00064 
00065    for (int i=0; i<nrow; i++) memcpy(u[i],me[i],sizeof(double)*ncol);
00066    svdcmp(u.me, nrow, ncol, s.begin(), v.me);      // Singular value decomposition.
00067 }
00068 
00069 int doubleMatrix::rank(void)                      // rank(a) based on svdcmp.cc
00070 {
00071    int nrow =  Matrix<double>::nrow;
00072    int ncol =  Matrix<double>::ncol;
00073    double** me =  Matrix<double>::me;
00074 
00075    Vector<double> w(ncol);
00076    Matrix<double> v(ncol,ncol);
00077    int m = nrow;
00078    if (nrow < ncol) m = ncol;                   //u(m,col) where m>=col
00079    Matrix<double> u(m,ncol);
00080    int i;
00081    for (i=0; i<nrow; i++) memcpy(u[i],me[i],sizeof(double)*ncol);
00082    svdcmp(u.begin(), m, ncol, w.begin(), v.begin());                 // Singular value decomposition.
00083 
00084    int  r = 0;
00085    for (i=0; i<ncol; i++) if (w[i] > SESSION.epsilon) r++;
00086    return (r);
00087 }
00088 
00089 // Build a design Matrix for cubic splines
00090 // Based on Green and Silverman (1994);Nonparametric Regression and 
00091 //          Generalized Linear Models, Chapman & Hall, Chap. 2
00092 //
00093 doubleMatrix doubleMatrix::splines(const doubleMatrix knots,const unsigned type )
00094 const
00095 {
00096   int  nk=knots.nrow;
00097   int  n=nrow;
00098   double k;
00099   doubleMatrix R,Q,Delt,H,X;
00100   R.resize(nk,nk);
00101   Q.resize(nk,nk);
00102   H.resize(nk-1,1);
00103   k=(knots[nk-1][0]-knots[0][0])/((double)(nk-1));
00104   for(int i=0;i<nk-1;i++) H[i][0]=(knots[i+1][0]-knots[i][0]);
00105   for(int i=2;i<nk;i++){
00106     R(i,i)=(H(i,1)+H(i-1,1))/3;
00107     if (i<(nk-1)) {
00108       R(i+1,i)=H(i,1)/6;
00109       R(i,i+1)=H(i,1)/6;
00110     }
00111     Q(i-1,i)=1/H(i-1,1);
00112     Q(i,i)=-(1/H(i-1,1))-(1/H(i,1));
00113     Q(i+1,i)=1/H(i,1);
00114   }
00115   doubleMatrix Xg,Xgamma;
00116   Xg.resize(n,nk);
00117   Xgamma.resize(n,nk);
00118   for(int i=1;i<=n;i++){
00119     double t=me[i-1][0];
00120     int j;
00121     for( j=1;t>knots.me[j][0];j++);
00122     double th=knots.me[j][0];
00123     double tl=knots.me[j-1][0];
00124     Xg(i,j+1)=(t-tl)/H(j,1);
00125     Xg(i,j)=(th-t)/H(j,1);
00126     Xgamma(i,j+1)=-(t-tl)*(th-t)*(1+(t-tl)/H(j,1))/6;
00127     Xgamma(i,j)=-(t-tl)*(th-t)*(1+(th-t)/H(j,1))/6;
00128   }
00129   X=Xg+Xgamma*R.ginv1()*Q.transpose();
00130   if(type==1) {
00131     doubleMatrix Xs,Delt,G;
00132     G.resize(nk-2,nk-2);
00133     Xs.resize(nk,nk);
00134     Delt.resize(nk,nk-2);
00135     for(int i=0;i<nk-2;i++){
00136       Delt[i][i]=1./H[i][0];
00137       Delt[i+1][i]=-(1./H[i][0]+1./H[i+1][0]);
00138       Delt[i+2][i]=1./H[i+1][0];
00139       G[i][i]=(H[i][0]+H[i+1][0])/3.;
00140       if(i) {
00141         G[i-1][i]=H[i][0]/6.;
00142         G[i][i-1]=H[i][0]/6.;
00143       }
00144     }
00145     G.sqrtm();
00146     doubleMatrix Zs,dpd;
00147     dpd=Delt.transpose()*Delt;
00148     Zs=Delt*dpd.inv()*G;
00149     Zs/=pow(k,1.5);
00150     for(int i=0;i<nk;i++){
00151       Xs[i][0]=1.;
00152       Xs[i][1]=knots[i][0];
00153       for(int j=0;j<nk-2;j++){
00154         Xs[i][j+2]=Zs[i][j];
00155       }
00156 
00157     }
00158     X=X*Xs;
00159   }
00160   //cout << X;
00161 
00162   return(X);
00163 }
00164 
00165 
00166 doubleMatrix& doubleMatrix::inv(void)
00167 {
00168    //////////////////////////////////////////////////////////
00169    // A itself turns into its inverse
00170    // returns non_singular indicator
00171    // REQUIREMENTS:  A must be nonsingular
00172    /////////////////////////////////////////////////////////
00173    int nrow =  Matrix<double>::nrow;
00174    int ncol =  Matrix<double>::ncol;
00175    double** me =  Matrix<double>::me;
00176 
00177    int i,j,d;
00178    if ( nrow != ncol ) throw exception("doubleMatrix::inv(): matrix must be square");
00179    Vector<int>    indx;  indx.reserve(nrow);
00180    Vector<double> tempcol; tempcol.reserve(nrow);
00181    Matrix<double> temp; temp.reserve(nrow,nrow);
00182 
00183    ludcmp(me,nrow,indx.begin(),d, SESSION.epsilon);
00184    for (j=0; j<nrow; j++) {
00185       tempcol.assign(0.0);
00186       tempcol[j] = 1.0;
00187       lubksb(me,nrow,indx.begin(),tempcol.begin());
00188       for (i=0; i<nrow;i++) temp[i][j] = tempcol[i];
00189    }
00190    for (i=0;i<nrow; i++) memcpy(me[i],temp[i],sizeof(double)*nrow);
00191    return *this;
00192 }
00193 
00194 
00195 
00196 
00197 doubleMatrix doubleMatrix::mat_log(double tol) const
00198 {                              // Matrix Log
00199    if(tol==0) tol=SESSION.epsilon;
00200    doubleMatrix temp,P;
00201    if (!this->symmetric()) throw exception("doubleMatrix.mat_exp() must be symmetric\n");
00202    if (nrow==0) return temp;
00203    temp.resize(nrow,nrow);
00204    Vector<double> D;
00205 
00206    P=*this;
00207    D=P.eigen();
00208    double dmin=D.min();
00209    double dmax=D.max();
00210    if(dmin < dmax*2.*tol) {
00211      dmin=dmax*2.*tol;
00212    }
00213    for(int k=0;k<nrow;k++) {
00214      if(D[k]<dmin) D[k]=dmin;
00215      D[k]=std::log(D[k]);
00216      for(int i=0;i<nrow;i++){
00217        for(int j=0;j<nrow;j++){
00218          temp[i][j]+=P[i][k]*P[j][k]*D[k];
00219        }
00220      }
00221    }
00222    return temp;
00223 }
00224 
00225 
00226 
00227 doubleMatrix doubleMatrix::mat_exp(double tol) const
00228 {                              // Matrix Exponential
00229    if(tol==0) tol=SESSION.epsilon;
00230 
00231    doubleMatrix temp,P;
00232    if (!this->symmetric()) throw exception("doubleMatrix.mat_exp() must be symmetric\n");
00233    if (nrow==0) return temp;
00234    temp.resize(nrow,nrow);
00235    Vector<double> D;
00236 
00237    P=*this;
00238    D=P.eigen();
00239    double dmin=D.min();
00240    double dmax=D.max();
00241    if(dmin < dmax+2.*std::log(tol)) {
00242      dmin=dmax+2.*std::log(tol);
00243    }
00244    for(int k=0;k<nrow;k++) {
00245      if(D[k]<dmin) D[k]=dmin;
00246      D[k]=std::exp(D[k]);
00247      for(int i=0;i<nrow;i++){
00248        for(int j=0;j<nrow;j++){
00249          temp[i][j]+=P[i][k]*P[j][k]*D[k];
00250        }
00251      }
00252    }
00253    return temp;
00254 }
00255 
00256 
00257 
00258 
00259 void doubleMatrix::mat_exp_der(Vector<doubleMatrix> &temp,double tol) const
00260 {                              // Matrix exp partial derivatives
00261    if(tol==0) tol=SESSION.epsilon;
00262 
00263    doubleMatrix P;
00264    if (!this->symmetric()) throw exception("doubleMatrix.mat_exp() must be symmetric\n");
00265    if (nrow==0) return;
00266    int nvc=(nrow*(nrow+1))/2;
00267    temp.resize(nvc);
00268    for(int k=0;k<nvc;k++) temp[k].resize(nrow,nrow);
00269 
00270    Vector<double> D;
00271 
00272    P=*this;
00273    D=P.eigen();
00274    //      cout << "\nP der\n" << P;
00275    double dmin=D.min();
00276    double dmax=D.max();
00277    if(dmin < dmax*2.*tol) {
00278      dmin=dmax*2.*tol;
00279    }
00280    for(int i=0;i<nrow;i++) {
00281      if(D[i]<dmin) D[i]=dmin;
00282    }
00283    doubleMatrix Partkl;
00284    double g;
00285    for(int k=0;k<nrow;k++){
00286      double dk=D[k];
00287      for(int l=0;l<nrow;l++) {
00288        double dl=D[l];
00289        if(std::fabs(dk-dl)< tol) g=std::sqrt(dk*dl);
00290        else g=(dk-dl)/std::log(dk/dl);
00291        Partkl.resize(nrow,nrow);
00292 
00293        for(int i=0;i<nrow;i++)
00294          for(int j=0;j<nrow;j++)
00295            Partkl[i][j]=g*P[i][k]*P[j][l];
00296        
00297        
00298        int vc=0;
00299        for(int i=0;i<nrow;i++) {
00300          for(int j=i;j<nrow;j++,vc++) {
00301            temp[vc]+=P[i][k]*P[j][l]*Partkl;
00302            if(i!=j) temp[vc]+=P[j][k]*P[i][l]*Partkl;
00303            //       cout << i << ":" << j << " "<< vc << " " << temp[vc] << endl;
00304          }
00305        }
00306 
00307      }
00308    }
00309    //      for(int i=0;i<nvc;i++) cout << i << "->" << temp[i] << endl;
00310 
00311    return;
00312 }
00313 
00314 
00315 
00316 
00317 
00318 
00319 doubleMatrix doubleMatrix::ginv0(void) const
00320 {                              // Penrose-Moore inverse of any matrix
00321    int nrow =  Matrix<double>::nrow;
00322    int ncol =  Matrix<double>::ncol;
00323    double** me =  Matrix<double>::me;
00324 
00325    doubleMatrix temp(ncol,nrow);
00326    if (ncol==0 || nrow==0) return temp;
00327    Vector<double>  w; w.reserve(ncol);
00328    Matrix<double> v; v.reserve(ncol,ncol);
00329    int m = nrow;
00330    if (nrow < ncol) m=ncol;                   //u(m,col) where m>=col
00331    Matrix<double> u; u.reserve(m,ncol);
00332 
00333    int i,j,k;
00334    double x;
00335    for (i=0; i<nrow; i++) memcpy(u[i],me[i],sizeof(double)*ncol);
00336    for (i=0; i<m-nrow; i++) memset(u[nrow+i],'\0',sizeof(double)*ncol);
00337    svdcmp(u.begin(), m, ncol, w.begin(), v.begin());                  // Singular value decomposition.
00338    double wmax = w.max();             // Maximum singular value.
00339    double wmin = wmax*SESSION.epsilon;
00340    for (k = 0; k < ncol; k++) {
00341       if (w[k] < wmin) {
00342          w[k] = 0.0;
00343       }
00344       else {
00345          w[k] = 1.0/w[k];
00346       }
00347    }
00348    for (i = 0; i < ncol; i++) {
00349       for (k = 0; k < ncol; k++) v[i][k] *= w[k];
00350       for (j = 0; j < nrow; j++) {
00351          for (x=0.0,k=0; k<ncol; ++k) x += v[i][k]*u[j][k];
00352          temp[i][j] = x;
00353       }
00354    }
00355    return temp;
00356 }
00357 
00358 doubleMatrix& doubleMatrix::ginv1(unsigned *irank)
00359 {         // it only works for symmetric-positive-semidefinite matrix
00360           //  Matrix itself becomes its inverse;
00361    if (!this->symmetric()) {
00362      throw exception("doubleMatrix::ginv1(): matrix must be symmetric");
00363    }
00364    double lgdet;
00365    unsigned myrank = ginverse1(begin(),num_rows(),lgdet,1,SESSION.epsilon);
00366    if (irank) *irank = myrank;
00367    return *this;
00368 }
00369 
00370 double doubleMatrix::cond(void)
00371 {
00372    int nrow =  Matrix<double>::nrow;
00373    int ncol =  Matrix<double>::ncol;
00374    double** me =  Matrix<double>::me;
00375 
00376    if (nrow < ncol) throw exception("doubleMatrix::cond(), M.nrow() >= M.ncol()");
00377 
00378    Vector<double>  w(ncol);
00379    Matrix<double> v(ncol,ncol);
00380    Matrix<double> u(nrow,ncol);
00381 
00382    for (int i=0; i<nrow; i++) memcpy(u[i],me[i],sizeof(double)*ncol);
00383    svdcmp(u.begin(), nrow, ncol, w.begin(), v.begin());         // Singular value decomposition.
00384 
00385    double smax = w.max();
00386    double smin = w.min();
00387    if (smin == 0.0) warning("Matrix::cond(): condition is infinite");
00388    return (smax/smin);
00389 }
00390 
00391 doubleMatrix doubleMatrix::lu_solve(const doubleMatrix& rhs)
00392 {
00393    int nrow =  Matrix<double>::nrow;
00394    int ncol =  Matrix<double>::ncol;
00395    double** me =  Matrix<double>::me;
00396 
00397    if (nrow  != ncol) throw exception("doubleMatrix::lu_solve(): matrix is not square ");
00398    int m = rhs.num_rows();
00399    int n = rhs.num_cols();
00400 
00401    if (ncol != m ) throw exception("doubleMatrix::lu_solve(): bad arg");
00402    doubleMatrix solmat(m,n);
00403    int i,j,d;
00404    Vector<double> solvec; solvec.reserve(m);
00405    Vector<int> indx;  indx.reserve(m);
00406    ludcmp(me,nrow,indx.begin(),d,SESSION.epsilon);
00407    warning("A.solve(b), A destroyed");
00408    for (j=0; j<n; j++) {
00409       for (i=0; i<m; i++) solvec[i] = rhs[i][j];
00410       lubksb(me,m,indx.begin(),solvec.begin());
00411       for (i=0; i<m; i++) solmat[i][j] = solvec[i];
00412    }
00413    return solmat;
00414 }
00415 
00416 Vector<double> doubleMatrix::lu_solve(const Vector<double>& rhs)
00417 {
00418    int n = rhs.size();
00419    doubleMatrix bmat(n,1);
00420    for (int i=0; i<n; i++) bmat[i][0] = rhs[i];
00421    bmat = lu_solve(bmat);
00422    return bmat.vec();
00423 }
00424 
00425 
00426 void doubleMatrix::gs_solve(const doubleMatrix& rhs,doubleMatrix& solmat,const double relax,
00427                      const double stopval,const int mxiter)
00428 {
00429   //   relax    relaxation coefficient, relax=1.2 seems good for some case
00430   //   stopval  the accuracy at which iteration stops.
00431   //   mxiter   maximum number of iterations allowed
00432 
00433    int nrow =  Matrix<double>::nrow;
00434    int ncol =  Matrix<double>::ncol;
00435    double** me =  Matrix<double>::me;
00436 
00437    int m = rhs.num_rows();
00438    int n = rhs.num_cols();
00439    if (nrow != ncol) throw exception("doubleMatrix::gs_solve(): matrix must be square ");
00440    if (ncol != m ) throw exception("doubleMatrix::gs_solve(): matrix and rhs are not conformable");
00441    if (solmat.num_rows() != m || solmat.num_cols() != n) {
00442       solmat.resize(m,n);
00443    }
00444    int i,j,k;
00445    double diag;
00446    int niter = 0;
00447    double a,cmax;
00448    double tol = SESSION.epsilon;
00449 
00450    Vector<double> oldsol(n);
00451    Vector<double> newsol(n);
00452    Vector<double> cval(n);
00453    Vector<double> local(n);
00454    do {                             // now iteration begins
00455       cmax = 0.0;
00456       for (i=0; i<m; i++) {
00457          for (k=0; k<n; k++) {
00458             oldsol[k] = solmat[i][k];
00459             local[k] = 0.0;
00460          }
00461          for (j=0; j<m; j++) {
00462             a = me[i][j];
00463             if (j != i) for (k=0; k<n; k++) local[k] += a * solmat[j][k];
00464          }
00465          diag = me[i][i];
00466          if (diag > tol) {
00467             for (k=0; k<n; k++) {
00468                newsol[k] = (rhs[i][k] - local[k])/diag;
00469                cval[k] = (newsol[k] - oldsol[k])*relax;
00470                if (fabs(cval[k]) > cmax) cmax = fabs(cval[k]);
00471                newsol[k] = solmat[i][k] = oldsol[k] + cval[k];
00472             }
00473          }
00474          else if (diag > -tol) {
00475             throw exception("doubleMatrix::gs_solve(): zero-diagonal found in Matrix::gs_solve()");
00476          }
00477          else {
00478             throw exception("doubleMatrix::gs_solve(): matrix is not psd");
00479          }
00480       }
00481       niter += 1;
00482       if ( (niter % 10) ==0) {
00483          std::cout << " GS: # of iter = " << niter << ", max_change = "
00484               << cmax << std::endl;
00485       }
00486    } while (niter <= mxiter && cmax > stopval);
00487    if (cmax > stopval) {
00488       warning("doubleMatrix::gs_solve(): not converge: %20.10f",cmax);
00489    }
00490 }
00491 
00492 void doubleMatrix::gs_solve(const Vector<double>& rhs, Vector<double>& sol, const double relax,
00493                      const double stopval, const int mxiter)
00494 {
00495    int n = rhs.size();
00496    doubleMatrix bmat(n,1),solmat(n,1);
00497    if (sol.size() != n) {
00498       sol.resize(n);
00499    }
00500    int i;
00501    for (i=0; i<n; i++) {
00502       bmat[i][0] = rhs[i];
00503       solmat[i][0] = sol[i];
00504    }
00505    gs_solve(bmat,solmat,relax,stopval,mxiter);
00506    for (i=0; i<n; i++) sol[i] = solmat[i][0];
00507 }
00508 
00509 Vector<double> doubleMatrix::eigen(const int job)
00510 {
00511    ///////////////////////////////////////////////////////////////////
00512    // job = 0, no eigenvectors are needed
00513    //       1, eigenvectors are also needed.
00514    // return eigenvalues
00515    // Note that  matrix itself become eigenvectors.
00516    //   all imaginary numbers in eigenvalus/eigenvectors are ignored
00517    //   if there are some for non-symmetrix real matrix.
00518    ////////////////////////////////////////////////////////////////////
00519 
00520   //   int nrow =  Matrix<double>::nrow;
00521   //   int ncol =  Matrix<double>::ncol;
00522   //   double** me =  Matrix<double>::me;
00523 
00524    if (nrow != ncol) throw exception( "doubleMatrix::eigen(): matrix must be square" );
00525    Vector<double> vals(nrow);
00526    if (this->symmetric()) {
00527       symm_eigen(vals.begin(),me,nrow);
00528    }
00529    else {
00530      std::cout << *this;
00531       Vector<double> ri(nrow); 
00532       Matrix<double> vr;
00533       Matrix<double> vi;
00534       if (job == 1) {
00535           vr.reserve(nrow,nrow);
00536           vi.reserve(nrow,nrow);
00537       }
00538       int i = nonsymm_eigen(job,me,nrow,vals.begin(),ri.begin(),vr.begin(),vi.begin());
00539       if (i == -2) {
00540          warning(" Matrix::eigen(): out of memory");
00541       }
00542       else if (i == -1) {
00543          warning(" Matrix::eigen(): not converged");
00544       }
00545       else if (i == 1) {
00546          warning(" Matrix::eigen(): eigenvalues/vectors are complex,\n "
00547                  " and the imaginary numbers are all ignored");
00548       }
00549       if (job == 1) {
00550          for (i=0; i<nrow; i++) memcpy(me[i],vr[i],sizeof(double)*ncol);
00551       }
00552    }
00553    return vals;
00554 }
00555 
00556 double doubleMatrix::det(void) const
00557 {
00558    int nrow =  Matrix<double>::nrow;
00559    int ncol =  Matrix<double>::ncol;
00560 
00561    double detval = 0.0;
00562    if ( nrow != ncol ) throw exception("doubleMatrix::det(): matrix must be square");
00563    int i,d;
00564    Vector<int> indx(nrow);
00565    doubleMatrix temp(*this);
00566    ludcmp(temp.begin(),nrow,indx.begin(),d, SESSION.epsilon);
00567    detval = (double)d;
00568    for (i=0; i<nrow; i++) detval *= temp[i][i];
00569    return detval;
00570 }
00571 
00572 double doubleMatrix::norm(const int p) const
00573 {
00574    int nrow =  Matrix<double>::nrow;
00575    int ncol =  Matrix<double>::ncol;
00576    double** me =  Matrix<double>::me;
00577 
00578    double retval = 0.0;
00579    int i;
00580    if (p == 1) {
00581       doubleMatrix A(*this);
00582       retval = abs(A).sum().max();
00583    }
00584    else if (p == 2) {
00585       Vector<double> w;  w.reserve(ncol);
00586       Matrix<double> v; v.reserve(ncol,ncol);
00587       int m = nrow;
00588       if (nrow < ncol) m = ncol;            //u(m,ccol) where m>=ccol
00589       Matrix<double> u(m,ncol);
00590 
00591       for (i=0; i<nrow; i++) memcpy(u[i],me[i],sizeof(double)*ncol);
00592       svdcmp(u.begin(), m, ncol, w.begin(), v.begin());                 // Singular value decomposition.
00593       retval = w.max();
00594    }
00595    else {
00596       throw exception("doubleMatrix::norm(): bad arg, 1 or 2 expected");
00597    }
00598    return retval;
00599 }
00600 
00601 double doubleMatrix::norm(const std::string &s) const
00602 {
00603    double retval = 0.0;
00604    doubleMatrix A = this->transpose();
00605    if (s == "inf") {
00606       retval = abs(A).sum().max();
00607    }
00608    else if (s == "fro") {
00609       retval = std::sqrt((A*(*this)).diag(0).sum());
00610    }
00611    else {
00612       throw exception("doubleMatrix::norm((): bad arg, it must be either \"inf\" or \"fro\" ");
00613    }
00614    return retval;
00615 }
00616 
00617 double doubleMatrix::logdet(void)
00618 {
00619    int nrow =  Matrix<double>::nrow;
00620    int ncol =  Matrix<double>::ncol;
00621    double** me =  Matrix<double>::me;
00622 
00623    double retval = 0.0;
00624    if (!this->symmetric()) throw exception("doubleMatrix::logdet(): matrix must be symmetric");
00625    Matrix<double> temp(*this);
00626 
00627    ginverse1(temp.begin(),nrow,retval,3,SESSION.epsilon);
00628    return retval;
00629 }
00630 
00631 double doubleMatrix::quadratic(const Vector<double> &x, const Vector<double> &y) const
00632 {
00633    int nrow =  Matrix<double>::nrow;
00634    int ncol =  Matrix<double>::ncol;
00635    double** me =  Matrix<double>::me;
00636    int m = x.size();
00637    int n = y.size();
00638 
00639    double s = 0.0;
00640    if (m != nrow  || n != ncol)  throw exception("doubleMatrix::quadratic(): size not conformable");
00641    for (int j,i=0;i<m; i++) for (j=0; j<n; j++) s += x[i]*me[i][j]*y[j];
00642    return s;
00643 }
00644 Vector<double> doubleMatrix::variance(orientation orien) const
00645 {
00646    int nrow =  Matrix<double>::nrow;
00647    int ncol =  Matrix<double>::ncol;
00648    double** me =  Matrix<double>::me;
00649    int i,j;
00650    double ss,s;
00651    Vector<double> temp;
00652    if (orien == COLUMN) {
00653       assert(nrow > 1);
00654       temp.resize(ncol);
00655       for (j=0; j<ncol; j++) {
00656          for (ss=0.0,s=0.0,i=0; i<nrow; ++i) {
00657              ss += me[i][j]*me[i][j];
00658              s  += me[i][j];
00659          }
00660          temp[j] = (ss-s*s/nrow)/(nrow - 1);
00661       }
00662    } else if (orien == ROW) {
00663       assert(ncol > 1);
00664       temp.resize(nrow);
00665       for (i=0; i<nrow; i++) {
00666          for (ss=0.0,s=0.0,j=0; j<ncol; ++j) {
00667              ss += me[i][j]*me[i][j];
00668              s  += me[i][j];
00669          }
00670          temp[i] = (ss-s*s/ncol)/(ncol - 1);
00671       }
00672    } else {
00673       warning("unknown orientation");
00674    }
00675    return temp;
00676 }
00677 
00678 doubleMatrix doubleMatrix::covariance(const doubleMatrix &B) const
00679 {
00680    int nrow =  Matrix<double>::nrow;
00681    int ncol =  Matrix<double>::ncol;
00682    double** me =  Matrix<double>::me;
00683 
00684    assert (nrow == B.num_rows() && ncol == B.num_cols());
00685    doubleMatrix temp(ncol,ncol);
00686    int i,j,k;
00687    double ss,sx,sy;
00688    for (i=0; i<ncol; ++i) {
00689       for (j=0; j<=i; ++j) {
00690          for (ss=0.0,sx=0.0,sy=0.0,k=0; k<nrow; ++k) {
00691             ss += me[k][i]*B[k][j];
00692             sx += me[k][i];
00693             sy += B[k][j];
00694          }
00695          temp[i][j] = temp[j][i] = (ss - sx*sy/ncol)/(ncol - 1);
00696       }
00697    }
00698    return temp;
00699 }
00700 
00701 doubleMatrix& doubleMatrix::sqrtm(void)
00702 {
00703    if (!this->symmetric()) throw exception("doubleMatrix::sqrtm(): matrix must be symmetric");
00704    double lgdet;
00705    ginverse1(begin(),num_rows(),lgdet,2,SESSION.epsilon);
00706    return *this;
00707 }
00708 
00709 doubleMatrix& doubleMatrix::identity(const int m,const int n)
00710 {
00711    resize(m,n);
00712    double **me = begin();
00713    for (int i=0; i<m; ++i) if (i < n) me[i][i] = 1.0;
00714    return *this;
00715 }
00716 
00717 doubleMatrix& doubleMatrix::sweep(const int i0,const int i1)
00718 {
00719    int nrow =  Matrix<double>::nrow;
00720    int ncol =  Matrix<double>::ncol;
00721 
00722    int n = std::min(nrow,ncol);
00723    if (i0<0 || i0 >=n || i0 > i1) throw exception("doubleMatrix::sweep(): range error");
00724    matvec::sweep(nrow,ncol,begin(),i0,i1,SESSION.epsilon);
00725    return *this;
00726 }
00727 }  //////////// end of namespace
00728 

Generated on Thu Jun 16 17:13:39 2005 for Matvec by doxygen1.2.16