00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #include "TDecompQRH.h"
00038 
00039 ClassImp(TDecompQRH)
00040 
00041 
00042 TDecompQRH::TDecompQRH(Int_t nrows,Int_t ncols)
00043 {
00044 
00045 
00046    if (nrows < ncols) {
00047       Error("TDecompQRH(Int_t,Int_t","matrix rows should be >= columns");
00048       return;
00049    }
00050 
00051    fQ.ResizeTo(nrows,ncols);
00052    fR.ResizeTo(ncols,ncols);
00053    if (nrows <= ncols) {
00054       fW.ResizeTo(nrows);
00055       fUp.ResizeTo(nrows);
00056    } else {
00057       fW.ResizeTo(ncols);
00058       fUp.ResizeTo(ncols);
00059    }
00060 }
00061 
00062 
00063 TDecompQRH::TDecompQRH(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb)
00064 {
00065 
00066 
00067    const Int_t nrows = row_upb-row_lwb+1;
00068    const Int_t ncols = col_upb-col_lwb+1;
00069 
00070    if (nrows < ncols) {
00071       Error("TDecompQRH(Int_t,Int_t,Int_t,Int_t","matrix rows should be >= columns");
00072       return;
00073    }
00074 
00075    fRowLwb = row_lwb;
00076    fColLwb = col_lwb;
00077 
00078    fQ.ResizeTo(nrows,ncols);
00079    fR.ResizeTo(ncols,ncols);
00080    if (nrows <= ncols) {
00081       fW.ResizeTo(nrows);
00082       fUp.ResizeTo(nrows);
00083    } else {
00084       fW.ResizeTo(ncols);
00085       fUp.ResizeTo(ncols);
00086    }
00087 }
00088 
00089 
00090 TDecompQRH::TDecompQRH(const TMatrixD &a,Double_t tol)
00091 {
00092 
00093 
00094    R__ASSERT(a.IsValid());
00095    if (a.GetNrows() < a.GetNcols()) {
00096       Error("TDecompQRH(const TMatrixD &","matrix rows should be >= columns");
00097       return;
00098    }
00099 
00100    SetBit(kMatrixSet);
00101    fCondition = a.Norm1();
00102    fTol = a.GetTol();
00103    if (tol > 0.0)
00104       fTol = tol;
00105 
00106    fRowLwb = a.GetRowLwb();
00107    fColLwb = a.GetColLwb();
00108    const Int_t nRow = a.GetNrows();
00109    const Int_t nCol = a.GetNcols();
00110 
00111    fQ.ResizeTo(nRow,nCol);
00112    memcpy(fQ.GetMatrixArray(),a.GetMatrixArray(),nRow*nCol*sizeof(Double_t));
00113    fR.ResizeTo(nCol,nCol);
00114    if (nRow <= nCol) {
00115       fW.ResizeTo(nRow);
00116       fUp.ResizeTo(nRow);
00117    } else {
00118       fW.ResizeTo(nCol);
00119       fUp.ResizeTo(nCol);
00120    }
00121 }
00122 
00123 
00124 TDecompQRH::TDecompQRH(const TDecompQRH &another) : TDecompBase(another)
00125 {
00126 
00127 
00128    *this = another;
00129 }
00130 
00131 
00132 Bool_t TDecompQRH::Decompose()
00133 {
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141    if (TestBit(kDecomposed)) return kTRUE;
00142 
00143    if ( !TestBit(kMatrixSet) ) {
00144       Error("Decompose()","Matrix has not been set");
00145       return kFALSE;
00146    }
00147 
00148    const Int_t nRow   = this->GetNrows();
00149    const Int_t nCol   = this->GetNcols();
00150    const Int_t rowLwb = this->GetRowLwb();
00151    const Int_t colLwb = this->GetColLwb();
00152 
00153    TVectorD diagR;
00154    Double_t work[kWorkMax];
00155    if (nCol > kWorkMax) diagR.ResizeTo(nCol);
00156    else                 diagR.Use(nCol,work);
00157 
00158    if (QRH(fQ,diagR,fUp,fW,fTol)) {
00159       for (Int_t i = 0; i < nRow; i++) {
00160          const Int_t ic = (i < nCol) ? i : nCol;
00161          for (Int_t j = ic ; j < nCol; j++)
00162             fR(i,j) = fQ(i,j);
00163       }
00164       TMatrixDDiag diag(fR); diag = diagR;
00165 
00166       fQ.Shift(rowLwb,0);
00167       fR.Shift(0,colLwb);
00168 
00169       SetBit(kDecomposed);
00170    }
00171 
00172    return kTRUE;
00173 }
00174 
00175 
00176 Bool_t TDecompQRH::QRH(TMatrixD &q,TVectorD &diagR,TVectorD &up,TVectorD &w,Double_t tol)
00177 {
00178 
00179 
00180    const Int_t nRow = q.GetNrows();
00181    const Int_t nCol = q.GetNcols();
00182 
00183    const Int_t n = (nRow <= nCol) ? nRow-1 : nCol;
00184 
00185    for (Int_t k = 0 ; k < n ; k++) {
00186       const TVectorD qc_k = TMatrixDColumn_const(q,k);
00187       if (!DefHouseHolder(qc_k,k,k+1,up(k),w(k),tol))
00188          return kFALSE;
00189       diagR(k) = qc_k(k)-up(k);
00190       if (k < nCol-1) {
00191          
00192          for (Int_t j = k+1; j < nCol; j++) {
00193             TMatrixDColumn qc_j = TMatrixDColumn(q,j);
00194             ApplyHouseHolder(qc_k,up(k),w(k),k,k+1,qc_j);
00195          }
00196       }
00197    }
00198 
00199    if (nRow <= nCol) {
00200       diagR(nRow-1) = q(nRow-1,nRow-1);
00201       up(nRow-1) = 0;
00202       w(nRow-1)  = 0;
00203    }
00204 
00205    return kTRUE;
00206 }
00207 
00208 
00209 void TDecompQRH::SetMatrix(const TMatrixD &a)
00210 {
00211 
00212 
00213    R__ASSERT(a.IsValid());
00214 
00215    ResetStatus();
00216    if (a.GetNrows() < a.GetNcols()) {
00217       Error("TDecompQRH(const TMatrixD &","matrix rows should be >= columns");
00218       return;
00219    }
00220 
00221    SetBit(kMatrixSet);
00222    fCondition = a.Norm1();
00223 
00224    fRowLwb = a.GetRowLwb();
00225    fColLwb = a.GetColLwb();
00226    const Int_t nRow = a.GetNrows();
00227    const Int_t nCol = a.GetNcols();
00228 
00229    fQ.ResizeTo(nRow,nCol);
00230    memcpy(fQ.GetMatrixArray(),a.GetMatrixArray(),nRow*nCol*sizeof(Double_t));
00231    fR.ResizeTo(nCol,nCol);
00232    if (nRow <= nCol) {
00233       fW.ResizeTo(nRow);
00234       fUp.ResizeTo(nRow);
00235    } else {
00236       fW.ResizeTo(nCol);
00237       fUp.ResizeTo(nCol);
00238    }
00239 }
00240 
00241 
00242 Bool_t TDecompQRH::Solve(TVectorD &b)
00243 {
00244 
00245 
00246 
00247    R__ASSERT(b.IsValid());
00248    if (TestBit(kSingular)) {
00249       Error("Solve()","Matrix is singular");
00250       return kFALSE;
00251    }
00252    if ( !TestBit(kDecomposed) ) {
00253       if (!Decompose()) {
00254          Error("Solve()","Decomposition failed");
00255          return kFALSE;
00256       }
00257    }
00258 
00259    if (fQ.GetNrows() != b.GetNrows() || fQ.GetRowLwb() != b.GetLwb()) {
00260       Error("Solve(TVectorD &","vector and matrix incompatible");
00261       return kFALSE;
00262    }
00263 
00264    const Int_t nQRow = fQ.GetNrows();
00265    const Int_t nQCol = fQ.GetNcols();
00266 
00267    
00268    const Int_t nQ = (nQRow <= nQCol) ? nQRow-1 : nQCol;
00269    for (Int_t k = 0; k < nQ; k++) {
00270       const TVectorD qc_k = TMatrixDColumn_const(fQ,k);
00271       ApplyHouseHolder(qc_k,fUp(k),fW(k),k,k+1,b);
00272    }
00273 
00274    const Int_t nRCol = fR.GetNcols();
00275 
00276    const Double_t *pR = fR.GetMatrixArray();
00277          Double_t *pb = b.GetMatrixArray();
00278 
00279    
00280    for (Int_t i = nRCol-1; i >= 0; i--) {
00281       const Int_t off_i = i*nRCol;
00282       Double_t r = pb[i];
00283       for (Int_t j = i+1; j < nRCol; j++)
00284          r -= pR[off_i+j]*pb[j];
00285       if (TMath::Abs(pR[off_i+i]) < fTol)
00286       {
00287          Error("Solve(TVectorD &)","R[%d,%d]=%.4e < %.4e",i,i,pR[off_i+i],fTol);
00288          return kFALSE;
00289       }
00290       pb[i] = r/pR[off_i+i];
00291    }
00292 
00293    return kTRUE;
00294 }
00295 
00296 
00297 Bool_t TDecompQRH::Solve(TMatrixDColumn &cb)
00298 {
00299 
00300 
00301 
00302    TMatrixDBase *b = const_cast<TMatrixDBase *>(cb.GetMatrix());
00303    R__ASSERT(b->IsValid());
00304    if (TestBit(kSingular)) {
00305       Error("Solve()","Matrix is singular");
00306       return kFALSE;
00307    }
00308    if ( !TestBit(kDecomposed) ) {
00309       if (!Decompose()) {
00310          Error("Solve()","Decomposition failed");
00311          return kFALSE;
00312       }
00313    }
00314 
00315    if (fQ.GetNrows() != b->GetNrows() || fQ.GetRowLwb() != b->GetRowLwb())
00316    {
00317       Error("Solve(TMatrixDColumn &","vector and matrix incompatible");
00318       return kFALSE;
00319    }
00320 
00321    const Int_t nQRow = fQ.GetNrows();
00322    const Int_t nQCol = fQ.GetNcols();
00323 
00324    
00325    const Int_t nQ = (nQRow <= nQCol) ? nQRow-1 : nQCol;
00326    for (Int_t k = 0; k < nQ; k++) {
00327       const TVectorD qc_k = TMatrixDColumn_const(fQ,k);
00328       ApplyHouseHolder(qc_k,fUp(k),fW(k),k,k+1,cb);
00329    }
00330 
00331    const Int_t nRCol = fR.GetNcols();
00332 
00333    const Double_t *pR  = fR.GetMatrixArray();
00334          Double_t *pcb = cb.GetPtr();
00335    const Int_t     inc = cb.GetInc();
00336 
00337    
00338    for (Int_t i = nRCol-1; i >= 0; i--) {
00339       const Int_t off_i  = i*nRCol;
00340       const Int_t off_i2 = i*inc;
00341       Double_t r = pcb[off_i2];
00342       for (Int_t j = i+1; j < nRCol; j++)
00343          r -= pR[off_i+j]*pcb[j*inc];
00344       if (TMath::Abs(pR[off_i+i]) < fTol)
00345       {
00346          Error("Solve(TMatrixDColumn &)","R[%d,%d]=%.4e < %.4e",i,i,pR[off_i+i],fTol);
00347          return kFALSE;
00348       }
00349       pcb[off_i2] = r/pR[off_i+i];
00350    }
00351 
00352    return kTRUE;
00353 }
00354 
00355 
00356 Bool_t TDecompQRH::TransSolve(TVectorD &b)
00357 {
00358 
00359 
00360 
00361    R__ASSERT(b.IsValid());
00362    if (TestBit(kSingular)) {
00363       Error("TransSolve()","Matrix is singular");
00364       return kFALSE;
00365    }
00366    if ( !TestBit(kDecomposed) ) {
00367       if (!Decompose()) {
00368          Error("TransSolve()","Decomposition failed");
00369          return kFALSE;
00370       }
00371    }
00372 
00373    if (fQ.GetNrows() != fQ.GetNcols() || fQ.GetRowLwb() != fQ.GetColLwb()) {
00374       Error("TransSolve(TVectorD &","matrix should be square");
00375       return kFALSE;
00376    }
00377 
00378    if (fR.GetNrows() != b.GetNrows() || fR.GetRowLwb() != b.GetLwb()) {
00379       Error("TransSolve(TVectorD &","vector and matrix incompatible");
00380       return kFALSE;
00381    }
00382 
00383    const Double_t *pR = fR.GetMatrixArray();
00384          Double_t *pb = b.GetMatrixArray();
00385 
00386    const Int_t nRCol = fR.GetNcols();
00387 
00388    
00389    for (Int_t i = 0; i < nRCol; i++) {
00390       const Int_t off_i = i*nRCol;
00391       Double_t r = pb[i];
00392       for (Int_t j = 0; j < i; j++) {
00393          const Int_t off_j = j*nRCol;
00394          r -= pR[off_j+i]*pb[j];
00395       }
00396       if (TMath::Abs(pR[off_i+i]) < fTol)
00397       {
00398          Error("TransSolve(TVectorD &)","R[%d,%d]=%.4e < %.4e",i,i,pR[off_i+i],fTol);
00399          return kFALSE;
00400       }
00401       pb[i] = r/pR[off_i+i];
00402    }
00403 
00404    const Int_t nQRow = fQ.GetNrows();
00405 
00406    
00407    for (Int_t k = nQRow-1; k >= 0; k--) {
00408       const TVectorD qc_k = TMatrixDColumn_const(fQ,k);
00409       ApplyHouseHolder(qc_k,fUp(k),fW(k),k,k+1,b);
00410    }
00411 
00412    return kTRUE;
00413 }
00414 
00415 
00416 Bool_t TDecompQRH::TransSolve(TMatrixDColumn &cb)
00417 {
00418 
00419 
00420 
00421    TMatrixDBase *b = const_cast<TMatrixDBase *>(cb.GetMatrix());
00422    R__ASSERT(b->IsValid());
00423    if (TestBit(kSingular)) {
00424       Error("TransSolve()","Matrix is singular");
00425       return kFALSE;
00426    }
00427    if ( !TestBit(kDecomposed) ) {
00428       if (!Decompose()) {
00429          Error("TransSolve()","Decomposition failed");
00430          return kFALSE;
00431       }
00432    }
00433 
00434    if (fQ.GetNrows() != fQ.GetNcols() || fQ.GetRowLwb() != fQ.GetColLwb()) {
00435       Error("TransSolve(TMatrixDColumn &","matrix should be square");
00436       return kFALSE;
00437    }
00438 
00439    if (fR.GetNrows() != b->GetNrows() || fR.GetRowLwb() != b->GetRowLwb()) {
00440       Error("TransSolve(TMatrixDColumn &","vector and matrix incompatible");
00441       return kFALSE;
00442    }
00443 
00444    const Double_t *pR  = fR.GetMatrixArray();
00445          Double_t *pcb = cb.GetPtr();
00446    const Int_t     inc = cb.GetInc();
00447 
00448    const Int_t nRCol = fR.GetNcols();
00449 
00450    
00451    for (Int_t i = 0; i < nRCol; i++) {
00452       const Int_t off_i  = i*nRCol;
00453       const Int_t off_i2 = i*inc;
00454       Double_t r = pcb[off_i2];
00455       for (Int_t j = 0; j < i; j++) {
00456          const Int_t off_j = j*nRCol;
00457          r -= pR[off_j+i]*pcb[j*inc];
00458       }
00459       if (TMath::Abs(pR[off_i+i]) < fTol)
00460       {
00461          Error("TransSolve(TMatrixDColumn &)","R[%d,%d]=%.4e < %.4e",i,i,pR[off_i+i],fTol);
00462          return kFALSE;
00463       }
00464       pcb[off_i2] = r/pR[off_i+i];
00465    }
00466 
00467    const Int_t nQRow = fQ.GetNrows();
00468 
00469    
00470    for (Int_t k = nQRow-1; k >= 0; k--) {
00471       const TVectorD qc_k = TMatrixDColumn_const(fQ,k);
00472       ApplyHouseHolder(qc_k,fUp(k),fW(k),k,k+1,cb);
00473    }
00474 
00475    return kTRUE;
00476 }
00477 
00478 
00479 void TDecompQRH::Det(Double_t &d1,Double_t &d2)
00480 {
00481 
00482 
00483 
00484    if ( !TestBit(kDetermined) ) {
00485       if ( !TestBit(kDecomposed) )
00486         Decompose();
00487       if (TestBit(kSingular)) {
00488          fDet1 = 0.0;
00489          fDet2 = 0.0;
00490       } else
00491          TDecompBase::Det(d1,d2);
00492       SetBit(kDetermined);
00493    }
00494    d1 = fDet1;
00495    d2 = fDet2;
00496 }
00497 
00498 
00499 Bool_t TDecompQRH::Invert(TMatrixD &inv)
00500 {
00501 
00502 
00503 
00504 
00505 
00506    if (inv.GetNrows()  != GetNrows()  || inv.GetNcols()  != GetNrows() ||
00507        inv.GetRowLwb() != GetRowLwb() || inv.GetColLwb() != GetColLwb()) {
00508       Error("Invert(TMatrixD &","Input matrix has wrong shape");
00509       return kFALSE;
00510    }
00511 
00512    inv.UnitMatrix();
00513    const Bool_t status = MultiSolve(inv);
00514 
00515    return status;
00516 }
00517 
00518 
00519 TMatrixD TDecompQRH::Invert(Bool_t &status)
00520 {
00521 
00522 
00523 
00524    const Int_t rowLwb = GetRowLwb();
00525    const Int_t colLwb = GetColLwb();
00526    const Int_t rowUpb = rowLwb+GetNrows()-1;
00527    TMatrixD inv(rowLwb,rowUpb,colLwb,colLwb+GetNrows()-1);
00528    inv.UnitMatrix();
00529    status = MultiSolve(inv);
00530    inv.ResizeTo(rowLwb,rowLwb+GetNcols()-1,colLwb,colLwb+GetNrows()-1);
00531 
00532    return inv;
00533 }
00534 
00535 
00536 void TDecompQRH::Print(Option_t *opt) const
00537 {
00538 
00539 
00540    TDecompBase::Print(opt);
00541    fQ.Print("fQ");
00542    fR.Print("fR");
00543    fUp.Print("fUp");
00544    fW.Print("fW");
00545 }
00546 
00547 
00548 TDecompQRH &TDecompQRH::operator=(const TDecompQRH &source)
00549 {
00550 
00551 
00552    if (this != &source) {
00553       TDecompBase::operator=(source);
00554       fQ.ResizeTo(source.fQ);
00555       fR.ResizeTo(source.fR);
00556       fUp.ResizeTo(source.fUp);
00557       fW.ResizeTo(source.fW);
00558       fQ  = source.fQ;
00559       fR  = source.fR;
00560       fUp = source.fUp;
00561       fW  = source.fW;
00562    }
00563    return *this;
00564 }