00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 #include "TDecompBK.h"
00013 #include "TMath.h"
00014 #include "TError.h"
00015 
00016 ClassImp(TDecompBK)
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 TDecompBK::TDecompBK()
00059 {
00060 
00061    fNIpiv = 0;
00062    fIpiv  = 0;
00063 }
00064 
00065 
00066 TDecompBK::TDecompBK(Int_t nrows)
00067 {
00068 
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 
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 
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 
00116 
00117    fNIpiv = 0;
00118    fIpiv  = 0;
00119    *this = another;
00120 }
00121 
00122 
00123 Bool_t TDecompBK::Decompose()
00124 {
00125 
00126 
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 
00138    const Double_t alpha = (1.+TMath::Sqrt(17.))/8.;
00139 
00140 
00141 
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       
00153       
00154 
00155       const Double_t absakk = TMath::Abs(diag(k));
00156 
00157       
00158       
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          
00173          kp = k;
00174          ok = kFALSE;
00175       } else {
00176          if (absakk >= alpha*colmax) {
00177            
00178             kp = k;
00179          } else {
00180             
00181             
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                
00195                kp = k;
00196             } else if( TMath::Abs(diag(imax)) >= alpha*rowmax) {
00197                
00198                kp = imax;
00199             } else {
00200                
00201                kp = imax;
00202                kstep = 2;
00203             }
00204          }
00205 
00206          const Int_t kk = k-kstep+1;
00207          if (kp != kk) {
00208             
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          
00240 
00241          if (kstep == 1 && k > 0) {
00242             
00243             
00244 
00245             
00246             
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             
00253             TMatrixDSub sub2(fU,0,k-1,k,k);
00254             sub2 *= r1;
00255          } else {
00256             
00257             
00258             
00259 
00260             
00261             
00262             
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          
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 
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 
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    
00360    
00361    
00362 
00363    Int_t k = n-1;
00364    while (k >= 0) {
00365 
00366       if (fIpiv[k] > 0) {
00367 
00368          
00369          
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          
00378          
00379          for (Int_t i = 0; i < k; i++)
00380             pb[i] -= pU[i*n+k]*pb[k];
00381 
00382          
00383          pb[k] /= diag(k);
00384          k--;
00385       } else {
00386 
00387          
00388          
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          
00397          
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          
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    
00419    
00420    
00421    
00422 
00423    k = 0;
00424    while (k < n) {
00425 
00426       if (fIpiv[k] > 0) {
00427          
00428          
00429          
00430          for (Int_t i = 0; i < k; i++)
00431             pb[k] -= pU[i*n+k]*pb[i];
00432 
00433          
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          
00443          
00444          
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          
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 
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   
00497   
00498   
00499 
00500    Int_t k = n-1;
00501    while (k >= 0) {
00502 
00503       if (fIpiv[k] > 0) {
00504 
00505          
00506          
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          
00515          
00516          for (Int_t i = 0; i < k; i++)
00517             pcb[i*inc] -= pU[i*n+k]*pcb[k*inc];
00518 
00519          
00520          pcb[k*inc] /= diag(k);
00521          k--;
00522       } else {
00523 
00524          
00525          
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          
00534          
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          
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    
00556    
00557    
00558    
00559 
00560    k = 0;
00561    while (k < n) {
00562 
00563       if (fIpiv[k] > 0) {
00564          
00565          
00566          
00567          for (Int_t i = 0; i < k; i++)
00568             pcb[k*inc] -= pU[i*n+k]*pcb[i*inc];
00569 
00570          
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          
00580          
00581          
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          
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 
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 
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 
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 
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 }