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

ginverse1.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 <cmath>
00024 #include <algorithm>
00025 #include "exception.h"
00026 #include "bg.h"
00027 
00028 /******************************************************************
00029 *      ginv for positive semi-definite(psd) symmetric matrix
00030 *                                a(0..n-1,0..n-1)
00031 *      mode = 1 inverse, a returns as ginv1(a)
00032 *             2 cholesky only, return a=(L\0)
00033 *             3 log determinent only, a  is destroyed
00034 *     NOTE: user is totally resposible to check if a is symmetric
00035 *******************************************************************/
00036 
00037 namespace matvec {
00038 unsigned ginverse1(double **a,const unsigned n,double& lgdet,int mode,
00039                   const double tol)
00040 {
00041    unsigned i,j,k,irank = n;
00042    double sum;
00043    ///////////////////////////////////////////////////
00044    // column-by-column, we are doing
00045    // L (lower triangular) in place such that L*L'=A
00046    ///////////////////////////////////////////////////
00047    lgdet = 0.0;
00048    for (j=0; j<n; ++j) {  // for column j, L[j][j] is calculated first
00049       sum = a[j][j];
00050       for (k=0; k<j; ++k) sum -= a[j][k]*a[j][k];
00051                         //  for other elements L[i,j] in jth column, i=j+1 to n
00052       if (sum <= -tol) {
00053         throw exception("ginverse1(): matrix is non-psd");
00054       }
00055       if (std::fabs(sum) < tol) {
00056          irank--;
00057          for (i=j; i<n; i++) a[i][j]=0.0;
00058       }
00059       else {
00060          lgdet += std::log(sum);
00061          a[j][j]=std::sqrt(sum);
00062          for (i=j+1; i<n; i++) {
00063             sum = a[i][j];
00064             for (k=0; k<j; ++k) sum -= a[i][k]*a[j][k];
00065             a[i][j]=sum/a[j][j];
00066          }
00067       }
00068    }
00069    if (mode != 1) {
00070       if (mode ==2) {
00071          for(i=0;i<n-1;i++) memset(&(a[i][i+1]),'\0',sizeof(double)*(n-i-1));
00072        }
00073        return irank;
00074    }
00075    //////////////////////////////////////////
00076    //  column-by-column,  we are doing 
00077    //   inv(L) in place (lower triangl)
00078    //////////////////////////////////////////
00079    for (j=0; j<n; j++) { 
00080       if (std::fabs(a[j][j]) < tol) {
00081          for (i=j; i<n; i++) a[i][j]=0.0;            
00082       }
00083       else {
00084          a[j][j] = 1./a[j][j];
00085          for (i=j+1; i<n; i++) {
00086             if (a[i][i] <= -tol)  throw exception("ginverse1(): matrix is non-psd");
00087             if (std::fabs(a[i][i]) < tol) {
00088                a[i][j]=0.0;
00089             }
00090             else {
00091                sum=0.0;
00092                for (k=j; k<i; k++) sum -= a[i][k]*a[k][j];                      
00093                a[i][j] = sum/a[i][i];
00094             }      // end of if-else block
00095          }         // end of for-loop
00096       }            // end of if-else block
00097    }               // end of for-loop
00098 
00099    //////////////////////////////////////
00100    //  column-by-column, we are doing 
00101    //  inv(L')*inv(L)= inv(a) in place
00102    //////////////////////////////////////
00103    for (j=0; j<n; j++) {
00104       for (i=j; i<n; i++) {
00105          for (sum=0.0,k=i; k<n; k++) sum += a[k][i]*a[k][j];    
00106          a[i][j]=sum;    a[j][i]=sum;
00107       }
00108    }
00109    return irank;
00110 }
00111 
00112 unsigned ginverse1(BG **a,const unsigned n,BG& lgdet,int mode,
00113                   const double tol)
00114 {
00115    unsigned i,j,k,irank = n;
00116    BG sum;
00117    ///////////////////////////////////////////////////
00118    // column-by-column, we are doing
00119    // L (lower triangular) in place such that L*L'=A
00120    ///////////////////////////////////////////////////
00121    lgdet = 0.0;
00122    for (j=0; j<n; ++j) {  // for column j, L[j][j] is calculated first
00123       sum = a[j][j];
00124       for (k=0; k<j; ++k) sum -= a[j][k]*a[j][k];
00125                         //  for other elements L[i,j] in jth column, i=j+1 to n
00126       if (sum <= -tol) {
00127         throw exception("ginverse1(): matrix is non-psd");
00128       }
00129       if (fabs(sum) < tol) {
00130          irank--;
00131          for (i=j; i<n; i++) a[i][j]=0.0;
00132       }
00133       else {
00134          lgdet += log(sum);
00135          a[j][j]=sqrt(sum);
00136          for (i=j+1; i<n; i++) {
00137             sum = a[i][j];
00138             for (k=0; k<j; ++k) sum -= a[i][k]*a[j][k];
00139             a[i][j]=sum/a[j][j];
00140          }
00141       }
00142    }
00143    if (mode != 1) {
00144       if (mode ==2) {
00145         for(i=0;i<n-1;i++) { 
00146           //memset(&(a[i][i+1]),'\0',sizeof(BG)*(n-i-1));
00147           for(j=i+1;j<n;j++){
00148             a[i][j] = 0.0;
00149           }
00150         }
00151        }
00152        return irank;
00153    }
00154    //////////////////////////////////////////
00155    //  column-by-column,  we are doing 
00156    //   inv(L) in place (lower triangl)
00157    //////////////////////////////////////////
00158    for (j=0; j<n; j++) { 
00159       if (fabs(a[j][j]) < tol) {
00160          for (i=j; i<n; i++) a[i][j]=0.0;            
00161       }
00162       else {
00163          a[j][j] = 1./a[j][j];
00164          for (i=j+1; i<n; i++) {
00165             if (a[i][i] <= -tol)  throw exception("ginverse1(): matrix is non-psd");
00166             if (fabs(a[i][i]) < tol) {
00167                a[i][j]=0.0;
00168             }
00169             else {
00170                sum=0.0;
00171                for (k=j; k<i; k++) sum -= a[i][k]*a[k][j];                      
00172                a[i][j] = sum/a[i][i];
00173             }      // end of if-else block
00174          }         // end of for-loop
00175       }            // end of if-else block
00176    }               // end of for-loop
00177 
00178    //////////////////////////////////////
00179    //  column-by-column, we are doing 
00180    //  inv(L')*inv(L)= inv(a) in place
00181    //////////////////////////////////////
00182    for (j=0; j<n; j++) {
00183       for (i=j; i<n; i++) {
00184          for (sum=0.0,k=i; k<n; k++) sum += a[k][i]*a[k][j];    
00185          a[i][j]=sum;    a[j][i]=sum;
00186       }
00187    }
00188    return irank;
00189 }
00190 
00191 
00192 bool psdefinite(const double **mat,const unsigned m,const unsigned n,const double tol)
00193 {
00194    /////// first check to see if it is symmetric or not
00195    if (m != n) return false;
00196    int i,j,t;
00197    bool k = true;
00198    for (i=1; i<m; i++) {
00199       for (j=0; j<i; j++) if (std::fabs(mat[i][j] - mat[j][i]) > tol) return false;
00200    }
00201 
00202    double **a = new double *[m];
00203    for (i=0; i<m; ++i) a[i] = new double [n];
00204 
00205    for (i=0; i<m; i++) memcpy(a[i],mat[i],sizeof(double)*n);
00206    double sum;
00207    for (j=0; j<n; j++) {
00208       sum = a[j][j];
00209       for (t=0; t<j; ++t) sum -= a[j][t]*a[j][t];
00210       if (sum <= -tol) {
00211          k = false;
00212          break;
00213       }
00214       else if (std::fabs(sum) < tol) {
00215          for (i=j; i<n; i++) a[i][j]=0.0;
00216       }
00217       else {
00218          a[j][j]=std::sqrt(sum);
00219          for (i=j+1; i<n; i++) {
00220             sum = a[i][j];
00221             for (t=0; t<j; ++t) sum -= a[i][t]*a[j][t];
00222             a[i][j]=sum/a[j][j];
00223          }
00224       }
00225    }
00226    for (i=0; i<m; ++i) {
00227      if(a[i]){
00228        delete [] a[i];
00229        a[i]=0;
00230      }
00231    }
00232    if(a){
00233      delete [] a;
00234      a=0;
00235    }
00236    return k;
00237 }
00238 
00239 bool psdefinite(const BG **mat,const unsigned m,const unsigned n,const double tol)
00240 {
00241    /////// first check to see if it is symmetric or not
00242    if (m != n) return false;
00243    int i,j,t;
00244    bool k = true;
00245    for (i=1; i<m; i++) {
00246       for (j=0; j<i; j++) if (fabs(mat[i][j] - mat[j][i]) > tol) return false;
00247    }
00248 
00249    BG **a = new BG *[m];
00250    for (i=0; i<m; ++i) a[i] = new BG [n];
00251 
00252    //for (i=0; i<m; i++) memcpy(a[i],mat[i],sizeof(BG)*n);
00253    for (i=0; i<m; i++) {
00254      for (j=0; j<m; j++){
00255        a[i][j] = mat[i][j];
00256      }
00257    }
00258    BG sum;
00259    for (j=0; j<n; j++) {
00260       sum = a[j][j];
00261       for (t=0; t<j; ++t) sum -= a[j][t]*a[j][t];
00262       if (sum <= -tol) {
00263          k = false;
00264          break;
00265       }
00266       else if (fabs(sum) < tol) {
00267          for (i=j; i<n; i++) a[i][j]=0.0;
00268       }
00269       else {
00270          a[j][j]=sqrt(sum);
00271          for (i=j+1; i<n; i++) {
00272             sum = a[i][j];
00273             for (t=0; t<j; ++t) sum -= a[i][t]*a[j][t];
00274             a[i][j]=sum/a[j][j];
00275          }
00276       }
00277    }
00278    for (i=0; i<m; ++i) {
00279      if(a[i]){
00280        delete [] a[i];
00281        a[i]=0;
00282      }
00283    }
00284    if(a){
00285      delete [] a;
00286      a=0;
00287    }
00288    return k;
00289 }
00290 
00291 void ludcmp(double **a,int n,int *indx,int& d,double tol)
00292 {
00293    int i,j,k,imax;
00294    double big,dum,sum,temp;
00295    double *vv = new double [n];
00296    d=1;
00297    for (i=0;i<n;i++) {
00298       big = 0.0;
00299       for (j=0;j<n;j++) if ((temp=std::fabs(a[i][j])) > big) big=temp;
00300       if (std::fabs(big) < tol) throw exception("ludcmp(): Singular matrix");
00301       vv[i] = 1.0/big;
00302    }
00303    for (j=0;j<n;j++) {
00304       for (i=0;i<j;i++) {
00305          sum = a[i][j];
00306          for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
00307          a[i][j]=sum;
00308       }
00309       big=0.0;
00310       imax = j;
00311       for (i=j;i<n;i++) {
00312          sum = a[i][j];
00313          for (k=0;k<j;k++) sum -= a[i][k]*a[k][j];
00314          a[i][j] = sum;
00315          if ( (dum = vv[i]*std::fabs(sum)) >= big) {
00316             big = dum;
00317             imax = i;
00318          }
00319       }
00320       if (j != imax) {
00321          for (k = 0; k<n; k++) {
00322             dum = a[imax][k];
00323             a[imax][k] = a[j][k];
00324             a[j][k] = dum;
00325          }
00326          d = -d;
00327          vv[imax] = vv[j];
00328       }
00329       indx[j] = imax;
00330       if (std::fabs(a[j][j]) < tol) throw exception("ludcmp(): Singular matrix");
00331       dum = 1.0/(a[j][j]);
00332       for (i=j+1;i<n;i++) a[i][j] *= dum;
00333    }
00334    if(vv){
00335      delete []  vv;
00336      vv=0;
00337    }
00338 }
00339 
00340 void ludcmp(BG **a,int n,int *indx,int& d, double tol)
00341 {
00342    int i,j,k,imax;
00343    BG big,dum,sum,temp;
00344    BG *vv = new BG [n];
00345    d=1;
00346    for (i=0;i<n;i++) {
00347       big = 0.0;
00348       for (j=0;j<n;j++) if ((temp=fabs(a[i][j])) > big) big=temp;
00349       if (fabs(big) < tol) throw exception("ludcmp(): Singular matrix");
00350       vv[i] = 1.0/big;
00351    }
00352    for (j=0;j<n;j++) {
00353       for (i=0;i<j;i++) {
00354          sum = a[i][j];
00355          for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
00356          a[i][j]=sum;
00357       }
00358       big=0.0;
00359       imax = j;
00360       for (i=j;i<n;i++) {
00361          sum = a[i][j];
00362          for (k=0;k<j;k++) sum -= a[i][k]*a[k][j];
00363          a[i][j] = sum;
00364          if ( (dum = vv[i]*fabs(sum)) >= big) {
00365             big = dum;
00366             imax = i;
00367          }
00368       }
00369       if (j != imax) {
00370          for (k = 0; k<n; k++) {
00371             dum = a[imax][k];
00372             a[imax][k] = a[j][k];
00373             a[j][k] = dum;
00374          }
00375          d = -d;
00376          vv[imax] = vv[j];
00377       }
00378       indx[j] = imax;
00379       if (fabs(a[j][j]) < tol) throw exception("ludcmp(): Singular matrix");
00380       dum = 1.0/(a[j][j]);
00381       for (i=j+1;i<n;i++) a[i][j] *= dum;
00382    }
00383    if(vv){
00384      delete []  vv;
00385      vv=0;
00386    }
00387 }
00388 
00389 void lubksb(double **a,int n,int *indx,double *b)
00390 {
00391    int i,j;
00392    int ip, ii = -1;
00393    double sum;
00394 
00395    for (i=0;i<n;i++) {
00396       ip = indx[i];
00397       sum = b[ip];
00398       b[ip] = b[i];
00399       if (ii>=0) {
00400          for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
00401       }
00402       else if (sum) {
00403          ii=i;
00404       }
00405       b[i] = sum;
00406    }
00407    for (i=n-1; i>=0; i--) {
00408       sum = b[i];
00409       for (j=i+1;j<n;j++) sum -= a[i][j]*b[j];
00410       b[i] = sum/a[i][i];
00411    }
00412 }
00413 
00414 void lubksb(BG **a,int n,int *indx,BG *b)
00415 {
00416    int i,j;
00417    int ip, ii = -1;
00418    BG sum;
00419 
00420    for (i=0;i<n;i++) {
00421       ip = indx[i];
00422       sum = b[ip];
00423       b[ip] = b[i];
00424       if (ii>=0) {
00425          for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
00426       }
00427       else if (sum!=0.0) {
00428          ii=i;
00429       }
00430       b[i] = sum;
00431    }
00432    for (i=n-1; i>=0; i--) {
00433       sum = b[i];
00434       for (j=i+1;j<n;j++) sum -= a[i][j]*b[j];
00435       b[i] = sum/a[i][i];
00436    }
00437 }
00438 
00439 
00440 // PYTHAG computes std::sqrt(a^{2} + b^{2}) without destructive overflow or underflow.
00441 
00442 static double at, bt, ct;
00443 #define PYTHAG(a, b) ((at = std::fabs(a)) > (bt = std::fabs(b)) ? \
00444 (ct = bt/at, at*std::sqrt(1.0+ct*ct)): (bt ? (ct = at/bt, bt*std::sqrt(1.0+ct*ct)): 0.0))
00445 
00446 static double maxarg1, maxarg2;
00447 #define MAX(a, b) (maxarg1 = (a), maxarg2 = (b), (maxarg1) > (maxarg2) ? \
00448 (maxarg1) : (maxarg2))
00449 
00450 #define SIGN(a, b) ((b) < 0.0 ? -std::fabs(a): std::fabs(a))
00451 
00452 void svdcmp(double* a[], int m, int n, double w[], double* v[])
00453 {
00454    /////////////////////////////////////////////////////////////////////
00455    // Given a matrix a[m][n], this routine computes its singular value
00456    // decomposition, A = U*W*V'.  The matrix U replaces a on output.
00457    // The diagonal matrix of singular values W is output as a vector w[n].
00458    // The matrix V  is output as v[n][n].
00459    // m must be greater or equal to n;  if it is smaller, then a should be
00460    // filled up to square with zero rows.
00461    /////////////////////////////////////////////////////////////////////////
00462 
00463    int flag, i, its, j, jj, k, l, nm;
00464    double c, f, h, s, x, y, z;
00465    double anorm = 0.0, g = 0.0, scale = 0.0;
00466 
00467    if (m < n) throw exception("svdcmp(): Matrix A  was not augmented with extra rows of zeros");
00468 
00469    double* rv1 = new double [n];
00470 
00471     // Householder reduction to bidiagonal form.
00472    l = 0;    // added by T. Wang to avoid warning in g++
00473    nm = 0;   // added by T. Wang to avoid warning in g++
00474    for (i = 0; i < n; i++) {
00475       l = i + 1;
00476       rv1[i] = scale*g;
00477       g = s = scale = 0.0;
00478       if (i < m) {
00479          for (k = i; k < m; k++) scale += std::fabs(a[k][i]);
00480             if (scale) {
00481                for (k = i; k < m; k++) {
00482                   a[k][i] /= scale;
00483                   s += a[k][i]*a[k][i];
00484                }
00485                f = a[i][i];
00486                g = -SIGN(std::sqrt(s), f);
00487                h = f*g - s;
00488                a[i][i] = f - g;
00489                if (i != n - 1) {
00490                   for (j = l; j < n; j++) {
00491                      for (s  = 0.0, k = i; k < m; k++) s += a[k][i]*a[k][j];
00492                      f = s/h;
00493                      for ( k = i; k < m; k++) a[k][j] += f*a[k][i];
00494                   }
00495                }
00496                for (k = i; k < m; k++) a[k][i] *= scale;
00497             }
00498          }
00499          w[i] = scale*g;
00500          g = s= scale = 0.0;
00501          if (i < m && i != n - 1) {
00502             for (k = l; k < n; k++)  scale += std::fabs(a[i][k]);
00503             if (scale) {
00504                for (k = l; k < n; k++) {
00505                   a[i][k] /= scale;
00506                   s += a[i][k]*a[i][k];
00507                }
00508                f = a[i][l];
00509                g = -SIGN(std::sqrt(s), f);
00510                h = f*g - s;
00511                a[i][l] = f - g;
00512                //              if(l==0){
00513                //                cout << "l eq 0" << endl;
00514                //              }
00515                for (k = l; k < n; k++)  rv1[k] = a[i][k]/h;
00516                if (i != m - 1) {
00517                   for (j = l; j < m; j++) {
00518                      for (s = 0.0, k = l; k < n; k++) s += a[j][k]*a[i][k];
00519                      for (k = l; k < n; k++) a[j][k] += s*rv1[k];
00520                   }
00521                }
00522                for (k = l; k < n; k++) a[i][k] *= scale;
00523             }
00524          }
00525          anorm = MAX(anorm, (std::fabs(w[i]) + std::fabs(rv1[i])));
00526       }
00527         /* Accumulation of right-hand transformations.  */
00528       for (i = n - 1; 0 <= i; i--) {
00529          if (i < n - 1) {
00530             if (g) {
00531                for (j = l; j < n; j++)  v[j][i] = (a[i][j]/a[i][l])/g;
00532                   /* Double division to avoid possible underflow: */
00533                for (j = l; j < n; j++) {
00534                   for (s = 0.0, k = l; k < n; k++) s += a[i][k]*v[k][j];
00535                   for (k = l; k < n; k++)  v[k][j] += s*v[k][i];
00536                }
00537             }
00538             for (j = l; j < n; j++) v[i][j] = v[j][i] = 0.0;
00539          }
00540          v[i][i] = 1.0;
00541          g = rv1[i];
00542          l = i;
00543       }
00544           /* Accumulation of left-hand transformations.   */
00545       for (i = n - 1; 0 <= i; i--) {
00546          l = i + 1;
00547          g = w[i];
00548          if (i < n - 1) for (j = l; j < n; j++) a[i][j] = 0.0;
00549          if (g) {
00550             g = 1.0/g;
00551             if (i != n - 1) {
00552                for (j = l; j < n; j++) {
00553                   for (s = 0.0, k = l; k < m; k++) s += a[k][i]*a[k][j];
00554                   f = (s/a[i][i])*g;
00555                   for (k = i; k < m; k++) a[k][j] += f*a[k][i];
00556                }
00557             }
00558             for (j = i; j < m; j++)  a[j][i] *= g;
00559          }
00560          else {
00561             for (j = i; j < m; j++) a[j][i] = 0.0;
00562          }
00563          a[i][i] += 1.0;   // ++a[i][i]
00564       }
00565        /* Diagonalization of the bidiagonal form.  */
00566       for (k = n - 1; 0 <= k; k--) {        /* Loop over singular values. */
00567          for (its = 0; its < 30; its++) {    /* Loop over allowed iterations.*/
00568             flag = 1;
00569             for (l = k; 0 <= l; l--) {     // Test for splitting:
00570                nm = l - 1;                 // Note that rv1[1] is always zero
00571                if ( (std::fabs(rv1[l]) + anorm) == anorm) {
00572                   flag = 0;
00573                   break;
00574                }
00575                if ( (std::fabs(w[nm]) + anorm) == anorm) break;
00576             }
00577             if (flag) {
00578               if(l==0) {
00579                 std::cout << " l=0 " <<flag << "\n";
00580               }
00581             c = 0.0;                       /* Cancellation of rv1[l], if l>0:*/
00582             s = 1.0;
00583             for (i = l; i <= k; i++) {
00584                f = s*rv1[i];
00585                if ((std::fabs(f) + anorm) != anorm) {
00586                   g = w[i];
00587                   h = PYTHAG(f, g);
00588                   w[i] = h;
00589                   h = 1.0/h;
00590                   c = g*h;
00591                   s = (-f*h);
00592                   for (j = 0; j < m; j++) {
00593                     if(nm < 0 || nm >= m){
00594                       std::cout << nm << " " << m <<" " << l << "\n";
00595                     }
00596                      y = a[j][nm];
00597                      z = a[j][i];
00598                      a[j][nm] = y*c + z*s;
00599                      a[j][i]  = z*c - y*s;
00600                   }
00601                }
00602             }
00603          }
00604          z = w[k];
00605          if (l == k) {       /* Convergence.  */
00606             if (z < 0.0) {        /* Singular value is made non-negative. */
00607                w[k] = -z;
00608                for (j = 0; j < n; j++) v[j][k] = (-v[j][k]);
00609             }
00610             break;
00611          }
00612          if (its == 29) {
00613             delete [] rv1;
00614             exception("svdcmp(): Not convergence in 30 SVDCMP iterations");
00615          }
00616          x = w[l];               /* Shift from bottom 2-by-2 minor. */
00617          nm = k - 1;
00618          y = w[nm];
00619          g = rv1[nm];
00620          h = rv1[k];
00621          f = ((y - z)*(y + z) + (g - h)*(g + h))/(2.0*h*y);
00622          g = PYTHAG(f, 1.0);
00623          f = ((x - z)*(x + z) + h*((y/(f + SIGN(g, f))) - h))/x;
00624             /* Next QR transformation:    */
00625          c = s = 1.0;
00626          for (j = l; j <= nm; j++) {
00627             i = j + 1;
00628             g = rv1[i];
00629             y = w[i];
00630             h = s*g;
00631             g = c*g;
00632             z = PYTHAG(f, h);
00633             rv1[j] = z;
00634             c = f/z;
00635             s = h/z;
00636             f = x*c + g*s;
00637             g = g*c - x*s;
00638             h = y*s;
00639             y = y*c;
00640             for (jj = 0; jj < n;  jj++) {
00641                x = v[jj][j];
00642                z = v[jj][i];
00643                v[jj][j] = x*c + z*s;
00644                v[jj][i] = z*c - x*s;
00645             }
00646             z = PYTHAG(f, h);
00647             w[j] = z;        /* Rotation can be arbitrary if z = 0.*/
00648             if (z) {
00649                z = 1.0/z;
00650                c = f*z;
00651                s = h*z;
00652             }
00653             f = (c*g) + (s*y);
00654             x = (c*y) - (s*g);
00655             for (jj = 0; jj < m; jj++) {
00656                y = a[jj][j];
00657                z = a[jj][i];
00658                a[jj][j] = y*c + z*s;
00659                a[jj][i] = z*c - y*s;
00660             }
00661          }
00662          rv1[l] = 0.0;
00663          rv1[k] = f;
00664          w[k] = x;
00665       }
00666    }
00667       if(rv1){
00668         delete []  rv1;
00669         rv1=0;
00670       }
00671 }
00672 
00673 // // PYTHAG computes std::sqrt(a^{2} + b^{2}) without destructive overflow or underflow.
00674 
00675 // static BG at, bt, ct;
00676 // #define BG_PYTHAG(a, b) ((at = fabs(a)) > (bt = fabs(b)) ? \
00677 // (ct = bt/at, at*sqrt(1.0+ct*ct)): (bt ? (ct = at/bt, bt*sqrt(1.0+ct*ct)): 0.0))
00678 
00679 // static double maxarg1, maxarg2;
00680 // #define BG_MAX(a, b) (maxarg1 = (a), maxarg2 = (b), (maxarg1) > (maxarg2) ? \
00681 // (maxarg1) : (maxarg2))
00682 
00683 // #define BG_SIGN(a, b) ((b) < 0.0 ? -fabs(a): fabs(a))
00684 
00685 // void svdcmp(double* a[], int m, int n, double w[], double* v[])
00686 // {
00687 //    /////////////////////////////////////////////////////////////////////
00688 //    // Given a matrix a[m][n], this routine computes its singular value
00689 //    // decomposition, A = U*W*V'.  The matrix U replaces a on output.
00690 //    // The diagonal matrix of singular values W is output as a vector w[n].
00691 //    // The matrix V  is output as v[n][n].
00692 //    // m must be greater or equal to n;  if it is smaller, then a should be
00693 //    // filled up to square with zero rows.
00694 //    /////////////////////////////////////////////////////////////////////////
00695 
00696 //    int flag, i, its, j, jj, k, l, nm;
00697 //    double c, f, h, s, x, y, z;
00698 //    double anorm = 0.0, g = 0.0, scale = 0.0;
00699 
00700 //    if (m < n) throw exception("svdcmp(): Matrix A  was not augmented with extra rows of zeros");
00701 
00702 //    double* rv1 = new double [n];
00703 
00704 //     // Householder reduction to bidiagonal form.
00705 //    l = 0;    // added by T. Wang to avoid warning in g++
00706 //    nm = 0;   // added by T. Wang to avoid warning in g++
00707 //    for (i = 0; i < n; i++) {
00708 //       l = i + 1;
00709 //       rv1[i] = scale*g;
00710 //       g = s = scale = 0.0;
00711 //       if (i < m) {
00712 //          for (k = i; k < m; k++) scale += fabs(a[k][i]);
00713 //             if (scale) {
00714 //                for (k = i; k < m; k++) {
00715 //                   a[k][i] /= scale;
00716 //                   s += a[k][i]*a[k][i];
00717 //                }
00718 //                f = a[i][i];
00719 //                g = -BG_SIGN(std::sqrt(s), f);
00720 //                h = f*g - s;
00721 //                a[i][i] = f - g;
00722 //                if (i != n - 1) {
00723 //                   for (j = l; j < n; j++) {
00724 //                      for (s  = 0.0, k = i; k < m; k++) s += a[k][i]*a[k][j];
00725 //                      f = s/h;
00726 //                      for ( k = i; k < m; k++) a[k][j] += f*a[k][i];
00727 //                   }
00728 //                }
00729 //                for (k = i; k < m; k++) a[k][i] *= scale;
00730 //             }
00731 //          }
00732 //          w[i] = scale*g;
00733 //          g = s= scale = 0.0;
00734 //          if (i < m && i != n - 1) {
00735 //             for (k = l; k < n; k++)  scale += std::fabs(a[i][k]);
00736 //             if (scale) {
00737 //                for (k = l; k < n; k++) {
00738 //                   a[i][k] /= scale;
00739 //                   s += a[i][k]*a[i][k];
00740 //                }
00741 //                f = a[i][l];
00742 //                g = -BG_SIGN(std::sqrt(s), f);
00743 //                h = f*g - s;
00744 //                a[i][l] = f - g;
00745 //             //              if(l==0){
00746 //             //                cout << "l eq 0" << endl;
00747 //             //              }
00748 //                for (k = l; k < n; k++)  rv1[k] = a[i][k]/h;
00749 //                if (i != m - 1) {
00750 //                   for (j = l; j < m; j++) {
00751 //                      for (s = 0.0, k = l; k < n; k++) s += a[j][k]*a[i][k];
00752 //                      for (k = l; k < n; k++) a[j][k] += s*rv1[k];
00753 //                   }
00754 //                }
00755 //                for (k = l; k < n; k++) a[i][k] *= scale;
00756 //             }
00757 //          }
00758 //          anorm = BG_MAX(anorm, (std::fabs(w[i]) + std::fabs(rv1[i])));
00759 //       }
00760 //         /* Accumulation of right-hand transformations.       */
00761 //       for (i = n - 1; 0 <= i; i--) {
00762 //          if (i < n - 1) {
00763 //          if (g) {
00764 //                for (j = l; j < n; j++)  v[j][i] = (a[i][j]/a[i][l])/g;
00765 //                /* Double division to avoid possible underflow: */
00766 //                for (j = l; j < n; j++) {
00767 //                   for (s = 0.0, k = l; k < n; k++) s += a[i][k]*v[k][j];
00768 //                   for (k = l; k < n; k++)  v[k][j] += s*v[k][i];
00769 //                }
00770 //          }
00771 //          for (j = l; j < n; j++) v[i][j] = v[j][i] = 0.0;
00772 //          }
00773 //          v[i][i] = 1.0;
00774 //          g = rv1[i];
00775 //          l = i;
00776 //       }
00777 //           /* Accumulation of left-hand transformations.        */
00778 //       for (i = n - 1; 0 <= i; i--) {
00779 //          l = i + 1;
00780 //          g = w[i];
00781 //          if (i < n - 1) for (j = l; j < n; j++) a[i][j] = 0.0;
00782 //          if (g) {
00783 //             g = 1.0/g;
00784 //             if (i != n - 1) {
00785 //                for (j = l; j < n; j++) {
00786 //                for (s = 0.0, k = l; k < m; k++) s += a[k][i]*a[k][j];
00787 //                   f = (s/a[i][i])*g;
00788 //                   for (k = i; k < m; k++) a[k][j] += f*a[k][i];
00789 //                }
00790 //          }
00791 //             for (j = i; j < m; j++)  a[j][i] *= g;
00792 //          }
00793 //          else {
00794 //             for (j = i; j < m; j++) a[j][i] = 0.0;
00795 //          }
00796 //          a[i][i] += 1.0;   // ++a[i][i]
00797 //       }
00798 //        /* Diagonalization of the bidiagonal form.  */
00799 //       for (k = n - 1; 0 <= k; k--) {        /* Loop over singular values. */
00800 //          for (its = 0; its < 30; its++) {    /* Loop over allowed iterations.*/
00801 //             flag = 1;
00802 //             for (l = k; 0 <= l; l--) {     // Test for splitting:
00803 //                nm = l - 1;                 // Note that rv1[1] is always zero
00804 //                if ( (std::fabs(rv1[l]) + anorm) == anorm) {
00805 //                   flag = 0;
00806 //                   break;
00807 //                }
00808 //                if ( (std::fabs(w[nm]) + anorm) == anorm) break;
00809 //             }
00810 //             if (flag) {
00811 //            if(l==0) {
00812 //              std::cout << " l=0 " <<flag << "\n";
00813 //            }
00814 //             c = 0.0;                    /* Cancellation of rv1[l], if l>0:*/
00815 //             s = 1.0;
00816 //             for (i = l; i <= k; i++) {
00817 //                f = s*rv1[i];
00818 //                if ((std::fabs(f) + anorm) != anorm) {
00819 //                   g = w[i];
00820 //                   h = BG_PYTHAG(f, g);
00821 //                   w[i] = h;
00822 //                   h = 1.0/h;
00823 //                   c = g*h;
00824 //                   s = (-f*h);
00825 //                   for (j = 0; j < m; j++) {
00826 //                  if(nm < 0 || nm >= m){
00827 //                    std::cout << nm << " " << m <<" " << l << "\n";
00828 //                  }
00829 //                      y = a[j][nm];
00830 //                      z = a[j][i];
00831 //                      a[j][nm] = y*c + z*s;
00832 //                      a[j][i]  = z*c - y*s;
00833 //                   }
00834 //                }
00835 //             }
00836 //          }
00837 //          z = w[k];
00838 //          if (l == k) {            /* Convergence.  */
00839 //             if (z < 0.0) {        /* Singular value is made non-negative. */
00840 //                w[k] = -z;
00841 //                for (j = 0; j < n; j++) v[j][k] = (-v[j][k]);
00842 //             }
00843 //             break;
00844 //          }
00845 //          if (its == 29) {
00846 //             delete [] rv1;
00847 //             exception("svdcmp(): Not convergence in 30 SVDCMP iterations");
00848 //          }
00849 //          x = w[l];               /* Shift from bottom 2-by-2 minor. */
00850 //          nm = k - 1;
00851 //          y = w[nm];
00852 //          g = rv1[nm];
00853 //          h = rv1[k];
00854 //          f = ((y - z)*(y + z) + (g - h)*(g + h))/(2.0*h*y);
00855 //          g = BG_PYTHAG(f, 1.0);
00856 //          f = ((x - z)*(x + z) + h*((y/(f + BG_SIGN(g, f))) - h))/x;
00857 //          /* Next QR transformation:    */
00858 //          c = s = 1.0;
00859 //          for (j = l; j <= nm; j++) {
00860 //             i = j + 1;
00861 //             g = rv1[i];
00862 //             y = w[i];
00863 //             h = s*g;
00864 //             g = c*g;
00865 //             z = BG_PYTHAG(f, h);
00866 //             rv1[j] = z;
00867 //             c = f/z;
00868 //             s = h/z;
00869 //             f = x*c + g*s;
00870 //             g = g*c - x*s;
00871 //             h = y*s;
00872 //             y = y*c;
00873 //             for (jj = 0; jj < n;  jj++) {
00874 //                x = v[jj][j];
00875 //                z = v[jj][i];
00876 //                v[jj][j] = x*c + z*s;
00877 //                v[jj][i] = z*c - x*s;
00878 //             }
00879 //             z = BG_PYTHAG(f, h);
00880 //             w[j] = z;        /* Rotation can be arbitrary if z = 0.*/
00881 //             if (z) {
00882 //                z = 1.0/z;
00883 //                c = f*z;
00884 //                s = h*z;
00885 //             }
00886 //             f = (c*g) + (s*y);
00887 //             x = (c*y) - (s*g);
00888 //             for (jj = 0; jj < m; jj++) {
00889 //                y = a[jj][j];
00890 //                z = a[jj][i];
00891 //                a[jj][j] = y*c + z*s;
00892 //                a[jj][i] = z*c - y*s;
00893 //             }
00894 //          }
00895 //          rv1[l] = 0.0;
00896 //          rv1[k] = f;
00897 //          w[k] = x;
00898 //       }
00899 //    }
00900 //       if(rv1){
00901 //      delete []  rv1;
00902 //      rv1=0;
00903 //       }
00904 // }
00905 
00906 
00907 
00908 void sweep(const int m, const int n, double **a, const int i0,
00909                   const int i1,const double tol)
00910 /******************************************************************
00911     sweeps matrix A on the pivots indicated by i0 through i1
00912     to produce a new matrix.
00913        for example, suppose that A is partitioned into
00914           [ R S
00915             T U ]
00916       such that R is q by q and nonsingular, U is m-q by n-q.
00917       then sweep(m,n,A,1,q,tol) returns
00918 
00919         /    -1        -1      \
00920         |   R         R  S     |
00921         |      -1          -1  |
00922         \  -T R       U-T R  S /
00923 
00924   Jan. 20,1992, University of Illinois
00925   Copyright (C) 1992-1995 Tianlin Wang
00926 ********************************************************************/
00927 {
00928    if (i0>i1 || i0 > std::min(m,n)) exception("sweep(): inappropriate values of arguments");
00929 
00930    int     i,j,k;
00931    double  d,b, *temp,*ak, *aktemp;
00932 
00933    for (k=i0; k<=i1; k++) {
00934       ak = a[k];
00935       d = ak[k];
00936       if (std::fabs(d) < tol) {
00937          for (i=0;i<m; i++) a[i][k] = 0.0;
00938          memset(ak,'\0',sizeof(double)*n);
00939       }
00940       else {
00941          aktemp = ak;
00942          for (j=0; j<n; j++) *aktemp++ /= d;
00943          for (i=0; i<m; i++) {
00944             aktemp = ak;
00945             if (i != k) {
00946                b = a[i][k];
00947                temp = a[i];
00948                for (j=0; j<n; j++) *temp++ -= *aktemp++ *b;
00949                a[i][k] = -b/d;
00950             }
00951          }
00952          ak[k] = 1.0/d;
00953       }
00954    }
00955 }
00956 
00957 void sweep(const int m, const int n, BG **a, const int i0,
00958                   const int i1,const BG tol)
00959 /******************************************************************
00960     sweeps matrix A on the pivots indicated by i0 through i1
00961     to produce a new matrix.
00962        for example, suppose that A is partitioned into
00963           [ R S
00964             T U ]
00965       such that R is q by q and nonsingular, U is m-q by n-q.
00966       then sweep(m,n,A,1,q,tol) returns
00967 
00968         /    -1        -1      \
00969         |   R         R  S     |
00970         |      -1          -1  |
00971         \  -T R       U-T R  S /
00972 
00973   Jan. 20,1992, University of Illinois
00974   Copyright (C) 1992-1995 Tianlin Wang
00975 ********************************************************************/
00976 {
00977    if (i0>i1 || i0 > std::min(m,n)) exception("sweep(): inappropriate values of arguments");
00978 
00979    int     i,j,k;
00980    BG  d, b, *temp,*ak, *aktemp;
00981 
00982    for (k=i0; k<=i1; k++) {
00983       ak = a[k];
00984       d = ak[k];
00985       if (fabs(d) < tol) {
00986          for (i=0;i<m; i++) a[i][k] = 0.0;
00987          //         memset(ak,'\0',sizeof(BG)*n);
00988          initial_BGarray(ak,n,0.0);
00989       }
00990       else {
00991          aktemp = ak;
00992          for (j=0; j<n; j++) *aktemp++ /= d;
00993          for (i=0; i<m; i++) {
00994             aktemp = ak;
00995             if (i != k) {
00996                b = a[i][k];
00997                temp = a[i];
00998                for (j=0; j<n; j++) *temp++ -= *aktemp++ *b;
00999                a[i][k] = -b/d;
01000             }
01001          }
01002          ak[k] = 1.0/d;
01003       }
01004    }
01005 }
01006 }  /////////// end of namespace
01007 

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