struct Unsymmeig { Int n; MatDoub a,zz; VecComplex wri; VecDoub scale; VecInt perm; Bool yesvecs,hessen; Unsymmeig(MatDoub_I &aa, Bool yesvec=true, Bool hessenb=false) : n(aa.nrows()), a(aa), zz(n,n,0.0), wri(n), scale(n,1.0), perm(n), yesvecs(yesvec), hessen(hessenb) { balance(); if (!hessen) elmhes(); if (yesvecs) { for (Int i=0;i::radix; Bool done=false; Doub sqrdx=RADIX*RADIX; while (!done) { done=true; for (Int i=0;ig) { f /= RADIX; c /= sqrdx; } if ((c+r)/f < 0.95*s) { done=false; g=1.0/f; scale[i] *= f; for (Int j=0;j abs(x)) { x=a[j][m-1]; i=j; } } perm[m]=i; if (i != m) { for (Int j=m-1;j0;mp--) { for (Int k=mp+1;k::epsilon(); for (i=0;i= 0) { its=0; do { for (l=nn;l>0;l--) { s=abs(a[l-1][l-1])+abs(a[l][l]); if (s == 0.0) s=anorm; if (abs(a[l][l-1]) <= EPS*s) { a[l][l-1] = 0.0; break; } } x=a[nn][nn]; if (l == nn) { wri[nn--]=x+t; } else { y=a[nn-1][nn-1]; w=a[nn][nn-1]*a[nn-1][nn]; if (l == nn-1) { p=0.5*(y-x); q=p*p+w; z=sqrt(abs(q)); x += t; if (q >= 0.0) { z=p+SIGN(z,p); wri[nn-1]=wri[nn]=x+z; if (z != 0.0) wri[nn]=x-w/z; } else { wri[nn]=Complex(x+p,-z); wri[nn-1]=conj(wri[nn]); } nn -= 2; } else { if (its == 30) throw("Too many iterations in hqr"); if (its == 10 || its == 20) { t += x; for (i=0;i=l;m--) { z=a[m][m]; r=x-z; s=y-z; p=(r*s-w)/a[m+1][m]+a[m][m+1]; q=a[m+1][m+1]-z-r-s; r=a[m+2][m+1]; s=abs(p)+abs(q)+abs(r); p /= s; q /= s; r /= s; if (m == l) break; u=abs(a[m][m-1])*(abs(q)+abs(r)); v=abs(p)*(abs(a[m-1][m-1])+abs(z)+abs(a[m+1][m+1])); if (u <= EPS*v) break; } for (i=m;i::epsilon(); for (i=0;i= 0) { its=0; do { for (l=nn;l>0;l--) { s=abs(a[l-1][l-1])+abs(a[l][l]); if (s == 0.0) s=anorm; if (abs(a[l][l-1]) <= EPS*s) { a[l][l-1] = 0.0; break; } } x=a[nn][nn]; if (l == nn) { wri[nn]=a[nn][nn]=x+t; nn--; } else { y=a[nn-1][nn-1]; w=a[nn][nn-1]*a[nn-1][nn]; if (l == nn-1) { p=0.5*(y-x); q=p*p+w; z=sqrt(abs(q)); x += t; a[nn][nn]=x; a[nn-1][nn-1]=y+t; if (q >= 0.0) { z=p+SIGN(z,p); wri[nn-1]=wri[nn]=x+z; if (z != 0.0) wri[nn]=x-w/z; x=a[nn][nn-1]; s=abs(x)+abs(z); p=x/s; q=z/s; r=sqrt(p*p+q*q); p /= r; q /= r; for (j=nn-1;j=l;m--) { z=a[m][m]; r=x-z; s=y-z; p=(r*s-w)/a[m+1][m]+a[m][m+1]; q=a[m+1][m+1]-z-r-s; r=a[m+2][m+1]; s=abs(p)+abs(q)+abs(r); p /= s; q /= s; r /= s; if (m == l) break; u=abs(a[m][m-1])*(abs(q)+abs(r)); v=abs(p)*(abs(a[m-1][m-1])+abs(z)+abs(a[m+1][m+1])); if (u <= EPS*v) break; } for (i=m;i=0;nn--) { p=real(wri[nn]); q=imag(wri[nn]); na=nn-1; if (q == 0.0) { m=nn; a[nn][nn]=1.0; for (i=nn-1;i>=0;i--) { w=a[i][i]-p; r=0.0; for (j=m;j<=nn;j++) r += a[i][j]*a[j][nn]; if (imag(wri[i]) < 0.0) { z=w; s=r; } else { m=i; if (imag(wri[i]) == 0.0) { t=w; if (t == 0.0) t=EPS*anorm; a[i][nn]=-r/t; } else { x=a[i][i+1]; y=a[i+1][i]; q=SQR(real(wri[i])-p)+SQR(imag(wri[i])); t=(x*s-z*r)/q; a[i][nn]=t; if (abs(x) > abs(z)) a[i+1][nn]=(-r-w*t)/x; else a[i+1][nn]=(-s-y*t)/z; } t=abs(a[i][nn]); if (EPS*t*t > 1) for (j=i;j<=nn;j++) a[j][nn] /= t; } } } else if (q < 0.0) { m=na; if (abs(a[nn][na]) > abs(a[na][nn])) { a[na][na]=q/a[nn][na]; a[na][nn]=-(a[nn][nn]-p)/a[nn][na]; } else { Complex temp=Complex(0.0,-a[na][nn])/Complex(a[na][na]-p,q); a[na][na]=real(temp); a[na][nn]=imag(temp); } a[nn][na]=0.0; a[nn][nn]=1.0; for (i=nn-2;i>=0;i--) { w=a[i][i]-p; ra=sa=0.0; for (j=m;j<=nn;j++) { ra += a[i][j]*a[j][na]; sa += a[i][j]*a[j][nn]; } if (imag(wri[i]) < 0.0) { z=w; r=ra; s=sa; } else { m=i; if (imag(wri[i]) == 0.0) { Complex temp = Complex(-ra,-sa)/Complex(w,q); a[i][na]=real(temp); a[i][nn]=imag(temp); } else { x=a[i][i+1]; y=a[i+1][i]; vr=SQR(real(wri[i])-p)+SQR(imag(wri[i]))-q*q; vi=2.0*q*(real(wri[i])-p); if (vr == 0.0 && vi == 0.0) vr=EPS*anorm*(abs(w)+abs(q)+abs(x)+abs(y)+abs(z)); Complex temp=Complex(x*r-z*ra+q*sa,x*s-z*sa-q*ra)/ Complex(vr,vi); a[i][na]=real(temp); a[i][nn]=imag(temp); if (abs(x) > abs(z)+abs(q)) { a[i+1][na]=(-ra-w*a[i][na]+q*a[i][nn])/x; a[i+1][nn]=(-sa-w*a[i][nn]-q*a[i][na])/x; } else { Complex temp=Complex(-r-y*a[i][na],-s-y*a[i][nn])/ Complex(z,q); a[i+1][na]=real(temp); a[i+1][nn]=imag(temp); } } } t=MAX(abs(a[i][na]),abs(a[i][nn])); if (EPS*t*t > 1) for (j=i;j<=nn;j++) { a[j][na] /= t; a[j][nn] /= t; } } } } for (j=n-1;j>=0;j--) for (i=0;i=0;i--) { if (real(wri[i]) >= real(x)) break; wri[i+1]=wri[i]; } wri[i+1]=x; } } void Unsymmeig::sortvecs() { Int i; VecDoub temp(n); for (Int j=1;j=0;i--) { if (real(wri[i]) >= real(x)) break; wri[i+1]=wri[i]; for (Int k=0;k