52 ClassImp(TMatrixDEigen);
57 TMatrixDEigen::TMatrixDEigen(
const TMatrixD &a)
59 R__ASSERT(a.IsValid());
61 const Int_t nRows = a.GetNrows();
62 const Int_t nCols = a.GetNcols();
63 const Int_t rowLwb = a.GetRowLwb();
64 const Int_t colLwb = a.GetColLwb();
66 if (nRows != nCols || rowLwb != colLwb)
68 Error(
"TMatrixDEigen(TMatrixD &)",
"matrix should be square");
72 const Int_t rowUpb = rowLwb+nRows-1;
73 fEigenVectors.ResizeTo(rowLwb,rowUpb,rowLwb,rowUpb);
74 fEigenValuesRe.ResizeTo(rowLwb,rowUpb);
75 fEigenValuesIm.ResizeTo(rowLwb,rowUpb);
78 Double_t work[kWorkMax];
79 if (nRows > kWorkMax) ortho.ResizeTo(nRows);
80 else ortho.Use(nRows,work);
85 MakeHessenBerg(fEigenVectors,ortho,mH);
88 MakeSchurr(fEigenVectors,fEigenValuesRe,fEigenValuesIm,mH);
92 Sort(fEigenVectors,fEigenValuesRe,fEigenValuesIm);
98 TMatrixDEigen::TMatrixDEigen(
const TMatrixDEigen &another)
109 void TMatrixDEigen::MakeHessenBerg(TMatrixD &v,TVectorD &ortho,TMatrixD &H)
111 Double_t *pV = v.GetMatrixArray();
112 Double_t *pO = ortho.GetMatrixArray();
113 Double_t *pH = H.GetMatrixArray();
115 const UInt_t n = v.GetNrows();
117 const UInt_t low = 0;
118 const UInt_t high = n-1;
121 for (m = low+1; m <= high-1; m++) {
122 const UInt_t off_m = m*n;
126 Double_t scale = 0.0;
127 for (i = m; i <= high; i++) {
128 const UInt_t off_i = i*n;
129 scale = scale + TMath::Abs(pH[off_i+m-1]);
136 for (i = high; i >= m; i--) {
137 const UInt_t off_i = i*n;
138 pO[i] = pH[off_i+m-1]/scale;
141 Double_t g = TMath::Sqrt(h);
150 for (j = m; j < n; j++) {
152 for (i = high; i >= m; i--) {
153 const UInt_t off_i = i*n;
154 f += pO[i]*pH[off_i+j];
157 for (i = m; i <= high; i++) {
158 const UInt_t off_i = i*n;
159 pH[off_i+j] -= f*pO[i];
163 for (i = 0; i <= high; i++) {
164 const UInt_t off_i = i*n;
166 for (j = high; j >= m; j--)
167 f += pO[j]*pH[off_i+j];
169 for (j = m; j <= high; j++)
170 pH[off_i+j] -= f*pO[j];
173 pH[off_m+m-1] = scale*g;
179 for (i = 0; i < n; i++) {
180 const UInt_t off_i = i*n;
181 for (j = 0; j < n; j++)
182 pV[off_i+j] = (i == j ? 1.0 : 0.0);
185 for (m = high-1; m >= low+1; m--) {
186 const UInt_t off_m = m*n;
187 if (pH[off_m+m-1] != 0.0) {
188 for (i = m+1; i <= high; i++) {
189 const UInt_t off_i = i*n;
190 pO[i] = pH[off_i+m-1];
192 for (j = m; j <= high; j++) {
194 for (i = m; i <= high; i++) {
195 const UInt_t off_i = i*n;
196 g += pO[i]*pV[off_i+j];
199 g = (g/pO[m])/pH[off_m+m-1];
200 for (i = m; i <= high; i++) {
201 const UInt_t off_i = i*n;
202 pV[off_i+j] += g*pO[i];
212 static Double_t gCdivr, gCdivi;
213 static void cdiv(Double_t xr,Double_t xi,Double_t yr,Double_t yi) {
215 if (TMath::Abs(yr) > TMath::Abs(yi)) {
218 gCdivr = (xr+r*xi)/d;
219 gCdivi = (xi-r*xr)/d;
223 gCdivr = (r*xr+xi)/d;
224 gCdivi = (r*xi-xr)/d;
234 void TMatrixDEigen::MakeSchurr(TMatrixD &v,TVectorD &d,TVectorD &e,TMatrixD &H)
238 const Int_t nn = v.GetNrows();
241 const Int_t high = nn-1;
242 const Double_t eps = TMath::Power(2.0,-52.0);
243 Double_t exshift = 0.0;
244 Double_t p=0,q=0,r=0,s=0,z=0,t,w,x,y;
246 Double_t *pV = v.GetMatrixArray();
247 Double_t *pD = d.GetMatrixArray();
248 Double_t *pE = e.GetMatrixArray();
249 Double_t *pH = H.GetMatrixArray();
255 for (i = 0; i < nn; i++) {
256 const Int_t off_i = i*nn;
257 if ((i < low) || (i > high)) {
261 for (j = TMath::Max(i-1,0); j < nn; j++)
262 norm += TMath::Abs(pH[off_i+j]);
269 const Int_t off_n = n*nn;
270 const Int_t off_n1 = (n-1)*nn;
276 const Int_t off_l1 = (l-1)*nn;
277 const Int_t off_l = l*nn;
278 s = TMath::Abs(pH[off_l1+l-1])+TMath::Abs(pH[off_l+l]);
281 if (TMath::Abs(pH[off_l+l-1]) < eps*s)
290 pH[off_n+n] = pH[off_n+n]+exshift;
298 }
else if (l == n-1) {
299 w = pH[off_n+n-1]*pH[off_n1+n];
300 p = (pH[off_n1+n-1]-pH[off_n+n])/2.0;
302 z = TMath::Sqrt(TMath::Abs(q));
303 pH[off_n+n] = pH[off_n+n]+exshift;
304 pH[off_n1+n-1] = pH[off_n1+n-1]+exshift;
321 s = TMath::Abs(x)+TMath::Abs(z);
324 r = TMath::Sqrt((p*p)+(q*q));
330 for (j = n-1; j < nn; j++) {
332 pH[off_n1+j] = q*z+p*pH[off_n+j];
333 pH[off_n+j] = q*pH[off_n+j]-p*z;
338 for (i = 0; i <= n; i++) {
339 const Int_t off_i = i*nn;
341 pH[off_i+n-1] = q*z+p*pH[off_i+n];
342 pH[off_i+n] = q*pH[off_i+n]-p*z;
347 for (i = low; i <= high; i++) {
348 const Int_t off_i = i*nn;
350 pV[off_i+n-1] = q*z+p*pV[off_i+n];
351 pV[off_i+n] = q*pV[off_i+n]-p*z;
376 w = pH[off_n+n-1]*pH[off_n1+n];
383 for (i = low; i <= n; i++) {
384 const Int_t off_i = i*nn;
387 s = TMath::Abs(pH[off_n+n-1])+TMath::Abs(pH[off_n1+n-2]);
401 s = x-w/((y-x)/2.0+s);
402 for (i = low; i <= n; i++) {
403 const Int_t off_i = i*nn;
412 Error(
"MakeSchurr",
"too many iterations");
420 const Int_t off_m = m*nn;
421 const Int_t off_m_1 = (m-1)*nn;
422 const Int_t off_m1 = (m+1)*nn;
423 const Int_t off_m2 = (m+2)*nn;
427 p = (r*s-w)/pH[off_m1+m]+pH[off_m+m+1];
428 q = pH[off_m1+m+1]-z-r-s;
430 s = TMath::Abs(p)+TMath::Abs(q)+TMath::Abs(r);
436 if (TMath::Abs(pH[off_m+m-1])*(TMath::Abs(q)+TMath::Abs(r)) <
437 eps*(TMath::Abs(p)*(TMath::Abs(pH[off_m_1+m-1])+TMath::Abs(z)+
438 TMath::Abs(pH[off_m1+m+1]))))
443 for (i = m+2; i <= n; i++) {
444 const Int_t off_i = i*nn;
452 for (k = m; k <= n-1; k++) {
453 const Int_t off_k = k*nn;
454 const Int_t off_k1 = (k+1)*nn;
455 const Int_t off_k2 = (k+2)*nn;
456 const Int_t notlast = (k != n-1);
460 r = (notlast ? pH[off_k2+k-1] : 0.0);
461 x = TMath::Abs(p)+TMath::Abs(q)+TMath::Abs(r);
470 s = TMath::Sqrt(p*p+q*q+r*r);
476 pH[off_k+k-1] = -s*x;
478 pH[off_k+k-1] = -pH[off_k+k-1];
488 for (j = k; j < nn; j++) {
489 p = pH[off_k+j]+q*pH[off_k1+j];
491 p = p+r*pH[off_k2+j];
492 pH[off_k2+j] = pH[off_k2+j]-p*z;
494 pH[off_k+j] = pH[off_k+j]-p*x;
495 pH[off_k1+j] = pH[off_k1+j]-p*y;
500 for (i = 0; i <= TMath::Min(n,k+3); i++) {
501 const Int_t off_i = i*nn;
502 p = x*pH[off_i+k]+y*pH[off_i+k+1];
504 p = p+z*pH[off_i+k+2];
505 pH[off_i+k+2] = pH[off_i+k+2]-p*r;
507 pH[off_i+k] = pH[off_i+k]-p;
508 pH[off_i+k+1] = pH[off_i+k+1]-p*q;
513 for (i = low; i <= high; i++) {
514 const Int_t off_i = i*nn;
515 p = x*pV[off_i+k]+y*pV[off_i+k+1];
517 p = p+z*pV[off_i+k+2];
518 pV[off_i+k+2] = pV[off_i+k+2]-p*r;
520 pV[off_i+k] = pV[off_i+k]-p;
521 pV[off_i+k+1] = pV[off_i+k+1]-p*q;
533 for (n = nn-1; n >= 0; n--) {
539 const Int_t off_n = n*nn;
543 for (i = n-1; i >= 0; i--) {
544 const Int_t off_i = i*nn;
545 const Int_t off_i1 = (i+1)*nn;
548 for (j = l; j <= n; j++) {
549 const Int_t off_j = j*nn;
550 r = r+pH[off_i+j]*pH[off_j+n];
561 pH[off_i+n] = -r/(eps*norm);
568 q = (pD[i]-p)*(pD[i]-p)+pE[i]*pE[i];
571 if (TMath::Abs(x) > TMath::Abs(z))
572 pH[i+1+n] = (-r-w*t)/x;
574 pH[i+1+n] = (-s-y*t)/z;
579 t = TMath::Abs(pH[off_i+n]);
581 for (j = i; j <= n; j++) {
582 const Int_t off_j = j*nn;
583 pH[off_j+n] = pH[off_j+n]/t;
593 const Int_t off_n1 = (n-1)*nn;
597 if (TMath::Abs(pH[off_n+n-1]) > TMath::Abs(pH[off_n1+n])) {
598 pH[off_n1+n-1] = q/pH[off_n+n-1];
599 pH[off_n1+n] = -(pH[off_n+n]-p)/pH[off_n+n-1];
601 cdiv(0.0,-pH[off_n1+n],pH[off_n1+n-1]-p,q);
602 pH[off_n1+n-1] = gCdivr;
603 pH[off_n1+n] = gCdivi;
607 for (i = n-2; i >= 0; i--) {
608 const Int_t off_i = i*nn;
609 const Int_t off_i1 = (i+1)*nn;
612 for (j = l; j <= n; j++) {
613 const Int_t off_j = j*nn;
614 ra += pH[off_i+j]*pH[off_j+n-1];
615 sa += pH[off_i+j]*pH[off_j+n];
627 pH[off_i+n-1] = gCdivr;
628 pH[off_i+n] = gCdivi;
635 Double_t vr = (pD[i]-p)*(pD[i]-p)+pE[i]*pE[i]-q*q;
636 Double_t vi = (pD[i]-p)*2.0*q;
637 if ((vr == 0.0) && (vi == 0.0)) {
638 vr = eps*norm*(TMath::Abs(w)+TMath::Abs(q)+
639 TMath::Abs(x)+TMath::Abs(y)+TMath::Abs(z));
641 cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
642 pH[off_i+n-1] = gCdivr;
643 pH[off_i+n] = gCdivi;
644 if (TMath::Abs(x) > (TMath::Abs(z)+TMath::Abs(q))) {
645 pH[off_i1+n-1] = (-ra-w*pH[off_i+n-1]+q*pH[off_i+n])/x;
646 pH[off_i1+n] = (-sa-w*pH[off_i+n]-q*pH[off_i+n-1])/x;
648 cdiv(-r-y*pH[off_i+n-1],-s-y*pH[off_i+n],z,q);
649 pH[off_i1+n-1] = gCdivr;
650 pH[off_i1+n] = gCdivi;
656 t = TMath::Max(TMath::Abs(pH[off_i+n-1]),TMath::Abs(pH[off_i+n]));
658 for (j = i; j <= n; j++) {
659 const Int_t off_j = j*nn;
660 pH[off_j+n-1] = pH[off_j+n-1]/t;
661 pH[off_j+n] = pH[off_j+n]/t;
671 for (i = 0; i < nn; i++) {
672 if (i < low || i > high) {
673 const Int_t off_i = i*nn;
674 for (j = i; j < nn; j++)
675 pV[off_i+j] = pH[off_i+j];
681 for (j = nn-1; j >= low; j--) {
682 for (i = low; i <= high; i++) {
683 const Int_t off_i = i*nn;
685 for (k = low; k <= TMath::Min(j,high); k++) {
686 const Int_t off_k = k*nn;
687 z = z+pV[off_i+k]*pH[off_k+j];
699 void TMatrixDEigen::Sort(TMatrixD &v,TVectorD &d,TVectorD &e)
702 Double_t *pV = v.GetMatrixArray();
703 Double_t *pD = d.GetMatrixArray();
704 Double_t *pE = e.GetMatrixArray();
706 const Int_t n = v.GetNrows();
708 for (Int_t i = 0; i < n-1; i++) {
710 Double_t norm = pD[i]*pD[i]+pE[i]*pE[i];
712 for (j = i+1; j < n; j++) {
713 const Double_t norm_new = pD[j]*pD[j]+pE[j]*pE[j];
714 if (norm_new > norm) {
727 for (j = 0; j < n; j++) {
728 const Int_t off_j = j*n;
730 pV[off_j+i] = pV[off_j+k];
740 TMatrixDEigen &TMatrixDEigen::operator=(
const TMatrixDEigen &source)
742 if (
this != &source) {
743 fEigenVectors.ResizeTo(source.fEigenVectors);
744 fEigenValuesRe.ResizeTo(source.fEigenValuesRe);
745 fEigenValuesIm.ResizeTo(source.fEigenValuesIm);
746 fEigenVectors = source.fEigenVectors;
747 fEigenValuesRe = source.fEigenValuesRe;
748 fEigenValuesIm = source.fEigenValuesIm;
792 const TMatrixD TMatrixDEigen::GetEigenValues()
const
794 const Int_t nrows = fEigenVectors.GetNrows();
795 const Int_t rowLwb = fEigenVectors.GetRowLwb();
796 const Int_t rowUpb = rowLwb+nrows-1;
798 TMatrixD mD(rowLwb,rowUpb,rowLwb,rowUpb);
800 Double_t *pD = mD.GetMatrixArray();
801 const Double_t *
const pd = fEigenValuesRe.GetMatrixArray();
802 const Double_t *
const pe = fEigenValuesIm.GetMatrixArray();
804 for (Int_t i = 0; i < nrows; i++) {
805 const Int_t off_i = i*nrows;
806 for (Int_t j = 0; j < nrows; j++)
810 pD[off_i+i+1] = pe[i];
811 }
else if (pe[i] < 0) {
812 pD[off_i+i-1] = pe[i];