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 }