TDecompBK.cxx

Go to the documentation of this file.
00001 // @(#)root/matrix:$Id: TDecompBK.cxx 35903 2010-09-30 10:41:51Z brun $
00002 // Authors: Fons Rademakers, Eddy Offermann  Sep 2004
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TDecompBK.h"
00013 #include "TMath.h"
00014 #include "TError.h"
00015 
00016 ClassImp(TDecompBK)
00017 
00018 ///////////////////////////////////////////////////////////////////////////
00019 //                                                                       //
00020 // The Bunch-Kaufman diagonal pivoting method decomposes a real          //
00021 // symmetric matrix A using                                              //
00022 //                                                                       //
00023 //     A = U*D*U^T                                                       //
00024 //                                                                       //
00025 //  where U is a product of permutation and unit upper triangular        //
00026 //  matrices, U^T is the transpose of U, and D is symmetric and block    //
00027 //  diagonal with 1-by-1 and 2-by-2 diagonal blocks.                     //
00028 //                                                                       //
00029 //     U = P(n-1)*U(n-1)* ... *P(k)U(k)* ...,                            //
00030 //  i.e., U is a product of terms P(k)*U(k), where k decreases from n-1  //
00031 //  to 0 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1//
00032 //  and 2-by-2 diagonal blocks D(k).  P(k) is a permutation matrix as    //
00033 //  defined by IPIV(k), and U(k) is a unit upper triangular matrix, such //
00034 //  that if the diagonal block D(k) is of order s (s = 1 or 2), then     //
00035 //                                                                       //
00036 //             (   I    v    0   )   k-s                                 //
00037 //     U(k) =  (   0    I    0   )   s                                   //
00038 //             (   0    0    I   )   n-k                                 //
00039 //                k-s   s   n-k                                          //
00040 //                                                                       //
00041 //  If s = 1, D(k) overwrites A(k,k), and v overwrites A(0:k-1,k).       //
00042 //  If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k),//
00043 //  and A(k,k), and v overwrites A(0:k-2,k-1:k).                         //
00044 //                                                                       //
00045 // fU contains on entry the symmetric matrix A of which only the upper   //
00046 // triangular part is referenced . On exit fU contains the block diagonal//
00047 // matrix D and the multipliers used to obtain the factor U, see above . //
00048 //                                                                       //
00049 // fIpiv if dimension n contains details of the interchanges and the     //
00050 // the block structure of D . If (fIPiv(k) > 0, then rows and columns k  //
00051 // and fIPiv(k) were interchanged and D(k,k) is a 1-by-1 diagonal block. //
00052 // If IPiv(k) = fIPiv(k-1) < 0, rows and columns k-1 and -IPiv(k) were   //
00053 // interchanged and D(k-1:k,k-1:k) is a 2-by-2 diagonal block.           //
00054 //                                                                       //
00055 ///////////////////////////////////////////////////////////////////////////
00056 
00057 //______________________________________________________________________________
00058 TDecompBK::TDecompBK()
00059 {
00060 // Default constructor
00061    fNIpiv = 0;
00062    fIpiv  = 0;
00063 }
00064 
00065 //______________________________________________________________________________
00066 TDecompBK::TDecompBK(Int_t nrows)
00067 {
00068 // Constructor for (nrows x nrows) symmetric matrix
00069 
00070    fNIpiv = nrows;
00071    fIpiv = new Int_t[fNIpiv];
00072    memset(fIpiv,0,fNIpiv*sizeof(Int_t));
00073    fU.ResizeTo(nrows,nrows);
00074 }
00075 
00076 //______________________________________________________________________________
00077 TDecompBK::TDecompBK(Int_t row_lwb,Int_t row_upb)
00078 {
00079 // Constructor for ([row_lwb..row_upb] x [row_lwb..row_upb]) symmetric matrix
00080 
00081    const Int_t nrows = row_upb-row_lwb+1;
00082    fNIpiv = nrows;
00083    fIpiv = new Int_t[fNIpiv];
00084    memset(fIpiv,0,fNIpiv*sizeof(Int_t));
00085    fColLwb = fRowLwb = row_lwb;
00086    fU.ResizeTo(nrows,nrows);
00087 }
00088 
00089 //______________________________________________________________________________
00090 TDecompBK::TDecompBK(const TMatrixDSym &a,Double_t tol)
00091 {
00092 // Constructor for symmetric matrix A
00093 
00094    R__ASSERT(a.IsValid());
00095 
00096    SetBit(kMatrixSet);
00097    fCondition = a.Norm1();
00098    fTol = a.GetTol();
00099    if (tol > 0)
00100       fTol = tol;
00101 
00102    fNIpiv = a.GetNcols();
00103    fIpiv = new Int_t[fNIpiv];
00104    memset(fIpiv,0,fNIpiv*sizeof(Int_t));
00105 
00106    const Int_t nRows = a.GetNrows();
00107    fColLwb = fRowLwb = a.GetRowLwb();
00108    fU.ResizeTo(nRows,nRows);
00109    memcpy(fU.GetMatrixArray(),a.GetMatrixArray(),nRows*nRows*sizeof(Double_t));
00110 }
00111 
00112 //______________________________________________________________________________
00113 TDecompBK::TDecompBK(const TDecompBK &another) : TDecompBase(another)
00114 {
00115 // Copy constructor
00116 
00117    fNIpiv = 0;
00118    fIpiv  = 0;
00119    *this = another;
00120 }
00121 
00122 //______________________________________________________________________________
00123 Bool_t TDecompBK::Decompose()
00124 {
00125 // Matrix A is decomposed in components U and D so that A = U*D*U^T
00126 // If the decomposition succeeds, bit kDecomposed is set , otherwise kSingular
00127 
00128    if (TestBit(kDecomposed)) return kTRUE;
00129 
00130    if ( !TestBit(kMatrixSet) ) {
00131       Error("Decompose()","Matrix has not been set");
00132       return kFALSE;
00133    }
00134 
00135    Bool_t ok = kTRUE;
00136 
00137 // Initialize alpha for use in choosing pivot block size.
00138    const Double_t alpha = (1.+TMath::Sqrt(17.))/8.;
00139 
00140 // Factorize a as u*d*u' using the upper triangle of a .
00141 //  k is the main loop index, decreasing from n-1 to 0 in steps of 1 or 2
00142 
00143    const Int_t     n  = fU.GetNcols();
00144          Double_t *pU = fU.GetMatrixArray();
00145    TMatrixDDiag diag(fU);
00146 
00147    Int_t imax = 0;
00148    Int_t k = n-1;
00149    while (k >= 0) {
00150       Int_t kstep = 1;
00151 
00152       // determine rows and columns to be interchanged and whether
00153       // a 1-by-1 or 2-by-2 pivot block will be used
00154 
00155       const Double_t absakk = TMath::Abs(diag(k));
00156 
00157       // imax is the row-index of the largest off-diagonal element in
00158       // column k, and colmax is its absolute value
00159 
00160       Double_t colmax;
00161       if ( k > 0 ) {
00162          TVectorD vcol = TMatrixDColumn_const(fU,k);
00163          vcol.Abs();
00164          imax = TMath::LocMax(k,vcol.GetMatrixArray());
00165          colmax = vcol[imax];
00166       } else {
00167          colmax = 0.;
00168       }
00169 
00170       Int_t kp;
00171       if (TMath::Max(absakk,colmax) <= fTol) {
00172          // the block diagonal matrix will be singular
00173          kp = k;
00174          ok = kFALSE;
00175       } else {
00176          if (absakk >= alpha*colmax) {
00177            // no interchange, use 1-by-1 pivot block
00178             kp = k;
00179          } else {
00180             // jmax is the column-index of the largest off-diagonal
00181             // element in row imax, and rowmax is its absolute value
00182             TVectorD vrow = TMatrixDRow_const(fU,imax);
00183             vrow.Abs();
00184             Int_t jmax = imax+1+TMath::LocMax(k-imax,vrow.GetMatrixArray()+imax+1);
00185             Double_t rowmax = vrow[jmax];
00186             if (imax > 0) {
00187                TVectorD vcol = TMatrixDColumn_const(fU,imax);
00188                vcol.Abs();
00189                jmax = TMath::LocMax(imax,vcol.GetMatrixArray());
00190                rowmax = TMath::Max(rowmax,vcol[jmax]);
00191             }
00192 
00193             if (absakk >= alpha*colmax*(colmax/rowmax)) {
00194                // No interchange, use 1-by-1 pivot block
00195                kp = k;
00196             } else if( TMath::Abs(diag(imax)) >= alpha*rowmax) {
00197                // Interchange rows and columns k and imax, use 1-by-1 pivot block
00198                kp = imax;
00199             } else {
00200                // Interchange rows and columns k-1 and imax, use 2-by-2 pivot block
00201                kp = imax;
00202                kstep = 2;
00203             }
00204          }
00205 
00206          const Int_t kk = k-kstep+1;
00207          if (kp != kk) {
00208             // Interchange rows and columns kk and kp in the leading submatrix a(0:k,0:k)
00209             Double_t *c_kk = pU+kk;
00210             Double_t *c_kp = pU+kp;
00211             for (Int_t irow = 0; irow < kp; irow++) {
00212                const Double_t t = *c_kk;
00213                *c_kk = *c_kp;
00214                *c_kp = t;
00215                c_kk += n;
00216                c_kp += n;
00217             }
00218 
00219             c_kk = pU+(kp+1)*n+kk;
00220             Double_t *r_kp = pU+kp*n+kp+1;
00221             for (Int_t icol = 0; icol < kk-kp-1; icol++) {
00222                const Double_t t = *c_kk;
00223                *c_kk = *r_kp;
00224                *r_kp = t;
00225                c_kk += n;
00226                r_kp += 1;
00227             }
00228 
00229             Double_t t = diag(kk);
00230             diag(kk) = diag(kp);
00231             diag(kp) = t;
00232             if (kstep == 2) {
00233                t = pU[(k-1)*n+k];
00234                pU[(k-1)*n+k] = pU[kp*n+k];
00235                pU[kp*n+k]    = t;
00236             }
00237          }
00238 
00239          // Update the leading submatrix
00240 
00241          if (kstep == 1 && k > 0) {
00242             // 1-by-1 pivot block d(k): column k now holds w(k) = u(k)*d(k)
00243             // where u(k) is the k-th column of u
00244 
00245             // perform a rank-1 update of a(0:k-1,0:k-1) as
00246             // a := a - u(k)*d(k)*u(k)' = a - w(k)*1/d(k)*w(k)'
00247 
00248             const Double_t r1 = 1./diag(k);
00249             TMatrixDSub sub1(fU,0,k-1,0,k-1);
00250             sub1.Rank1Update(TMatrixDColumn_const(fU,k),-r1);
00251 
00252             // store u(k) in column k
00253             TMatrixDSub sub2(fU,0,k-1,k,k);
00254             sub2 *= r1;
00255          } else {
00256             // 2-by-2 pivot block d(k): columns k and k-1 now hold
00257             // ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k)
00258             // where u(k) and u(k-1) are the k-th and (k-1)-th columns of u
00259 
00260             // perform a rank-2 update of a(0:k-2,0:k-2) as
00261             // a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )'
00262             //    = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )'
00263 
00264             if ( k > 1 ) {
00265                      Double_t *pU_k1 = pU+(k-1)*n;
00266                      Double_t d12    = pU_k1[k];
00267                const Double_t d22    = pU_k1[k-1]/d12;
00268                const Double_t d11    = diag(k)/d12;
00269                const Double_t t      = 1./(d11*d22-1.);
00270                d12 = t/d12;
00271 
00272                for (Int_t j = k-2; j >= 0; j--) {
00273                   Double_t *pU_j = pU+j*n;
00274                   const Double_t wkm1 = d12*(d11*pU_j[k-1]-pU_j[k]);
00275                   const Double_t wk   = d12*(d22*pU_j[k]-pU_j[k-1]);
00276                   for (Int_t i = j; i >= 0; i--) {
00277                      Double_t *pU_i = pU+i*n;
00278                      pU_i[j] -= (pU_i[k]*wk+pU_i[k-1]*wkm1);
00279                   }
00280                   pU_j[k]   = wk;
00281                   pU_j[k-1] = wkm1;
00282                }
00283             }
00284          }
00285 
00286          // Store details of the interchanges in fIpiv
00287          if (kstep == 1) {
00288             fIpiv[k] = (kp+1);
00289          } else {
00290             fIpiv[k]   = -(kp+1);
00291             fIpiv[k-1] = -(kp+1);
00292          }
00293       }
00294 
00295       k -= kstep;
00296    }
00297 
00298    if (!ok) SetBit(kSingular);
00299    else     SetBit(kDecomposed);
00300 
00301    fU.Shift(fRowLwb,fRowLwb);
00302 
00303    return ok;
00304 }
00305 
00306 //______________________________________________________________________________
00307 void TDecompBK::SetMatrix(const TMatrixDSym &a)
00308 {
00309 // Set the matrix to be decomposed, decomposition status is reset.
00310 
00311    R__ASSERT(a.IsValid());
00312 
00313    ResetStatus();
00314 
00315    SetBit(kMatrixSet);
00316    fCondition = a.Norm1();
00317 
00318    if (fNIpiv != a.GetNcols()) {
00319       fNIpiv = a.GetNcols();
00320       delete [] fIpiv;
00321       fIpiv = new Int_t[fNIpiv];
00322       memset(fIpiv,0,fNIpiv*sizeof(Int_t));
00323    }
00324 
00325    const Int_t nRows = a.GetNrows();
00326    fColLwb = fRowLwb = a.GetRowLwb();
00327    fU.ResizeTo(nRows,nRows);
00328    memcpy(fU.GetMatrixArray(),a.GetMatrixArray(),nRows*nRows*sizeof(Double_t));
00329 }
00330 
00331 //______________________________________________________________________________
00332 Bool_t TDecompBK::Solve(TVectorD &b)
00333 {
00334 // Solve Ax=b assuming the BK form of A is stored in fU . Solution returned in b.
00335 
00336    R__ASSERT(b.IsValid());
00337    if (TestBit(kSingular)) {
00338       Error("Solve()","Matrix is singular");
00339       return kFALSE;
00340    }
00341    if ( !TestBit(kDecomposed) ) {
00342       if (!Decompose()) {
00343          Error("Solve()","Decomposition failed");
00344          return kFALSE;
00345       }
00346    }
00347 
00348    if (fU.GetNrows() != b.GetNrows() || fU.GetRowLwb() != b.GetLwb()) {
00349       Error("Solve(TVectorD &","vector and matrix incompatible");
00350       return kFALSE;
00351    }
00352 
00353    const Int_t n = fU.GetNrows();
00354 
00355    TMatrixDDiag_const diag(fU);
00356    const Double_t *pU = fU.GetMatrixArray();
00357          Double_t *pb = b.GetMatrixArray();
00358 
00359    // solve a*x = b, where a = u*d*u'. First solve u*d*x = b, overwriting b with x.
00360    // k is the main loop index, decreasing from n-1 to 0 in steps of 1 or 2,
00361    // depending on the size of the diagonal blocks.
00362 
00363    Int_t k = n-1;
00364    while (k >= 0) {
00365 
00366       if (fIpiv[k] > 0) {
00367 
00368          //  1 x 1 diagonal block
00369          //  interchange rows k and ipiv(k).
00370          const Int_t kp = fIpiv[k]-1;
00371          if (kp != k) {
00372             const Double_t tmp = pb[k];
00373             pb[k]  = pb[kp];
00374             pb[kp] = tmp;
00375          }
00376 
00377          // multiply by inv(u(k)), where u(k) is the transformation
00378          // stored in column k of a.
00379          for (Int_t i = 0; i < k; i++)
00380             pb[i] -= pU[i*n+k]*pb[k];
00381 
00382          // multiply by the inverse of the diagonal block.
00383          pb[k] /= diag(k);
00384          k--;
00385       } else {
00386 
00387          // 2 x 2 diagonal block
00388          // interchange rows k-1 and -ipiv(k).
00389          const Int_t kp = -fIpiv[k]-1;
00390          if (kp != k-1) {
00391             const Double_t tmp = pb[k-1];
00392             pb[k-1]  = pb[kp];
00393             pb[kp]   = tmp;
00394          }
00395 
00396          // multiply by inv(u(k)), where u(k) is the transformation
00397          // stored in columns k-1 and k of a.
00398          Int_t i;
00399          for (i = 0; i < k-1; i++)
00400             pb[i] -= pU[i*n+k]*pb[k];
00401          for (i = 0; i < k-1; i++)
00402             pb[i] -= pU[i*n+k-1]*pb[k-1];
00403 
00404          // multiply by the inverse of the diagonal block.
00405          const Double_t *pU_k1 = pU+(k-1)*n;
00406          const Double_t ukm1k  = pU_k1[k];
00407          const Double_t ukm1   = pU_k1[k-1]/ukm1k;
00408          const Double_t uk     = diag(k)/ukm1k;
00409          const Double_t denom  = ukm1*uk-1.;
00410          const Double_t bkm1   = pb[k-1]/ukm1k;
00411          const Double_t bk     = pb[k]/ukm1k;
00412          pb[k-1] = (uk*bkm1-bk)/denom;
00413          pb[k]   = (ukm1*bk-bkm1)/denom;
00414          k -= 2;
00415       }
00416    }
00417 
00418    // Next solve u'*x = b, overwriting b with x.
00419    //
00420    //  k is the main loop index, increasing from 0 to n-1 in steps of
00421    //  1 or 2, depending on the size of the diagonal blocks.
00422 
00423    k = 0;
00424    while (k < n) {
00425 
00426       if (fIpiv[k] > 0) {
00427          // 1 x 1 diagonal block
00428          //  multiply by inv(u'(k)), where u(k) is the transformation
00429          //  stored in column k of a.
00430          for (Int_t i = 0; i < k; i++)
00431             pb[k] -= pU[i*n+k]*pb[i];
00432 
00433          // interchange elements k and ipiv(k).
00434          const Int_t kp = fIpiv[k]-1;
00435          if (kp != k) {
00436             const Double_t tmp = pb[k];
00437             pb[k]  = pb[kp];
00438             pb[kp] = tmp;
00439          }
00440          k++;
00441       } else {
00442          // 2 x 2 diagonal block
00443          // multiply by inv(u'(k+1)), where u(k+1) is the transformation
00444          // stored in columns k and k+1 of a.
00445          Int_t i ;
00446          for (i = 0; i < k; i++)
00447             pb[k] -= pU[i*n+k]*pb[i];
00448          for (i = 0; i < k; i++)
00449             pb[k+1] -= pU[i*n+k+1]*pb[i];
00450 
00451          // interchange elements k and -ipiv(k).
00452          const Int_t kp = -fIpiv[k]-1;
00453          if (kp != k) {
00454             const Double_t tmp = pb[k];
00455             pb[k]  = pb[kp];
00456             pb[kp] = tmp;
00457          }
00458          k += 2;
00459       }
00460    }
00461 
00462    return kTRUE;
00463 }
00464 
00465 //______________________________________________________________________________
00466 Bool_t TDecompBK::Solve(TMatrixDColumn &cb)
00467 {
00468 // Solve Ax=b assuming the BK form of A is stored in fU . Solution returned in b.
00469 
00470    TMatrixDBase *b = const_cast<TMatrixDBase *>(cb.GetMatrix());
00471    R__ASSERT(b->IsValid());
00472    if (TestBit(kSingular)) {
00473       Error("Solve()","Matrix is singular");
00474       return kFALSE;
00475    }
00476    if ( !TestBit(kDecomposed) ) {
00477       if (!Decompose()) {
00478          Error("Solve()","Decomposition failed");
00479          return kFALSE;
00480       }
00481    }
00482 
00483    if (fU.GetNrows() != b->GetNrows() || fU.GetRowLwb() != b->GetRowLwb()) {
00484       Error("Solve(TMatrixDColumn &","vector and matrix incompatible");
00485       return kFALSE;
00486    }
00487 
00488    const Int_t n = fU.GetNrows();
00489 
00490    TMatrixDDiag_const diag(fU);
00491    const Double_t *pU  = fU.GetMatrixArray();
00492          Double_t *pcb = cb.GetPtr();
00493    const Int_t     inc = cb.GetInc();
00494 
00495 
00496   // solve a*x = b, where a = u*d*u'. First solve u*d*x = b, overwriting b with x.
00497   // k is the main loop index, decreasing from n-1 to 0 in steps of 1 or 2,
00498   // depending on the size of the diagonal blocks.
00499 
00500    Int_t k = n-1;
00501    while (k >= 0) {
00502 
00503       if (fIpiv[k] > 0) {
00504 
00505          //  1 x 1 diagonal block
00506          //  interchange rows k and ipiv(k).
00507          const Int_t kp = fIpiv[k]-1;
00508          if (kp != k) {
00509             const Double_t tmp = pcb[k*inc];
00510             pcb[k*inc]  = pcb[kp*inc];
00511             pcb[kp*inc] = tmp;
00512          }
00513 
00514          // multiply by inv(u(k)), where u(k) is the transformation
00515          // stored in column k of a.
00516          for (Int_t i = 0; i < k; i++)
00517             pcb[i*inc] -= pU[i*n+k]*pcb[k*inc];
00518 
00519          // multiply by the inverse of the diagonal block.
00520          pcb[k*inc] /= diag(k);
00521          k--;
00522       } else {
00523 
00524          // 2 x 2 diagonal block
00525          // interchange rows k-1 and -ipiv(k).
00526          const Int_t kp = -fIpiv[k]-1;
00527          if (kp != k-1) {
00528             const Double_t tmp = pcb[(k-1)*inc];
00529             pcb[(k-1)*inc] = pcb[kp*inc];
00530             pcb[kp*inc]    = tmp;
00531          }
00532 
00533          // multiply by inv(u(k)), where u(k) is the transformation
00534          // stored in columns k-1 and k of a.
00535          Int_t i;
00536          for (i = 0; i < k-1; i++)
00537             pcb[i*inc] -= pU[i*n+k]*pcb[k*inc];
00538          for (i = 0; i < k-1; i++)
00539             pcb[i*inc] -= pU[i*n+k-1]*pcb[(k-1)*inc];
00540 
00541          // multiply by the inverse of the diagonal block.
00542          const Double_t *pU_k1 = pU+(k-1)*n;
00543          const Double_t ukm1k  = pU_k1[k];
00544          const Double_t ukm1   = pU_k1[k-1]/ukm1k;
00545          const Double_t uk     = diag(k)/ukm1k;
00546          const Double_t denom  = ukm1*uk-1.;
00547          const Double_t bkm1   = pcb[(k-1)*inc]/ukm1k;
00548          const Double_t bk     = pcb[k*inc]/ukm1k;
00549          pcb[(k-1)*inc] = (uk*bkm1-bk)/denom;
00550          pcb[k*inc]     = (ukm1*bk-bkm1)/denom;
00551          k -= 2;
00552       }
00553    }
00554 
00555    // Next solve u'*x = b, overwriting b with x.
00556    //
00557    //  k is the main loop index, increasing from 0 to n-1 in steps of
00558    //  1 or 2, depending on the size of the diagonal blocks.
00559 
00560    k = 0;
00561    while (k < n) {
00562 
00563       if (fIpiv[k] > 0) {
00564          // 1 x 1 diagonal block
00565          //  multiply by inv(u'(k)), where u(k) is the transformation
00566          //  stored in column k of a.
00567          for (Int_t i = 0; i < k; i++)
00568             pcb[k*inc] -= pU[i*n+k]*pcb[i*inc];
00569 
00570          // interchange elements k and ipiv(k).
00571          const Int_t kp = fIpiv[k]-1;
00572          if (kp != k) {
00573             const Double_t tmp = pcb[k*inc];
00574             pcb[k*inc]  = pcb[kp*inc];
00575             pcb[kp*inc] = tmp;
00576          }
00577          k++;
00578       } else {
00579          // 2 x 2 diagonal block
00580          // multiply by inv(u'(k+1)), where u(k+1) is the transformation
00581          // stored in columns k and k+1 of a.
00582          Int_t i;
00583          for (i = 0; i < k; i++)
00584             pcb[k*inc] -= pU[i*n+k]*pcb[i*inc];
00585          for (i = 0; i < k; i++)
00586             pcb[(k+1)*inc] -= pU[i*n+k+1]*pcb[i*inc];
00587 
00588          // interchange elements k and -ipiv(k).
00589          const Int_t kp = -fIpiv[k]-1;
00590          if (kp != k) {
00591             const Double_t tmp = pcb[k*inc];
00592             pcb[k*inc]  = pcb[kp*inc];
00593             pcb[kp*inc] = tmp;
00594          }
00595          k += 2;
00596       }
00597    }
00598 
00599    return kTRUE;
00600 }
00601 
00602 //______________________________________________________________________________
00603 Bool_t TDecompBK::Invert(TMatrixDSym &inv)
00604 {
00605 // For a symmetric matrix A(m,m), its inverse A_inv(m,m) is returned .
00606 
00607    if (inv.GetNrows() != GetNrows() || inv.GetRowLwb() != GetRowLwb()) {
00608       Error("Invert(TMatrixDSym &","Input matrix has wrong shape");
00609       return kFALSE;
00610    }
00611 
00612    inv.UnitMatrix();
00613 
00614    const Int_t colLwb = inv.GetColLwb();
00615    const Int_t colUpb = inv.GetColUpb();
00616    Bool_t status = kTRUE;
00617    for (Int_t icol = colLwb; icol <= colUpb && status; icol++) {
00618       TMatrixDColumn b(inv,icol);
00619       status &= Solve(b);
00620    }
00621 
00622    return status;
00623 }
00624 
00625 //______________________________________________________________________________
00626 TMatrixDSym TDecompBK::Invert(Bool_t &status)
00627 {
00628 // For a symmetric matrix A(m,m), its inverse A_inv(m,m) is returned .
00629 
00630    const Int_t rowLwb = GetRowLwb();
00631    const Int_t rowUpb = rowLwb+GetNrows()-1;
00632 
00633    TMatrixDSym inv(rowLwb,rowUpb);
00634    inv.UnitMatrix();
00635    status = Invert(inv);
00636 
00637    return inv;
00638 }
00639 
00640 //______________________________________________________________________________
00641 void TDecompBK::Print(Option_t *opt) const
00642 {
00643 // Print the class members
00644 
00645    TDecompBase::Print(opt);
00646    printf("fIpiv:\n");
00647    for (Int_t i = 0; i < fNIpiv; i++)
00648       printf("[%d] = %d\n",i,fIpiv[i]);
00649    fU.Print("fU");
00650 }
00651 
00652 //______________________________________________________________________________
00653 TDecompBK &TDecompBK::operator=(const TDecompBK &source)
00654 {
00655 // Assigment operator
00656 
00657    if (this != &source) {
00658       TDecompBase::operator=(source);
00659       fU.ResizeTo(source.fU);
00660       fU   = source.fU;
00661       if (fNIpiv != source.fNIpiv) {
00662          if (fIpiv)
00663             delete [] fIpiv;
00664          fNIpiv = source.fNIpiv;
00665          fIpiv = new Int_t[fNIpiv];
00666       }
00667       if (fIpiv) memcpy(fIpiv,source.fIpiv,fNIpiv*sizeof(Int_t));
00668    }
00669    return *this;
00670 }

Generated on Tue Jul 5 14:36:26 2011 for ROOT_528-00b_version by  doxygen 1.5.1