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 }