Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TDecompBK.cxx
Go to the documentation of this file.
1// @(#)root/matrix:$Id$
2// Authors: Fons Rademakers, Eddy Offermann Sep 2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TDecompBK.h"
13#include "TMath.h"
14#include "TError.h"
15
16
17/** \class TDecompBK
18 \ingroup Matrix
19
20 The Bunch-Kaufman diagonal pivoting method decomposes a real
21 symmetric matrix A using
22
23~~~
24 A = U*D*U^T
25~~~
26
27 where U is a product of permutation and unit upper triangular
28 matrices, U^T is the transpose of U, and D is symmetric and block
29 diagonal with 1-by-1 and 2-by-2 diagonal blocks.
30
31 U = P(n-1)*U(n-1)* ... *P(k)U(k)* ...,
32 i.e., U is a product of terms P(k)*U(k), where k decreases from n-1
33 to 0 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
34 and 2-by-2 diagonal blocks D(k). P(k) is a permutation matrix as
35 defined by IPIV(k), and U(k) is a unit upper triangular matrix, such
36 that if the diagonal block D(k) is of order s (s = 1 or 2), then
37
38~~~
39 ( I v 0 ) k-s
40 U(k) = ( 0 I 0 ) s
41 ( 0 0 I ) n-k
42 k-s s n-k
43~~~
44
45 If s = 1, D(k) overwrites A(k,k), and v overwrites A(0:k-1,k).
46 If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k),
47 and A(k,k), and v overwrites A(0:k-2,k-1:k).
48
49 fU contains on entry the symmetric matrix A of which only the upper
50 triangular part is referenced . On exit fU contains the block diagonal
51 matrix D and the multipliers used to obtain the factor U, see above .
52
53 fIpiv if dimension n contains details of the interchanges and the
54 the block structure of D . If (fIPiv(k) > 0, then rows and columns k
55 and fIPiv(k) were interchanged and D(k,k) is a 1-by-1 diagonal block.
56 If IPiv(k) = fIPiv(k-1) < 0, rows and columns k-1 and -IPiv(k) were
57 interchanged and D(k-1:k,k-1:k) is a 2-by-2 diagonal block.
58*/
59
60////////////////////////////////////////////////////////////////////////////////
61/// Default constructor
62
64{
65 fNIpiv = 0;
66 fIpiv = nullptr;
67}
68
69////////////////////////////////////////////////////////////////////////////////
70/// Constructor for (nrows x nrows) symmetric matrix
71
79
80////////////////////////////////////////////////////////////////////////////////
81/// Constructor for ([row_lwb..row_upb] x [row_lwb..row_upb]) symmetric matrix
82
92
93////////////////////////////////////////////////////////////////////////////////
94/// Constructor for symmetric matrix A
95
97{
98 R__ASSERT(a.IsValid());
99
101 fCondition = a.Norm1();
102 fTol = a.GetTol();
103 if (tol > 0)
104 fTol = tol;
105
106 fNIpiv = a.GetNcols();
107 fIpiv = new Int_t[fNIpiv];
108 memset(fIpiv,0,fNIpiv*sizeof(Int_t));
109
110 const Int_t nRows = a.GetNrows();
111 fColLwb = fRowLwb = a.GetRowLwb();
113 memcpy(fU.GetMatrixArray(),a.GetMatrixArray(),nRows*nRows*sizeof(Double_t));
114}
115
116////////////////////////////////////////////////////////////////////////////////
117/// Copy constructor
118
120{
121 fNIpiv = 0;
122 fIpiv = nullptr;
123 *this = another;
124}
125
126////////////////////////////////////////////////////////////////////////////////
127/// Matrix A is decomposed in components U and D so that A = U*D*U^T
128/// If the decomposition succeeds, bit kDecomposed is set , otherwise kSingular
129
131{
132 if (TestBit(kDecomposed)) return kTRUE;
133
134 if ( !TestBit(kMatrixSet) ) {
135 Error("Decompose()","Matrix has not been set");
136 return kFALSE;
137 }
138
139 Bool_t ok = kTRUE;
140
141// Initialize alpha for use in choosing pivot block size.
142 const Double_t alpha = (1.+TMath::Sqrt(17.))/8.;
143
144// Factorize a as u*d*u' using the upper triangle of a .
145// k is the main loop index, decreasing from n-1 to 0 in steps of 1 or 2
146
147 const Int_t n = fU.GetNcols();
150
151 Int_t imax = 0;
152 Int_t k = n-1;
153 while (k >= 0) {
154 Int_t kstep = 1;
155
156 // determine rows and columns to be interchanged and whether
157 // a 1-by-1 or 2-by-2 pivot block will be used
158
159 const Double_t absakk = TMath::Abs(diag(k));
160
161 // imax is the row-index of the largest off-diagonal element in
162 // column k, and colmax is its absolute value
163
165 if ( k > 0 ) {
167 vcol.Abs();
168 imax = TMath::LocMax(k,vcol.GetMatrixArray());
169 colmax = vcol[imax];
170 } else {
171 colmax = 0.;
172 }
173
174 Int_t kp;
175 if (TMath::Max(absakk,colmax) <= fTol) {
176 // the block diagonal matrix will be singular
177 kp = k;
178 ok = kFALSE;
179 } else {
180 if (absakk >= alpha*colmax) {
181 // no interchange, use 1-by-1 pivot block
182 kp = k;
183 } else {
184 // jmax is the column-index of the largest off-diagonal
185 // element in row imax, and rowmax is its absolute value
187 vrow.Abs();
188 Int_t jmax = imax+1+TMath::LocMax(k-imax,vrow.GetMatrixArray()+imax+1);
190 if (imax > 0) {
192 vcol.Abs();
193 jmax = TMath::LocMax(imax,vcol.GetMatrixArray());
195 }
196
197 if (absakk >= alpha*colmax*(colmax/rowmax)) {
198 // No interchange, use 1-by-1 pivot block
199 kp = k;
200 } else if( TMath::Abs(diag(imax)) >= alpha*rowmax) {
201 // Interchange rows and columns k and imax, use 1-by-1 pivot block
202 kp = imax;
203 } else {
204 // Interchange rows and columns k-1 and imax, use 2-by-2 pivot block
205 kp = imax;
206 kstep = 2;
207 }
208 }
209
210 const Int_t kk = k-kstep+1;
211 if (kp != kk) {
212 // Interchange rows and columns kk and kp in the leading submatrix a(0:k,0:k)
213 Double_t *c_kk = pU+kk;
214 Double_t *c_kp = pU+kp;
215 for (Int_t irow = 0; irow < kp; irow++) {
216 const Double_t t = *c_kk;
217 *c_kk = *c_kp;
218 *c_kp = t;
219 c_kk += n;
220 c_kp += n;
221 }
222
223 c_kk = pU+(kp+1)*n+kk;
224 Double_t *r_kp = pU+kp*n+kp+1;
225 for (Int_t icol = 0; icol < kk-kp-1; icol++) {
226 const Double_t t = *c_kk;
227 *c_kk = *r_kp;
228 *r_kp = t;
229 c_kk += n;
230 r_kp += 1;
231 }
232
233 Double_t t = diag(kk);
234 diag(kk) = diag(kp);
235 diag(kp) = t;
236 if (kstep == 2) {
237 t = pU[(k-1)*n+k];
238 pU[(k-1)*n+k] = pU[kp*n+k];
239 pU[kp*n+k] = t;
240 }
241 }
242
243 // Update the leading submatrix
244
245 if (kstep == 1 && k > 0) {
246 // 1-by-1 pivot block d(k): column k now holds w(k) = u(k)*d(k)
247 // where u(k) is the k-th column of u
248
249 // perform a rank-1 update of a(0:k-1,0:k-1) as
250 // a := a - u(k)*d(k)*u(k)' = a - w(k)*1/d(k)*w(k)'
251
252 const Double_t r1 = 1./diag(k);
253 TMatrixDSub sub1(fU,0,k-1,0,k-1);
254 sub1.Rank1Update(TMatrixDColumn_const(fU,k),-r1);
255
256 // store u(k) in column k
257 TMatrixDSub sub2(fU,0,k-1,k,k);
258 sub2 *= r1;
259 } else {
260 // 2-by-2 pivot block d(k): columns k and k-1 now hold
261 // ( w(k-1) w(k) ) = ( u(k-1) u(k) )*d(k)
262 // where u(k) and u(k-1) are the k-th and (k-1)-th columns of u
263
264 // perform a rank-2 update of a(0:k-2,0:k-2) as
265 // a := a - ( u(k-1) u(k) )*d(k)*( u(k-1) u(k) )'
266 // = a - ( w(k-1) w(k) )*inv(d(k))*( w(k-1) w(k) )'
267
268 if ( k > 1 ) {
269 Double_t *pU_k1 = pU+(k-1)*n;
270 Double_t d12 = pU_k1[k];
271 const Double_t d22 = pU_k1[k-1]/d12;
272 const Double_t d11 = diag(k)/d12;
273 const Double_t t = 1./(d11*d22-1.);
274 d12 = t/d12;
275
276 for (Int_t j = k-2; j >= 0; j--) {
277 Double_t *pU_j = pU+j*n;
278 const Double_t wkm1 = d12*(d11*pU_j[k-1]-pU_j[k]);
279 const Double_t wk = d12*(d22*pU_j[k]-pU_j[k-1]);
280 for (Int_t i = j; i >= 0; i--) {
281 Double_t *pU_i = pU+i*n;
282 pU_i[j] -= (pU_i[k]*wk+pU_i[k-1]*wkm1);
283 }
284 pU_j[k] = wk;
285 pU_j[k-1] = wkm1;
286 }
287 }
288 }
289
290 // Store details of the interchanges in fIpiv
291 if (kstep == 1) {
292 fIpiv[k] = (kp+1);
293 } else {
294 fIpiv[k] = -(kp+1);
295 fIpiv[k-1] = -(kp+1);
296 }
297 }
298
299 k -= kstep;
300 }
301
302 if (!ok) SetBit(kSingular);
303 else SetBit(kDecomposed);
304
306
307 return ok;
308}
309
310////////////////////////////////////////////////////////////////////////////////
311/// Set the matrix to be decomposed, decomposition status is reset.
312
314{
315 R__ASSERT(a.IsValid());
316
317 ResetStatus();
318
320 fCondition = a.Norm1();
321
322 if (fNIpiv != a.GetNcols()) {
323 fNIpiv = a.GetNcols();
324 delete [] fIpiv;
325 fIpiv = new Int_t[fNIpiv];
326 memset(fIpiv,0,fNIpiv*sizeof(Int_t));
327 }
328
329 const Int_t nRows = a.GetNrows();
330 fColLwb = fRowLwb = a.GetRowLwb();
332 memcpy(fU.GetMatrixArray(),a.GetMatrixArray(),nRows*nRows*sizeof(Double_t));
333}
334
335////////////////////////////////////////////////////////////////////////////////
336/// Solve Ax=b assuming the BK form of A is stored in fU . Solution returned in b.
337
339{
340 R__ASSERT(b.IsValid());
341 if (TestBit(kSingular)) {
342 Error("Solve()","Matrix is singular");
343 return kFALSE;
344 }
345 if ( !TestBit(kDecomposed) ) {
346 if (!Decompose()) {
347 Error("Solve()","Decomposition failed");
348 return kFALSE;
349 }
350 }
351
352 if (fU.GetNrows() != b.GetNrows() || fU.GetRowLwb() != b.GetLwb()) {
353 Error("Solve(TVectorD &","vector and matrix incompatible");
354 return kFALSE;
355 }
356
357 const Int_t n = fU.GetNrows();
358
360 const Double_t *pU = fU.GetMatrixArray();
361 Double_t *pb = b.GetMatrixArray();
362
363 // solve a*x = b, where a = u*d*u'. First solve u*d*x = b, overwriting b with x.
364 // k is the main loop index, decreasing from n-1 to 0 in steps of 1 or 2,
365 // depending on the size of the diagonal blocks.
366
367 Int_t k = n-1;
368 while (k >= 0) {
369
370 if (fIpiv[k] > 0) {
371
372 // 1 x 1 diagonal block
373 // interchange rows k and ipiv(k).
374 const Int_t kp = fIpiv[k]-1;
375 if (kp != k) {
376 const Double_t tmp = pb[k];
377 pb[k] = pb[kp];
378 pb[kp] = tmp;
379 }
380
381 // multiply by inv(u(k)), where u(k) is the transformation
382 // stored in column k of a.
383 for (Int_t i = 0; i < k; i++)
384 pb[i] -= pU[i*n+k]*pb[k];
385
386 // multiply by the inverse of the diagonal block.
387 pb[k] /= diag(k);
388 k--;
389 } else {
390
391 // 2 x 2 diagonal block
392 // interchange rows k-1 and -ipiv(k).
393 const Int_t kp = -fIpiv[k]-1;
394 if (kp != k-1) {
395 const Double_t tmp = pb[k-1];
396 pb[k-1] = pb[kp];
397 pb[kp] = tmp;
398 }
399
400 // multiply by inv(u(k)), where u(k) is the transformation
401 // stored in columns k-1 and k of a.
402 Int_t i;
403 for (i = 0; i < k-1; i++)
404 pb[i] -= pU[i*n+k]*pb[k];
405 for (i = 0; i < k-1; i++)
406 pb[i] -= pU[i*n+k-1]*pb[k-1];
407
408 // multiply by the inverse of the diagonal block.
409 const Double_t *pU_k1 = pU+(k-1)*n;
410 const Double_t ukm1k = pU_k1[k];
411 const Double_t ukm1 = pU_k1[k-1]/ukm1k;
412 const Double_t uk = diag(k)/ukm1k;
413 const Double_t denom = ukm1*uk-1.;
414 const Double_t bkm1 = pb[k-1]/ukm1k;
415 const Double_t bk = pb[k]/ukm1k;
416 pb[k-1] = (uk*bkm1-bk)/denom;
417 pb[k] = (ukm1*bk-bkm1)/denom;
418 k -= 2;
419 }
420 }
421
422 // Next solve u'*x = b, overwriting b with x.
423 //
424 // k is the main loop index, increasing from 0 to n-1 in steps of
425 // 1 or 2, depending on the size of the diagonal blocks.
426
427 k = 0;
428 while (k < n) {
429
430 if (fIpiv[k] > 0) {
431 // 1 x 1 diagonal block
432 // multiply by inv(u'(k)), where u(k) is the transformation
433 // stored in column k of a.
434 for (Int_t i = 0; i < k; i++)
435 pb[k] -= pU[i*n+k]*pb[i];
436
437 // interchange elements k and ipiv(k).
438 const Int_t kp = fIpiv[k]-1;
439 if (kp != k) {
440 const Double_t tmp = pb[k];
441 pb[k] = pb[kp];
442 pb[kp] = tmp;
443 }
444 k++;
445 } else {
446 // 2 x 2 diagonal block
447 // multiply by inv(u'(k+1)), where u(k+1) is the transformation
448 // stored in columns k and k+1 of a.
449 Int_t i ;
450 for (i = 0; i < k; i++)
451 pb[k] -= pU[i*n+k]*pb[i];
452 for (i = 0; i < k; i++)
453 pb[k+1] -= pU[i*n+k+1]*pb[i];
454
455 // interchange elements k and -ipiv(k).
456 const Int_t kp = -fIpiv[k]-1;
457 if (kp != k) {
458 const Double_t tmp = pb[k];
459 pb[k] = pb[kp];
460 pb[kp] = tmp;
461 }
462 k += 2;
463 }
464 }
465
466 return kTRUE;
467}
468
469////////////////////////////////////////////////////////////////////////////////
470/// Solve Ax=b assuming the BK form of A is stored in fU . Solution returned in b.
471
473{
474 TMatrixDBase *b = const_cast<TMatrixDBase *>(cb.GetMatrix());
475 R__ASSERT(b->IsValid());
476 if (TestBit(kSingular)) {
477 Error("Solve()","Matrix is singular");
478 return kFALSE;
479 }
480 if ( !TestBit(kDecomposed) ) {
481 if (!Decompose()) {
482 Error("Solve()","Decomposition failed");
483 return kFALSE;
484 }
485 }
486
487 if (fU.GetNrows() != b->GetNrows() || fU.GetRowLwb() != b->GetRowLwb()) {
488 Error("Solve(TMatrixDColumn &","vector and matrix incompatible");
489 return kFALSE;
490 }
491
492 const Int_t n = fU.GetNrows();
493
495 const Double_t *pU = fU.GetMatrixArray();
496 Double_t *pcb = cb.GetPtr();
497 const Int_t inc = cb.GetInc();
498
499
500 // solve a*x = b, where a = u*d*u'. First solve u*d*x = b, overwriting b with x.
501 // k is the main loop index, decreasing from n-1 to 0 in steps of 1 or 2,
502 // depending on the size of the diagonal blocks.
503
504 Int_t k = n-1;
505 while (k >= 0) {
506
507 if (fIpiv[k] > 0) {
508
509 // 1 x 1 diagonal block
510 // interchange rows k and ipiv(k).
511 const Int_t kp = fIpiv[k]-1;
512 if (kp != k) {
513 const Double_t tmp = pcb[k*inc];
514 pcb[k*inc] = pcb[kp*inc];
515 pcb[kp*inc] = tmp;
516 }
517
518 // multiply by inv(u(k)), where u(k) is the transformation
519 // stored in column k of a.
520 for (Int_t i = 0; i < k; i++)
521 pcb[i*inc] -= pU[i*n+k]*pcb[k*inc];
522
523 // multiply by the inverse of the diagonal block.
524 pcb[k*inc] /= diag(k);
525 k--;
526 } else {
527
528 // 2 x 2 diagonal block
529 // interchange rows k-1 and -ipiv(k).
530 const Int_t kp = -fIpiv[k]-1;
531 if (kp != k-1) {
532 const Double_t tmp = pcb[(k-1)*inc];
533 pcb[(k-1)*inc] = pcb[kp*inc];
534 pcb[kp*inc] = tmp;
535 }
536
537 // multiply by inv(u(k)), where u(k) is the transformation
538 // stored in columns k-1 and k of a.
539 Int_t i;
540 for (i = 0; i < k-1; i++)
541 pcb[i*inc] -= pU[i*n+k]*pcb[k*inc];
542 for (i = 0; i < k-1; i++)
543 pcb[i*inc] -= pU[i*n+k-1]*pcb[(k-1)*inc];
544
545 // multiply by the inverse of the diagonal block.
546 const Double_t *pU_k1 = pU+(k-1)*n;
547 const Double_t ukm1k = pU_k1[k];
548 const Double_t ukm1 = pU_k1[k-1]/ukm1k;
549 const Double_t uk = diag(k)/ukm1k;
550 const Double_t denom = ukm1*uk-1.;
551 const Double_t bkm1 = pcb[(k-1)*inc]/ukm1k;
552 const Double_t bk = pcb[k*inc]/ukm1k;
553 pcb[(k-1)*inc] = (uk*bkm1-bk)/denom;
554 pcb[k*inc] = (ukm1*bk-bkm1)/denom;
555 k -= 2;
556 }
557 }
558
559 // Next solve u'*x = b, overwriting b with x.
560 //
561 // k is the main loop index, increasing from 0 to n-1 in steps of
562 // 1 or 2, depending on the size of the diagonal blocks.
563
564 k = 0;
565 while (k < n) {
566
567 if (fIpiv[k] > 0) {
568 // 1 x 1 diagonal block
569 // multiply by inv(u'(k)), where u(k) is the transformation
570 // stored in column k of a.
571 for (Int_t i = 0; i < k; i++)
572 pcb[k*inc] -= pU[i*n+k]*pcb[i*inc];
573
574 // interchange elements k and ipiv(k).
575 const Int_t kp = fIpiv[k]-1;
576 if (kp != k) {
577 const Double_t tmp = pcb[k*inc];
578 pcb[k*inc] = pcb[kp*inc];
579 pcb[kp*inc] = tmp;
580 }
581 k++;
582 } else {
583 // 2 x 2 diagonal block
584 // multiply by inv(u'(k+1)), where u(k+1) is the transformation
585 // stored in columns k and k+1 of a.
586 Int_t i;
587 for (i = 0; i < k; i++)
588 pcb[k*inc] -= pU[i*n+k]*pcb[i*inc];
589 for (i = 0; i < k; i++)
590 pcb[(k+1)*inc] -= pU[i*n+k+1]*pcb[i*inc];
591
592 // interchange elements k and -ipiv(k).
593 const Int_t kp = -fIpiv[k]-1;
594 if (kp != k) {
595 const Double_t tmp = pcb[k*inc];
596 pcb[k*inc] = pcb[kp*inc];
597 pcb[kp*inc] = tmp;
598 }
599 k += 2;
600 }
601 }
602
603 return kTRUE;
604}
605
606////////////////////////////////////////////////////////////////////////////////
607/// For a symmetric matrix A(m,m), its inverse A_inv(m,m) is returned .
608
610{
611 if (inv.GetNrows() != GetNrows() || inv.GetRowLwb() != GetRowLwb()) {
612 Error("Invert(TMatrixDSym &","Input matrix has wrong shape");
613 return kFALSE;
614 }
615
616 inv.UnitMatrix();
617
618 const Int_t colLwb = inv.GetColLwb();
619 const Int_t colUpb = inv.GetColUpb();
620 Bool_t status = kTRUE;
621 for (Int_t icol = colLwb; icol <= colUpb && status; icol++) {
623 status &= Solve(b);
624 }
625
626 return status;
627}
628
629////////////////////////////////////////////////////////////////////////////////
630/// For a symmetric matrix A(m,m), its inverse A_inv(m,m) is returned .
631
633{
634 const Int_t rowLwb = GetRowLwb();
635 const Int_t rowUpb = rowLwb+GetNrows()-1;
636
638 inv.UnitMatrix();
639 status = Invert(inv);
640
641 return inv;
642}
643
644////////////////////////////////////////////////////////////////////////////////
645/// Print the class members
646
648{
650 printf("fIpiv:\n");
651 for (Int_t i = 0; i < fNIpiv; i++)
652 printf("[%d] = %d\n",i,fIpiv[i]);
653 fU.Print("fU");
654}
655
656////////////////////////////////////////////////////////////////////////////////
657/// Assignment operator
658
660{
661 if (this != &source) {
663 fU.ResizeTo(source.fU);
664 fU = source.fU;
665 if (fNIpiv != source.fNIpiv) {
666 if (fIpiv)
667 delete [] fIpiv;
668 fNIpiv = source.fNIpiv;
669 fIpiv = new Int_t[fNIpiv];
670 }
671 if (fIpiv) memcpy(fIpiv,source.fIpiv,fNIpiv*sizeof(Int_t));
672 }
673 return *this;
674}
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
TMatrixTColumn_const< Double_t > TMatrixDColumn_const
TMatrixTRow_const< Double_t > TMatrixDRow_const
The Bunch-Kaufman diagonal pivoting method decomposes a real symmetric matrix A using.
Definition TDecompBK.h:27
Int_t GetNrows() const override
Definition TDecompBK.h:45
TDecompBK & operator=(const TDecompBK &source)
Assignment operator.
TDecompBK()
Default constructor.
Definition TDecompBK.cxx:63
TMatrixDSym Invert()
Definition TDecompBK.h:64
Bool_t Decompose() override
Matrix A is decomposed in components U and D so that A = U*D*U^T If the decomposition succeeds,...
Int_t fNIpiv
Definition TDecompBK.h:30
Bool_t Solve(TVectorD &b) override
Solve Ax=b assuming the BK form of A is stored in fU . Solution returned in b.
TMatrixD fU
Definition TDecompBK.h:32
virtual void SetMatrix(const TMatrixDSym &a)
Set the matrix to be decomposed, decomposition status is reset.
void Print(Option_t *opt="") const override
Print the class members.
Int_t * fIpiv
Definition TDecompBK.h:31
Decomposition Base class.
Definition TDecompBase.h:34
Int_t GetRowLwb() const
Definition TDecompBase.h:73
void ResetStatus()
Definition TDecompBase.h:43
Int_t fRowLwb
Definition TDecompBase.h:40
Double_t fTol
Definition TDecompBase.h:36
TDecompBase & operator=(const TDecompBase &source)
Assignment operator.
Double_t fCondition
Definition TDecompBase.h:39
Int_t fColLwb
Definition TDecompBase.h:41
void Print(Option_t *opt="") const override
Print class members.
Int_t GetNrows() const
void Print(Option_t *name="") const override
Print the matrix as a table of elements.
Int_t GetRowLwb() const
Int_t GetNcols() const
virtual TMatrixTBase< Element > & Shift(Int_t row_shift, Int_t col_shift)
Shift the row index by adding row_shift and the column index by adding col_shift, respectively.
const TMatrixTBase< Element > * GetMatrix() const
Element * GetPtr() const
const Element * GetMatrixArray() const override
Definition TMatrixT.h:228
TMatrixTBase< Element > & ResizeTo(Int_t nrows, Int_t ncols, Int_t=-1) override
Set size of the matrix to nrows x ncols New dynamic elements are created, the overlapping part of the...
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
const Int_t n
Definition legend1.C:16
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:251
Long64_t LocMax(Long64_t n, const T *a)
Returns index of array with the maximum element.
Definition TMath.h:1099
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124
void inv(rsa_NUMBER *, rsa_NUMBER *, rsa_NUMBER *)
Definition rsaaux.cxx:949