CMS 3D CMS Logo

SprMatrix.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // $Id: SprMatrix.cc,v 1.3 2007/11/12 06:19:18 narsky Exp $
00003 // ---------------------------------------------------------------------------
00004 //
00005 // This file is a part of the CLHEP - a Class Library for High Energy Physics.
00006 // 
00007 // 
00008 // Copyright Cornell University 1993, 1996, All Rights Reserved.
00009 // 
00010 // This software written by Nobu Katayama and Mike Smyth, Cornell University.
00011 // 
00012 // Redistribution and use in source and binary forms, with or without
00013 // modification, are permitted provided that the following conditions
00014 // are met:
00015 // 1. Redistributions of source code must retain the above copyright
00016 //    notice and author attribution, this list of conditions and the
00017 //    following disclaimer. 
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 //    notice and author attribution, this list of conditions and the
00020 //    following disclaimer in the documentation and/or other materials
00021 //    provided with the distribution.
00022 // 3. Neither the name of the University nor the names of its contributors
00023 //    may be used to endorse or promote products derived from this software
00024 //    without specific prior written permission.
00025 // 
00026 // Creation of derivative forms of this software for commercial
00027 // utilization may be subject to restriction; written permission may be
00028 // obtained from Cornell University.
00029 // 
00030 // CORNELL MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  By way
00031 // of example, but not limitation, CORNELL MAKES NO REPRESENTATIONS OR
00032 // WARRANTIES OF MERCANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
00033 // THE USE OF THIS SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS,
00034 // COPYRIGHTS, TRADEMARKS, OR OTHER RIGHTS.  Cornell University shall not be
00035 // held liable for any liability with respect to any claim by the user or any
00036 // other party arising from use of the program.
00037 //
00038 
00039 #include <cfloat>        // for DBL_EPSILON
00040 #include <cmath>
00041 #include <cstdlib>
00042 
00043 #include "SprMatrix.hh"
00044 #include "SprSymMatrix.hh"
00045 #include "SprVector.hh"
00046 
00047 // Simple operation for all elements
00048 
00049 #define SIMPLE_UOP(OPER)                            \
00050    register mIter a=m.begin();                      \
00051    register mIter e=m.end();                        \
00052    for(;a!=e; a++) (*a) OPER t;
00053 
00054 #define SIMPLE_BOP(OPER)                            \
00055    register SprMatrix::mIter a=m.begin();                      \
00056    register SprMatrix::mcIter b=m2.m.begin();                  \
00057    register SprMatrix::mIter e=m.end();                        \
00058    for(;a!=e; a++, b++) (*a) OPER (*b);
00059 
00060 #define SIMPLE_TOP(OPER)                            \
00061    register SprMatrix::mcIter a=m1.m.begin();       \
00062    register SprMatrix::mcIter b=m2.m.begin();       \
00063    register SprMatrix::mIter t=mret.m.begin();      \
00064    register SprMatrix::mcIter e=m1.m.end();         \
00065    for(;a!=e; a++, b++, t++) (*t) = (*a) OPER (*b);
00066 
00067 // Static functions.
00068 
00069 #define CHK_DIM_2(r1,r2,c1,c2,fun) \
00070    if (r1!=r2 || c1!=c2)  { \
00071      SprGenMatrix::error("Range error in Matrix function " #fun "(1)."); \
00072    }
00073 
00074 #define CHK_DIM_1(c1,r2,fun) \
00075    if (c1!=r2) { \
00076      SprGenMatrix::error("Range error in Matrix function " #fun "(2)."); \
00077    }
00078 
00079 // Constructors. (Default constructors are inlined and in .icc file)
00080 
00081 SprMatrix::SprMatrix(int p,int q)
00082    : m(p*q), nrow(p), ncol(q)
00083 {
00084   size = nrow * ncol;
00085 }
00086 
00087 SprMatrix::SprMatrix(int p,int q,int init)
00088    : m(p*q), nrow(p), ncol(q)
00089 {
00090    size = nrow * ncol;
00091 
00092    if (size > 0) {
00093       switch(init)
00094       {
00095       case 0:
00096          break;
00097 
00098       case 1:
00099          {
00100             if ( ncol == nrow ) {
00101                mIter a = m.begin();
00102                mIter b = m.end();
00103                for( ; a<b; a+=(ncol+1)) *a = 1.0;
00104             } else {
00105                error("Invalid dimension in SprMatrix(int,int,1).");
00106             }
00107             break;
00108          }
00109       default:
00110          error("Matrix: initialization must be either 0 or 1.");
00111       }
00112    }
00113 }
00114 
00115 //
00116 // Destructor
00117 //
00118 SprMatrix::~SprMatrix() {
00119 }
00120 
00121 SprMatrix::SprMatrix(const SprMatrix &m1)
00122    : m(m1.size), nrow(m1.nrow), ncol(m1.ncol), size(m1.size)
00123 {
00124    m = m1.m;
00125 
00126 }
00127 
00128 SprMatrix::SprMatrix(const SprSymMatrix &m1)
00129    : m(m1.nrow*m1.nrow), nrow(m1.nrow), ncol(m1.nrow)
00130 {
00131    size = nrow * ncol;
00132 
00133    int n = ncol;
00134    mcIter sjk = m1.m.begin();
00135    mIter m1j = m.begin();
00136    mIter mj  = m.begin();
00137    // j >= k
00138    for(int j=1;j<=nrow;j++) {
00139       mIter mjk = mj;
00140       mIter mkj = m1j;
00141       for(int k=1;k<=j;k++) {
00142          *(mjk++) = *sjk;
00143          if(j!=k) *mkj = *sjk;
00144          sjk++;
00145          mkj += n;
00146       }
00147       mj += n;
00148       m1j++;
00149    }
00150 }
00151 
00152 SprMatrix::SprMatrix(const SprVector &m1)
00153    : m(m1.nrow), nrow(m1.nrow), ncol(1)
00154 {
00155 
00156    size = nrow;
00157    m = m1.m;
00158 }
00159 
00160 
00161 //
00162 //
00163 // Sub matrix
00164 //
00165 //
00166 
00167 SprMatrix SprMatrix::sub(int min_row, int max_row,
00168                          int min_col,int max_col) const
00169 {
00170   SprMatrix mret(max_row-min_row+1,max_col-min_col+1);
00171   if(max_row > num_row() || max_col >num_col())
00172     error("SprMatrix::sub: Index out of range");
00173   mIter a = mret.m.begin();
00174   int nc = num_col();
00175   mcIter b1 = m.begin() + (min_row - 1) * nc + min_col - 1;
00176   
00177   for(int irow=1; irow<=mret.num_row(); irow++) {
00178     mcIter brc = b1;
00179     for(int icol=1; icol<=mret.num_col(); icol++) {
00180       *(a++) = *(brc++);
00181     }
00182     b1 += nc;
00183   }
00184   return mret;
00185 }
00186 
00187 void SprMatrix::sub(int row,int col,const SprMatrix &m1)
00188 {
00189   if(row <1 || row+m1.num_row()-1 > num_row() || 
00190      col <1 || col+m1.num_col()-1 > num_col()   )
00191     error("SprMatrix::sub: Index out of range");
00192   mcIter a = m1.m.begin();
00193   int nc = num_col();
00194   mIter b1 = m.begin() + (row - 1) * nc + col - 1;
00195   
00196   for(int irow=1; irow<=m1.num_row(); irow++) {
00197     mIter brc = b1;
00198     for(int icol=1; icol<=m1.num_col(); icol++) {
00199       *(brc++) = *(a++);
00200     }
00201     b1 += nc;
00202   }
00203 }
00204 
00205 //
00206 // Direct sum of two matricies
00207 //
00208 
00209 SprMatrix dsum(const SprMatrix &m1, const SprMatrix &m2)
00210 {
00211   SprMatrix mret(m1.num_row() + m2.num_row(), m1.num_col() + m2.num_col(),
00212                  0);
00213   mret.sub(1,1,m1);
00214   mret.sub(m1.num_row()+1,m1.num_col()+1,m2);
00215   return mret;
00216 }
00217 
00218 /* -----------------------------------------------------------------------
00219    This section contains support routines for matrix.h. This section contains
00220    The two argument functions +,-. They call the copy constructor and +=,-=.
00221    ----------------------------------------------------------------------- */
00222 SprMatrix SprMatrix::operator- () const 
00223 {
00224    SprMatrix m2(nrow, ncol);
00225    register mcIter a=m.begin();
00226    register mIter b=m2.m.begin();
00227    register mcIter e=m.end();
00228    for(;a<e; a++, b++) (*b) = -(*a);
00229    return m2;
00230 }
00231 
00232    
00233 
00234 SprMatrix operator+(const SprMatrix &m1,const SprMatrix &m2)
00235 {
00236   SprMatrix mret(m1.nrow, m1.ncol);
00237   CHK_DIM_2(m1.num_row(),m2.num_row(), m1.num_col(),m2.num_col(),+);
00238   SIMPLE_TOP(+)
00239   return mret;
00240 }
00241 
00242 //
00243 // operator -
00244 //
00245 
00246 SprMatrix operator-(const SprMatrix &m1,const SprMatrix &m2)
00247 {
00248   SprMatrix mret(m1.num_row(), m1.num_col());
00249   CHK_DIM_2(m1.num_row(),m2.num_row(),
00250                          m1.num_col(),m2.num_col(),-);
00251   SIMPLE_TOP(-)
00252   return mret;
00253 }
00254 
00255 /* -----------------------------------------------------------------------
00256    This section contains support routines for matrix.h. This file contains
00257    The two argument functions *,/. They call copy constructor and then /=,*=.
00258    ----------------------------------------------------------------------- */
00259 
00260 SprMatrix operator/(
00261 const SprMatrix &m1,double t)
00262 {
00263   SprMatrix mret(m1);
00264   mret /= t;
00265   return mret;
00266 }
00267 
00268 SprMatrix operator*(const SprMatrix &m1,double t)
00269 {
00270   SprMatrix mret(m1);
00271   mret *= t;
00272   return mret;
00273 }
00274 
00275 SprMatrix operator*(double t,const SprMatrix &m1)
00276 {
00277   SprMatrix mret(m1);
00278   mret *= t;
00279   return mret;
00280 }
00281 
00282 SprMatrix operator*(const SprMatrix &m1,const SprMatrix &m2)
00283 {
00284   // initialize matrix to 0.0
00285   SprMatrix mret(m1.nrow,m2.ncol,0);
00286   CHK_DIM_1(m1.ncol,m2.nrow,*);
00287 
00288   int m1cols = m1.ncol;
00289   int m2cols = m2.ncol;
00290 
00291   for (int i=0; i<m1.nrow; i++)
00292   {
00293      for (int j=0; j<m1cols; j++) 
00294      {
00295         register double temp = m1.m[i*m1cols+j];
00296         register SprMatrix::mIter pt = mret.m.begin() + i*m2cols;
00297         
00298         // Loop over k (the column index in matrix m2)
00299         register SprMatrix::mcIter pb = m2.m.begin() + m2cols*j;
00300         const SprMatrix::mcIter pblast = pb + m2cols;
00301         while (pb < pblast)
00302         {
00303            (*pt) += temp * (*pb);
00304            pb++;
00305            pt++;
00306         }
00307      }
00308   }
00309 
00310   return mret;
00311 }
00312 
00313 /* -----------------------------------------------------------------------
00314    This section contains the assignment and inplace operators =,+=,-=,*=,/=.
00315    ----------------------------------------------------------------------- */
00316 
00317 SprMatrix & SprMatrix::operator+=(const SprMatrix &m2)
00318 {
00319   CHK_DIM_2(num_row(),m2.num_row(),num_col(),m2.num_col(),+=);
00320   SIMPLE_BOP(+=)
00321   return (*this);
00322 }
00323 
00324 SprMatrix & SprMatrix::operator-=(const SprMatrix &m2)
00325 {
00326   CHK_DIM_2(num_row(),m2.num_row(),num_col(),m2.num_col(),-=);
00327   SIMPLE_BOP(-=)
00328   return (*this);
00329 }
00330 
00331 SprMatrix & SprMatrix::operator/=(double t)
00332 {
00333   SIMPLE_UOP(/=)
00334   return (*this);
00335 }
00336 
00337 SprMatrix & SprMatrix::operator*=(double t)
00338 {
00339   SIMPLE_UOP(*=)
00340   return (*this);
00341 }
00342 
00343 SprMatrix & SprMatrix::operator=(const SprMatrix &m1)
00344 {
00345    if(m1.nrow*m1.ncol != size) //??fixme?? m1.size != size
00346    {
00347       size = m1.nrow * m1.ncol;
00348       m.resize(size); //??fixme?? if (size < m1.size) m.resize(m1.size);
00349    }
00350    nrow = m1.nrow;
00351    ncol = m1.ncol;
00352    m = m1.m;
00353    return (*this);
00354 }
00355 
00356 // SprMatrix & SprMatrix::operator=(const HepRotation &m2) 
00357 // is now in Matrix=Rotation.cc
00358 
00359 // Print the Matrix.
00360 
00361 std::ostream& operator<<(std::ostream &s, const SprMatrix &q)
00362 {
00363   s << "\n";
00364 /* Fixed format needs 3 extra characters for field, while scientific needs 7 */
00365   int width;
00366   if(s.flags() & std::ios::fixed)
00367     width = s.precision()+3;
00368   else
00369     width = s.precision()+7;
00370   for(int irow = 1; irow<= q.num_row(); irow++)
00371     {
00372       for(int icol = 1; icol <= q.num_col(); icol++)
00373         {
00374           s.width(width);
00375           s << q(irow,icol) << " ";
00376         }
00377       s << std::endl;
00378     }
00379   return s;
00380 }
00381 
00382 SprMatrix SprMatrix::T() const
00383 {
00384    SprMatrix mret(ncol,nrow);
00385    register mcIter pl = m.end();
00386    register mcIter pme = m.begin();
00387    register mIter pt = mret.m.begin();
00388    register mIter ptl = mret.m.end();
00389    for (; pme < pl; pme++, pt+=nrow)
00390    {
00391       if (pt >= ptl) pt -= (size-1);
00392       (*pt) = (*pme);
00393    }
00394    return mret;
00395 }
00396 
00397 SprMatrix SprMatrix::apply(double (*f)(double, int, int)) const
00398 {
00399   SprMatrix mret(num_row(),num_col());
00400   mcIter a = m.begin();
00401   mIter b = mret.m.begin();
00402   for(int ir=1;ir<=num_row();ir++) {
00403     for(int ic=1;ic<=num_col();ic++) {
00404       *(b++) = (*f)(*(a++), ir, ic);
00405     }
00406   }
00407   return mret;
00408 }
00409 
00410 int SprMatrix::dfinv_matrix(int *ir) {
00411   if (num_col()!=num_row())
00412     error("dfinv_matrix: Matrix is not NxN");
00413   register int n = num_col();
00414   if (n==1) return 0;
00415 
00416   double s31, s32;
00417   register double s33, s34;
00418 
00419   mIter m11 = m.begin();
00420   mIter m12 = m11 + 1;
00421   mIter m21 = m11 + n;
00422   mIter m22 = m12 + n;
00423   *m21 = -(*m22) * (*m11) * (*m21);
00424   *m12 = -(*m12);
00425   if (n>2) {
00426     mIter mi = m.begin() + 2 * n;
00427     mIter mii= m.begin() + 2 * n + 2;
00428     mIter mimim = m.begin() + n + 1;
00429     for (int i=3;i<=n;i++) {
00430       int im2 = i - 2;
00431       mIter mj = m.begin();
00432       mIter mji = mj + i - 1;
00433       mIter mij = mi;
00434       for (int j=1;j<=im2;j++) { 
00435         s31 = 0.0;
00436         s32 = *mji;
00437         mIter mkj = mj + j - 1;
00438         mIter mik = mi + j - 1;
00439         mIter mjkp = mj + j;
00440         mIter mkpi = mj + n + i - 1;
00441         for (int k=j;k<=im2;k++) {
00442           s31 += (*mkj) * (*(mik++));
00443           s32 += (*(mjkp++)) * (*mkpi);
00444           mkj += n;
00445           mkpi += n;
00446         }
00447         *mij = -(*mii) * (((*(mij-n)))*( (*(mii-1)))+(s31));
00448         *mji = -s32;
00449         mj += n;
00450         mji += n;
00451         mij++;
00452       }
00453       *(mii-1) = -(*mii) * (*mimim) * (*(mii-1));
00454       *(mimim+1) = -(*(mimim+1));
00455       mi += n;
00456       mimim += (n+1);
00457       mii += (n+1);
00458     }
00459   }
00460   mIter mi = m.begin();
00461   mIter mii = m.begin();
00462   for (int i=1;i<n;i++) {
00463     int ni = n - i;
00464     mIter mij = mi;
00465     int j;
00466     for (j=1; j<=i;j++) {
00467       s33 = *mij;
00468       register mIter mikj = mi + n + j - 1;
00469       register mIter miik = mii + 1;
00470       mIter min_end = mi + n;
00471       for (;miik<min_end;) {
00472         s33 += (*mikj) * (*(miik++));
00473         mikj += n;
00474       }
00475       *(mij++) = s33;
00476     }
00477     for (j=1;j<=ni;j++) {
00478       s34 = 0.0;
00479       mIter miik = mii + j;
00480       mIter mikij = mii + j * n + j;
00481       for (int k=j;k<=ni;k++) {
00482         s34 += *mikij * (*(miik++));
00483         mikij += n;
00484       }
00485       *(mii+j) = s34;
00486     }
00487     mi += n;
00488     mii += (n+1);
00489   }
00490   int nxch = ir[n];
00491   if (nxch==0) return 0;
00492   for (int mm=1;mm<=nxch;mm++) {
00493     int k = nxch - mm + 1;
00494     int ij = ir[k];
00495     int i = ij >> 12;
00496     int j = ij%4096;
00497     mIter mki = m.begin() + i - 1;
00498     mIter mkj = m.begin() + j - 1;
00499     for (k=1; k<=n;k++) {
00500       // 2/24/05 David Sachs fix of improper swap bug that was present
00501       // for many years:
00502       double ti = *mki; // 2/24/05
00503       *mki = *mkj;
00504       *mkj = ti;        // 2/24/05
00505       mki += n;
00506       mkj += n;
00507     }
00508   }
00509   return 0;
00510 }
00511 
00512 int SprMatrix::dfact_matrix(double &det, int *ir) {
00513   if (ncol!=nrow)
00514      error("dfact_matrix: Matrix is not NxN");
00515 
00516   int ifail, jfail;
00517   register int n = ncol;
00518 
00519   double tf;
00520   double g1 = 1.0e-19, g2 = 1.0e19;
00521 
00522   double p, q, t;
00523   double s11, s12;
00524 
00525   double epsilon = 8*DBL_EPSILON;
00526   // could be set to zero (like it was before)
00527   // but then the algorithm often doesn't detect
00528   // that a matrix is singular
00529 
00530   int normal = 0, imposs = -1;
00531   int jrange = 0, jover = 1, junder = -1;
00532   ifail = normal;
00533   jfail = jrange;
00534   int nxch = 0;
00535   det = 1.0;
00536   mIter mj = m.begin();
00537   mIter mjj = mj;
00538   for (int j=1;j<=n;j++) {
00539     int k = j;
00540     p = (fabs(*mjj));
00541     if (j!=n) {
00542       mIter mij = mj + n + j - 1; 
00543       for (int i=j+1;i<=n;i++) {
00544         q = (fabs(*(mij)));
00545         if (q > p) {
00546           k = i;
00547           p = q;
00548         }
00549         mij += n;
00550       }
00551       if (k==j) {
00552         if (p <= epsilon) {
00553           det = 0;
00554           ifail = imposs;
00555           jfail = jrange;
00556           return ifail;
00557         }
00558         det = -det; // in this case the sign of the determinant
00559                     // must not change. So I change it twice. 
00560       }
00561       mIter mjl = mj;
00562       mIter mkl = m.begin() + (k-1)*n;
00563       for (int l=1;l<=n;l++) {
00564         tf = *mjl;
00565         *(mjl++) = *mkl;
00566         *(mkl++) = tf;
00567       }
00568       nxch = nxch + 1;  // this makes the determinant change its sign
00569       ir[nxch] = (((j)<<12)+(k));
00570     } else {
00571       if (p <= epsilon) {
00572         det = 0.0;
00573         ifail = imposs;
00574         jfail = jrange;
00575         return ifail;
00576       }
00577     }
00578     det *= *mjj;
00579     *mjj = 1.0 / *mjj;
00580     t = (fabs(det));
00581     if (t < g1) {
00582       det = 0.0;
00583       if (jfail == jrange) jfail = junder;
00584     } else if (t > g2) {
00585       det = 1.0;
00586       if (jfail==jrange) jfail = jover;
00587     }
00588     if (j!=n) {
00589       mIter mk = mj + n;
00590       mIter mkjp = mk + j;
00591       mIter mjk = mj + j;
00592       for (k=j+1;k<=n;k++) {
00593         s11 = - (*mjk);
00594         s12 = - (*mkjp);
00595         if (j!=1) {
00596           mIter mik = m.begin() + k - 1;
00597           mIter mijp = m.begin() + j;
00598           mIter mki = mk;
00599           mIter mji = mj;
00600           for (int i=1;i<j;i++) {
00601             s11 += (*mik) * (*(mji++));
00602             s12 += (*mijp) * (*(mki++));
00603             mik += n;
00604             mijp += n;
00605           }
00606         }
00607         *(mjk++) = -s11 * (*mjj);
00608         *(mkjp) = -(((*(mjj+1)))*((*(mkjp-1)))+(s12));
00609         mk += n;
00610         mkjp += n;
00611       }
00612     }
00613     mj += n;
00614     mjj += (n+1);
00615   }
00616   if (nxch%2==1) det = -det;
00617   if (jfail !=jrange) det = 0.0;
00618   ir[n] = nxch;
00619   return 0;
00620 }
00621 
00622 // I removed Matrix invert functionality -Xuan Luo 18 Jul 2006
00623 // void SprMatrix::invert(int &) {}
00624 
00625 double SprMatrix::determinant() const {
00626   static int max_array = 20;
00627   static int *ir = new int [max_array+1];
00628   if(ncol != nrow)
00629     error("SprMatrix::determinant: Matrix is not NxN");
00630   if (ncol > max_array) {
00631     delete [] ir;
00632     max_array = nrow;
00633     ir = new int [max_array+1];
00634   }
00635   double det;
00636   SprMatrix mt(*this);
00637   int i = mt.dfact_matrix(det, ir);
00638   if(i==0) return det;
00639   return 0;
00640 }
00641 
00642 double SprMatrix::trace() const {
00643    double t = 0.0;
00644    for (mcIter d = m.begin(); d < m.end(); d += (ncol+1) )
00645       t += *d;
00646    return t;
00647 }
00648 
00649 
00650 void SprMatrix::row_house(const SprMatrix &v,
00651                           int row,int col,int row_start,int col_start)
00652 {
00653    double normsq=0;
00654    int end = row_start+this->num_row()-row;
00655    for (int i=row_start; i<=end; i++)
00656      normsq += v(i,col)*v(i,col);
00657    // If v is 0, then we can skip doing row_house.
00658    if (normsq !=0)
00659      this->row_house(v,normsq,row,col,row_start,col_start);
00660 }
00661 
00662 
00663 void SprMatrix::row_house(const SprMatrix &v,
00664                           double vnormsq,
00665                           int row, int col, int row_start, int col_start) {
00666    double beta=-2/vnormsq;
00667 
00668    // This is a fast way of calculating w=beta*A.sub(row,n,col,n).T()*v
00669    SprVector w(this->num_col()-col+1,0);
00670    int na = this->num_col();
00671    int nv = v.num_col();
00672    SprMatrix::mIter wptr = w.m.begin();
00673    SprMatrix::mIter arcb = this->m.begin() + (row-1) * na + (col-1);
00674    SprMatrix::mcIter vpcb = v.m.begin() + (row_start-1) * nv + (col_start-1);
00675    int c;
00676    for (c=col;c<=this->num_col();c++) {
00677       SprMatrix::mIter arc = arcb;
00678       SprMatrix::mcIter vpc = vpcb;
00679       for (int r=row;r<=this->num_row();r++) {
00680          (*wptr)+=(*arc)*(*vpc);
00681          arc += na;
00682          vpc += nv;
00683       }
00684       wptr++;
00685       arcb++;
00686    }
00687    w*=beta;
00688 
00689    arcb = this->m.begin() + (row-1) * na + (col-1);
00690    SprMatrix::mcIter vpc = v.m.begin() + (row_start-1) * nv + (col_start-1);
00691    for (int r=row; r<=this->num_row();r++) {
00692       SprMatrix::mIter arc = arcb;
00693       SprMatrix::mIter wptr = w.m.begin();
00694       for (c=col;c<=this->num_col();c++) {
00695          (*(arc++))+=(*vpc)*(*(wptr++));
00696       }
00697       arcb += na;
00698       vpc += nv;
00699    }
00700 }
00701 
00702 
00703 void SprMatrix::givens(double a, double b, double *c, double *s)
00704 {
00705    if (b ==0) { *c=1; *s=0; }
00706    else {
00707       if (fabs(b)>fabs(a)) {
00708          double tau=-a/b;
00709          *s=1/sqrt(1+tau*tau);
00710          *c=(*s)*tau;
00711       } else {
00712          double tau=-b/a;
00713          *c=1/sqrt(1+tau*tau);
00714          *s=(*c)*tau;
00715       }
00716    }
00717 }
00718 
00719 
00720 void SprMatrix::col_givens(double c,double s,
00721                            int k1, int k2, int row_min, int row_max) {
00722    if (row_max<=0) row_max = this->num_row();
00723    int n = this->num_col();
00724    SprMatrix::mIter Ajk1 = this->m.begin() + (row_min - 1) * n + k1 - 1;
00725    SprMatrix::mIter Ajk2 = this->m.begin() + (row_min - 1) * n + k2 - 1;
00726    for (int j=row_min;j<=row_max;j++) {
00727       double tau1=(*Ajk1); double tau2=(*Ajk2);
00728       (*Ajk1)=c*tau1-s*tau2;(*Ajk2)=s*tau1+c*tau2;
00729       Ajk1 += n;
00730       Ajk2 += n;
00731    }
00732 }
00733 

Generated on Tue Jun 9 17:42:03 2009 for CMSSW by  doxygen 1.5.4