45 TDecompLU::TDecompLU()
56 TDecompLU::TDecompLU(Int_t nrows)
60 fIndex =
new Int_t[fNIndex];
61 memset(fIndex,0,fNIndex*
sizeof(Int_t));
63 fLU.ResizeTo(nrows,nrows);
69 TDecompLU::TDecompLU(Int_t row_lwb,Int_t row_upb)
71 const Int_t nrows = row_upb-row_lwb+1;
74 fIndex =
new Int_t[fNIndex];
75 memset(fIndex,0,fNIndex*
sizeof(Int_t));
79 fLU.ResizeTo(row_lwb,row_lwb+nrows-1,row_lwb,row_lwb+nrows-1);
85 TDecompLU::TDecompLU(
const TMatrixD &a,Double_t tol,Int_t implicit)
87 R__ASSERT(a.IsValid());
89 if (a.GetNrows() != a.GetNcols() || a.GetRowLwb() != a.GetColLwb()) {
90 Error(
"TDecompLU(const TMatrixD &",
"matrix should be square");
95 fCondition = a.Norm1();
96 fImplicitPivot = implicit;
102 fNIndex = a.GetNcols();
103 fIndex =
new Int_t[fNIndex];
104 memset(fIndex,0,fNIndex*
sizeof(Int_t));
106 fRowLwb = a.GetRowLwb();
107 fColLwb = a.GetColLwb();
115 TDecompLU::TDecompLU(
const TDecompLU &another) : TDecompBase(another)
126 Bool_t TDecompLU::Decompose()
128 if (TestBit(kDecomposed))
return kTRUE;
130 if ( !TestBit(kMatrixSet) ) {
131 Error(
"Decompose()",
"Matrix has not been set");
138 ok = DecomposeLUCrout(fLU,fIndex,fSign,fTol,nrZeros);
140 ok = DecomposeLUGauss(fLU,fIndex,fSign,fTol,nrZeros);
142 if (!ok) SetBit(kSingular);
143 else SetBit(kDecomposed);
151 const TMatrixD TDecompLU::GetMatrix()
153 if (TestBit(kSingular)) {
154 Error(
"GetMatrix()",
"Matrix is singular");
157 if ( !TestBit(kDecomposed) ) {
159 Error(
"GetMatrix()",
"Decomposition failed");
166 Double_t *
const pU = mU.GetMatrixArray();
167 Double_t *
const pL = mL.GetMatrixArray();
168 const Int_t n = fLU.GetNcols();
169 for (Int_t irow = 0; irow < n; irow++) {
170 const Int_t off_row = irow*n;
171 for (Int_t icol = 0; icol < n; icol++) {
172 if (icol > irow) pL[off_row+icol] = 0.;
173 else if (icol < irow) pU[off_row+icol] = 0.;
174 else pL[off_row+icol] = 1.;
182 Double_t *
const pA = a.GetMatrixArray();
183 for (Int_t i = n-1; i >= 0; i--) {
184 const Int_t j = fIndex[i];
186 const Int_t off_j = j*n;
187 const Int_t off_i = i*n;
188 for (Int_t k = 0; k < n; k++) {
189 const Double_t tmp = pA[off_j+k];
190 pA[off_j+k] = pA[off_i+k];
202 void TDecompLU::SetMatrix(
const TMatrixD &a)
204 R__ASSERT(a.IsValid());
207 if (a.GetNrows() != a.GetNcols() || a.GetRowLwb() != a.GetColLwb()) {
208 Error(
"TDecompLU(const TMatrixD &",
"matrix should be square");
213 fCondition = a.Norm1();
216 if (fNIndex != a.GetNcols()) {
217 fNIndex = a.GetNcols();
219 fIndex =
new Int_t[fNIndex];
220 memset(fIndex,0,fNIndex*
sizeof(Int_t));
223 fRowLwb = a.GetRowLwb();
224 fColLwb = a.GetColLwb();
233 Bool_t TDecompLU::Solve(TVectorD &b)
235 R__ASSERT(b.IsValid());
236 if (TestBit(kSingular)) {
237 Error(
"Solve()",
"Matrix is singular");
240 if ( !TestBit(kDecomposed) ) {
242 Error(
"Solve()",
"Decomposition failed");
247 if (fLU.GetNrows() != b.GetNrows() || fLU.GetRowLwb() != b.GetLwb()) {
248 Error(
"Solve(TVectorD &",
"vector and matrix incompatible");
252 const Int_t n = fLU.GetNrows();
254 const Double_t *pLU = fLU.GetMatrixArray();
255 Double_t *pb = b.GetMatrixArray();
260 for (i = 0; i < n ; i++) {
261 const Int_t off_i = i*n;
262 if (TMath::Abs(pLU[off_i+i]) < fTol) {
263 Error(
"Solve(TVectorD &b)",
"LU[%d,%d]=%.4e < %.4e",i,i,pLU[off_i+i],fTol);
270 for (i = 0; i < n; i++) {
271 const Int_t off_i = i*n;
272 const Int_t iperm = fIndex[i];
273 Double_t r = pb[iperm];
276 for (Int_t j = nonzero; j < i; j++)
277 r -= pLU[off_i+j]*pb[j];
284 for (i = n-1; i >= 0; i--) {
285 const Int_t off_i = i*n;
287 for (Int_t j = i+1; j < n; j++)
288 r -= pLU[off_i+j]*pb[j];
289 pb[i] = r/pLU[off_i+i];
299 Bool_t TDecompLU::Solve(TMatrixDColumn &cb)
301 TMatrixDBase *b =
const_cast<TMatrixDBase *
>(cb.GetMatrix());
302 R__ASSERT(b->IsValid());
303 if (TestBit(kSingular)) {
304 Error(
"Solve()",
"Matrix is singular");
307 if ( !TestBit(kDecomposed) ) {
309 Error(
"Solve()",
"Decomposition failed");
314 if (fLU.GetNrows() != b->GetNrows() || fLU.GetRowLwb() != b->GetRowLwb()) {
315 Error(
"Solve(TMatrixDColumn &",
"vector and matrix incompatible");
319 const Int_t n = fLU.GetNrows();
320 const Double_t *pLU = fLU.GetMatrixArray();
325 for (i = 0; i < n ; i++) {
326 const Int_t off_i = i*n;
327 if (TMath::Abs(pLU[off_i+i]) < fTol) {
328 Error(
"Solve(TMatrixDColumn &cb)",
"LU[%d,%d]=%.4e < %.4e",i,i,pLU[off_i+i],fTol);
333 Double_t *pcb = cb.GetPtr();
334 const Int_t inc = cb.GetInc();
338 for (i = 0; i < n; i++) {
339 const Int_t off_i = i*n;
340 const Int_t off_i2 = i*inc;
341 const Int_t iperm = fIndex[i];
342 const Int_t off_iperm = iperm*inc;
343 Double_t r = pcb[off_iperm];
344 pcb[off_iperm] = pcb[off_i2];
346 for (Int_t j = nonzero; j <= i-1; j++)
347 r -= pLU[off_i+j]*pcb[j*inc];
354 for (i = n-1; i >= 0; i--) {
355 const Int_t off_i = i*n;
356 const Int_t off_i2 = i*inc;
357 Double_t r = pcb[off_i2];
358 for (Int_t j = i+1; j < n; j++)
359 r -= pLU[off_i+j]*pcb[j*inc];
360 pcb[off_i2] = r/pLU[off_i+i];
371 Bool_t TDecompLU::TransSolve(TVectorD &b)
373 R__ASSERT(b.IsValid());
374 if (TestBit(kSingular)) {
375 Error(
"TransSolve()",
"Matrix is singular");
378 if ( !TestBit(kDecomposed) ) {
380 Error(
"TransSolve()",
"Decomposition failed");
385 if (fLU.GetNrows() != b.GetNrows() || fLU.GetRowLwb() != b.GetLwb()) {
386 Error(
"TransSolve(TVectorD &",
"vector and matrix incompatible");
390 const Int_t n = fLU.GetNrows();
392 const Double_t *pLU = fLU.GetMatrixArray();
393 Double_t *pb = b.GetMatrixArray();
398 for (i = 0; i < n ; i++) {
399 const Int_t off_i = i*n;
400 if (TMath::Abs(pLU[off_i+i]) < fTol) {
401 Error(
"TransSolve(TVectorD &b)",
"LU[%d,%d]=%.4e < %.4e",i,i,pLU[off_i+i],fTol);
407 for (i = 0; i < n; i++) {
408 const Int_t off_i = i*n;
410 for (Int_t j = 0; j < i ; j++) {
411 const Int_t off_j = j*n;
412 r -= pLU[off_j+i]*pb[j];
414 pb[i] = r/pLU[off_i+i];
419 for (i = n-1 ; i >= 0; i--) {
422 for (Int_t j = i+1; j <= nonzero; j++) {
423 const Int_t off_j = j*n;
424 r -= pLU[off_j+i]*pb[j];
428 const Int_t iperm = fIndex[i];
440 Bool_t TDecompLU::TransSolve(TMatrixDColumn &cb)
442 TMatrixDBase *b =
const_cast<TMatrixDBase *
>(cb.GetMatrix());
443 R__ASSERT(b->IsValid());
444 if (TestBit(kSingular)) {
445 Error(
"TransSolve()",
"Matrix is singular");
448 if ( !TestBit(kDecomposed) ) {
450 Error(
"TransSolve()",
"Decomposition failed");
455 if (fLU.GetNrows() != b->GetNrows() || fLU.GetRowLwb() != b->GetRowLwb()) {
456 Error(
"TransSolve(TMatrixDColumn &",
"vector and matrix incompatible");
460 const Int_t n = fLU.GetNrows();
461 const Int_t lwb = fLU.GetRowLwb();
463 const Double_t *pLU = fLU.GetMatrixArray();
468 for (i = 0; i < n ; i++) {
469 const Int_t off_i = i*n;
470 if (TMath::Abs(pLU[off_i+i]) < fTol) {
471 Error(
"TransSolve(TMatrixDColumn &cb)",
"LU[%d,%d]=%.4e < %.4e",i,i,pLU[off_i+i],fTol);
477 for (i = 0; i < n; i++) {
478 const Int_t off_i = i*n;
479 Double_t r = cb(i+lwb);
480 for (Int_t j = 0; j < i ; j++) {
481 const Int_t off_j = j*n;
482 r -= pLU[off_j+i]*cb(j+lwb);
484 cb(i+lwb) = r/pLU[off_i+i];
489 for (i = n-1 ; i >= 0; i--) {
490 Double_t r = cb(i+lwb);
492 for (Int_t j = i+1; j <= nonzero; j++) {
493 const Int_t off_j = j*n;
494 r -= pLU[off_j+i]*cb(j+lwb);
498 const Int_t iperm = fIndex[i];
499 cb(i+lwb) = cb(iperm+lwb);
509 void TDecompLU::Det(Double_t &d1,Double_t &d2)
511 if ( !TestBit(kDetermined) ) {
512 if ( !TestBit(kDecomposed) )
514 TDecompBase::Det(d1,d2);
526 Bool_t TDecompLU::Invert(TMatrixD &inv)
528 if (inv.GetNrows() != GetNrows() || inv.GetNcols() != GetNcols() ||
529 inv.GetRowLwb() != GetRowLwb() || inv.GetColLwb() != GetColLwb()) {
530 Error(
"Invert(TMatrixD &",
"Input matrix has wrong shape");
535 const Bool_t status = MultiSolve(inv);
544 TMatrixD TDecompLU::Invert(Bool_t &status)
546 const Int_t rowLwb = GetRowLwb();
547 const Int_t rowUpb = rowLwb+GetNrows()-1;
549 TMatrixD inv(rowLwb,rowUpb,rowLwb,rowUpb);
551 status = MultiSolve(inv);
559 void TDecompLU::Print(Option_t *opt)
const
561 TDecompBase::Print(opt);
562 printf(
"fImplicitPivot = %d\n",fImplicitPivot);
563 printf(
"fSign = %f\n",fSign);
565 for (Int_t i = 0; i < fNIndex; i++)
566 printf(
"[%d] = %d\n",i,fIndex[i]);
573 TDecompLU &TDecompLU::operator=(
const TDecompLU &source)
575 if (
this != &source) {
576 TDecompBase::operator=(source);
577 fLU.ResizeTo(source.fLU);
579 fSign = source.fSign;
580 fImplicitPivot = source.fImplicitPivot;
581 if (fNIndex != source.fNIndex) {
584 fNIndex = source.fNIndex;
585 fIndex =
new Int_t[fNIndex];
587 if (fIndex) memcpy(fIndex,source.fIndex,fNIndex*
sizeof(Int_t));
599 Bool_t TDecompLU::DecomposeLUCrout(TMatrixD &lu,Int_t *index,Double_t &sign,
600 Double_t tol,Int_t &nrZeros)
602 const Int_t n = lu.GetNcols();
603 Double_t *pLU = lu.GetMatrixArray();
605 Double_t work[kWorkMax];
606 Bool_t isAllocated = kFALSE;
607 Double_t *scale = work;
610 scale =
new Double_t[n];
616 for (Int_t i = 0; i < n ; i++) {
617 const Int_t off_i = i*n;
619 for (Int_t j = 0; j < n; j++) {
620 const Double_t tmp = TMath::Abs(pLU[off_i+j]);
624 scale[i] = (max == 0.0 ? 0.0 : 1.0/max);
627 for (Int_t j = 0; j < n; j++) {
628 const Int_t off_j = j*n;
630 for (Int_t i = 0; i < j; i++) {
631 const Int_t off_i = i*n;
632 Double_t r = pLU[off_i+j];
633 for (Int_t k = 0; k < i; k++) {
634 const Int_t off_k = k*n;
635 r -= pLU[off_i+k]*pLU[off_k+j];
647 for (Int_t i = j; i < n; i++) {
648 const Int_t off_i = i*n;
649 Double_t r = pLU[off_i+j];
650 for (Int_t k = 0; k < j; k++) {
651 const Int_t off_k = k*n;
652 r -= pLU[off_i+k]*pLU[off_k+j];
655 const Double_t tmp = scale[i]*TMath::Abs(r);
664 const Int_t off_imax = imax*n;
665 for (Int_t k = 0; k < n; k++ ) {
666 const Double_t tmp = pLU[off_imax+k];
667 pLU[off_imax+k] = pLU[off_j+k];
671 scale[imax] = scale[j];
676 if (pLU[off_j+j] != 0.0) {
677 if (TMath::Abs(pLU[off_j+j]) < tol)
680 const Double_t tmp = 1.0/pLU[off_j+j];
681 for (Int_t i = j+1; i < n; i++) {
682 const Int_t off_i = i*n;
687 ::Error(
"TDecompLU::DecomposeLUCrout",
"matrix is singular");
688 if (isAllocated)
delete [] scale;
708 Bool_t TDecompLU::DecomposeLUGauss(TMatrixD &lu,Int_t *index,Double_t &sign,
709 Double_t tol,Int_t &nrZeros)
711 const Int_t n = lu.GetNcols();
712 Double_t *pLU = lu.GetMatrixArray();
718 for (Int_t j = 0; j < n-1; j++) {
719 const Int_t off_j = j*n;
723 Double_t max = TMath::Abs(pLU[off_j+j]);
726 for (Int_t i = j+1; i < n; i++) {
727 const Int_t off_i = i*n;
728 const Double_t mLUij = TMath::Abs(pLU[off_i+j]);
737 const Int_t off_ipov = i_pivot*n;
738 for (Int_t k = 0; k < n; k++ ) {
739 const Double_t tmp = pLU[off_ipov+k];
740 pLU[off_ipov+k] = pLU[off_j+k];
747 const Double_t mLUjj = pLU[off_j+j];
750 if (TMath::Abs(mLUjj) < tol)
752 for (Int_t i = j+1; i < n; i++) {
753 const Int_t off_i = i*n;
754 const Double_t mLUij = pLU[off_i+j]/mLUjj;
755 pLU[off_i+j] = mLUij;
757 for (Int_t k = j+1; k < n; k++) {
758 const Double_t mLUik = pLU[off_i+k];
759 const Double_t mLUjk = pLU[off_j+k];
760 pLU[off_i+k] = mLUik-mLUij*mLUjk;
764 ::Error(
"TDecompLU::DecomposeLUGauss",
"matrix is singular");
775 Bool_t TDecompLU::InvertLU(TMatrixD &lu,Double_t tol,Double_t *det)
780 if (lu.GetNrows() != lu.GetNcols() || lu.GetRowLwb() != lu.GetColLwb()) {
781 ::Error(
"TDecompLU::InvertLU",
"matrix should be square");
785 const Int_t n = lu.GetNcols();
786 Double_t *pLU = lu.GetMatrixArray();
788 Int_t worki[kWorkMax];
789 Bool_t isAllocatedI = kFALSE;
790 Int_t *index = worki;
792 isAllocatedI = kTRUE;
793 index =
new Int_t[n];
798 if (!DecomposeLUCrout(lu,index,sign,tol,nrZeros) || nrZeros > 0) {
801 ::Error(
"TDecompLU::InvertLU",
"matrix is singular, %d diag elements < tolerance of %.4e",nrZeros,tol);
808 const TVectorD diagv = TMatrixDDiag_const(lu);
809 DiagProd(diagv,tol,d1,d2);
811 *det = d1*TMath::Power(2.0,d2);
818 for (j = 0; j < n; j++) {
819 const Int_t off_j = j*n;
821 pLU[off_j+j] = 1./pLU[off_j+j];
822 const Double_t mLU_jj = -pLU[off_j+j];
826 Double_t *pX = pLU+j;
828 for (k = 0; k <= j-1; k++) {
829 const Int_t off_k = k*n;
830 if ( pX[off_k] != 0.0 ) {
831 const Double_t tmp = pX[off_k];
832 for (Int_t i = 0; i <= k-1; i++) {
833 const Int_t off_i = i*n;
834 pX[off_i] += tmp*pLU[off_i+k];
836 pX[off_k] *= pLU[off_k+k];
839 for (k = 0; k <= j-1; k++) {
840 const Int_t off_k = k*n;
847 Double_t workd[kWorkMax];
848 Bool_t isAllocatedD = kFALSE;
849 Double_t *pWorkd = workd;
851 isAllocatedD = kTRUE;
852 pWorkd =
new Double_t[n];
855 for (j = n-1; j >= 0; j--) {
858 for (Int_t i = j+1; i < n; i++) {
859 const Int_t off_i = i*n;
860 pWorkd[i] = pLU[off_i+j];
867 const Double_t *mp = pLU+j+1;
868 Double_t *tp = pLU+j;
870 for (Int_t irow = 0; irow < n; irow++) {
872 const Double_t *sp = pWorkd+j+1;
873 for (Int_t icol = 0; icol < n-1-j ; icol++)
874 sum += *mp++ * *sp++;
886 for (j = n-1; j >= 0; j--) {
887 const Int_t jperm = index[j];
889 for (Int_t i = 0; i < n; i++) {
890 const Int_t off_i = i*n;
891 const Double_t tmp = pLU[off_i+jperm];
892 pLU[off_i+jperm] = pLU[off_i+j];