00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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);
00067 }
00068
00069 int doubleMatrix::rank(void)
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;
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());
00083
00084 int r = 0;
00085 for (i=0; i<ncol; i++) if (w[i] > SESSION.epsilon) r++;
00086 return (r);
00087 }
00088
00089
00090
00091
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
00161
00162 return(X);
00163 }
00164
00165
00166 doubleMatrix& doubleMatrix::inv(void)
00167 {
00168
00169
00170
00171
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 {
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 {
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 {
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
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
00304 }
00305 }
00306
00307 }
00308 }
00309
00310
00311 return;
00312 }
00313
00314
00315
00316
00317
00318
00319 doubleMatrix doubleMatrix::ginv0(void) const
00320 {
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;
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());
00338 double wmax = w.max();
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 {
00360
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());
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
00430
00431
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 {
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
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
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;
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());
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 }
00728