20T rayleigh_quotient(mat<T>& A,vec<T>&x)
22 return dot(x,A*x)/dot(x,x);
30void rot(mat<T> &a,
const T s,
const T tau,
const int i,
32 const int j,
const int k,
const int l)
49void eigsrt(diag_mat<T> &d, mat<T> &v)
57 for (
unsigned i=0;i<n-1;i++)
63 for (
unsigned j=i;j<n;j++)
65 if (d(j) >= p) p=d(k=j);
75 for (
unsigned j=0;j<n;j++)
92bool eig_sym(
const mat<T> &a, mat<T> &v, diag_mat<T> &d,
bool ordering=
true,
unsigned maxiter=50)
95 unsigned n =aa.nrows();
103 const T eps = std::numeric_limits<T>::epsilon();
105 T tresh,theta,tau,t,sm,s,h,g,c;
111 for(
unsigned i = 0; i < n; i++)
114 for (
unsigned i=1;i<=maxiter;i++)
122 for (ip=0;ip<n-1;ip++)
126 for (iq=ip+1;iq<n;iq++)
128 sm += std::abs(aa(ip,iq));
146 tresh=(T)(0.2*sm/(n*n));
152 for (ip=0;ip<n-1;ip++)
156 for (iq=ip+1;iq<n;iq++)
160 g=((T)100.0)*std::abs(aa(ip,iq));
162 if (i > 4 && g <= eps*std::abs(d(ip)) && g <= eps*std::abs(d(iq)))
166 else if (std::abs(aa(ip,iq)) > tresh)
172 if (g <= eps*std::abs(h))
178 theta=(T)(0.5*h/(aa(ip,iq)));
180 t=(T)(1.0/(std::abs(theta)+sqrt(1.0+theta*theta)));
182 if (theta < 0.0) t = -t;
186 c=(T)(1.0/sqrt(1+t*t));
204 for (
unsigned j=0;j<ip;j++)
206 rot(aa,s,tau,j,ip,j,iq);
208 for (
unsigned j=ip+1;j<iq;j++)
210 rot(aa,s,tau,ip,j,j,iq);
212 for (
unsigned j=iq+1;j<n;j++)
214 rot(aa,s,tau,ip,j,iq,j);
216 for (
unsigned j=0;j<n;j++)
218 rot(v,s,tau,j,ip,j,iq);
228 for (ip=0;ip<n;ip++) {
258 n(aa.
nrows()), a(aa), zz(n,n,0.0), wri(n), scale(n), perm(n),
259 yesvecs(yesvec), hessen(hessenb)
263 if (!hessen) elmhes();
265 for (
int i=0;i<n;i++)
267 if (!hessen) eltran();
288T SIGN(
const T &a,
const T &b)
289 {
return (T)(b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a));}
291void Unsymmeig<T>::balance()
293 const T RADIX = std::numeric_limits<T>::radix;
298 for (
int i=0;i<n;i++) {
300 for (
int j=0;j<n;j++)
302 c += std::abs(a(j,i));
303 r += std::abs(a(i,j));
305 if (c != 0.0 && r != 0.0) {
318 if ((c+r)/f < 0.95*s)
323 for (
int j=0;j<n;j++) a(i,j) *= g;
324 for (
int j=0;j<n;j++) a(j,i) *= f;
331void Unsymmeig<T>::balbak()
333 for (
int i=0;i<n;i++)
334 for (
int j=0;j<n;j++)
339void Unsymmeig<T>::elmhes()
341 for (
int m=1;m<n-1;m++) {
344 for (
int j=m;j<n;j++)
346 if (std::abs(a(j,m-1)) > std::abs(x))
355 for (
int j=m-1;j<n;j++) std::swap(a(i,j),a(m,j));
356 for (
int j=0;j<n;j++) std::swap(a(j,i),a(j,m));
367 for (
int j=m;j<n;j++) a(i,j) -= y*a(m,j);
368 for (
int j=0;j<n;j++) a(j,m) += y*a(j,i);
376void Unsymmeig<T>::eltran()
378 for (
int mp=n-2;mp>0;mp--)
380 for (
int k=mp+1;k<n;k++)
384 for (
int j=mp;j<n;j++) {
394void Unsymmeig<T>::hqr()
396 int nn,m,l,k,j,its,i,mmin;
397 T z,y,x,w,v,u,t,s,r,q,p,anorm=0.0;
399 const T EPS=std::numeric_limits<T>::epsilon();
401 for (j=std::max(i-1,0);j<n;j++)
402 anorm += std::abs(a(i,j));
409 s=std::abs(a(l-1,l-1))+std::abs(a(l,l));
410 if (s == 0.0) s=anorm;
411 if (std::abs(a(l,l-1)) <= EPS*s)
422 w=a(nn,nn-1)*a(nn-1,nn);
431 wri[nn-1]=wri[nn]=x+z;
432 if (z != 0.0) wri[nn]=x-w/z;
434 wri[nn]=std::complex<T>(x+p,-z);
435 wri[nn-1]=conj(wri[nn]);
439 if (its == 30)
throw(
"Too many iterations in hqr");
440 if (its == 10 || its == 20) {
442 for (i=0;i<nn+1;i++) a(i,i) -= x;
443 s=std::abs(a(nn,nn-1))+std::abs(a(nn-1,nn-2));
448 for (m=nn-2;m>=l;m--) {
452 p=(r*s-w)/a(m+1,m)+a(m,m+1);
455 s=std::abs(p)+std::abs(q)+std::abs(r);
460 u=std::abs(a(m,m-1))*(std::abs(q)+std::abs(r));
461 v=std::abs(p)*(std::abs(a(m-1,m-1))+std::abs(z)+std::abs(a(m+1,m+1)));
462 if (u <= EPS*v)
break;
464 for (i=m;i<nn-1;i++) {
466 if (i != m) a(i+2,i-1)=0.0;
473 if (k+1 != nn) r=a(k+2,k-1);
474 if ((x=std::abs(p)+std::abs(q)+std::abs(r)) != 0.0) {
480 if ((s=SIGN(sqrt(p*p+q*q+r*r),p)) != 0.0) {
483 a(k,k-1) = -a(k,k-1);
502 mmin = nn < k+3 ? nn : k+3;
503 for (i=l;i<mmin+1;i++)
505 p=x*a(i,k)+y*a(i,k+1);
523void Unsymmeig<T>::hqr2()
525 int nn,m,l,k,j,its,i,mmin,na;
526 T z,y,x,w,v,u,t,s,r,q,p,anorm=0.0,ra,sa,
vr,vi;
528 const T EPS=std::numeric_limits<T>::epsilon();
530 for (j=std::max(i-1,0);j<n;j++)
531 anorm += std::abs(a(i,j));
538 s=std::abs(a(l-1,l-1))+std::abs(a(l,l));
539 if (s == 0.0) s=anorm;
540 if (std::abs(a(l,l-1)) <= EPS*s) {
547 wri(nn)=a(nn,nn)=x+t;
551 w=a(nn,nn-1)*a(nn-1,nn);
561 wri[nn-1]=wri[nn]=x+z;
562 if (z != 0.0) wri[nn]=x-w/z;
564 s=std::abs(x)+std::abs(z);
570 for (j=nn-1;j<n;j++) {
572 a(nn-1,j)=q*z+p*a(nn,j);
573 a(nn,j)=q*a(nn,j)-p*z;
575 for (i=0;i<=nn;i++) {
577 a(i,nn-1)=q*z+p*a(i,nn);
578 a(i,nn)=q*a(i,nn)-p*z;
582 zz(i,nn-1)=q*z+p*zz(i,nn);
583 zz(i,nn)=q*zz(i,nn)-p*z;
586 wri[nn]=std::complex<T>(x+p,-z);
587 wri[nn-1]=std::conj(wri[nn]);
591 if (its == 30)
throw(
"Too many iterations in hqr");
592 if (its == 10 || its == 20)
595 for (i=0;i<nn+1;i++) a(i,i) -= x;
596 s=std::abs(a(nn,nn-1))+std::abs(a(nn-1,nn-2));
601 for (m=nn-2;m>=l;m--)
606 p=(r*s-w)/a(m+1,m)+a(m,m+1);
609 s=std::abs(p)+std::abs(q)+std::abs(r);
614 u=std::abs(a(m,m-1))*(std::abs(q)+std::abs(r));
615 v=std::abs(p)*(std::abs(a(m-1,m-1))+std::abs(z)+std::abs(a(m+1,m+1)));
616 if (u <= EPS*v)
break;
618 for (i=m;i<nn-1;i++) {
620 if (i != m) a(i+2,i-1)=0.0;
627 if (k+1 != nn) r=a(k+2,k-1);
628 if ((x=std::abs(p)+std::abs(q)+std::abs(r)) != 0.0) {
634 if ((s=SIGN(sqrt(p*p+q*q+r*r),p)) != 0.0) {
637 a(k,k-1) = -a(k,k-1);
655 mmin = nn < k+3 ? nn : k+3;
656 for (i=0;i<mmin+1;i++) {
657 p=x*a(i,k)+y*a(i,k+1);
665 for (i=0; i<n; i++) {
666 p=x*zz(i,k)+y*zz(i,k+1);
681 for (nn=n-1;nn>=0;nn--) {
688 for (i=nn-1;i>=0;i--) {
693 if (imag(wri[i]) < 0.0) {
699 if (imag(wri[i]) == 0.0) {
707 q=cgv::math::sqr(real(wri[i])-p)+cgv::math::sqr(imag(wri[i]));
710 if (std::abs(x) > std::abs(z))
711 a(i+1,nn)=(-r-w*t)/x;
713 a(i+1,nn)=(-s-y*t)/z;
721 }
else if (q < 0.0) {
723 if (std::abs(a(nn,na)) > std::abs(a(na,nn))) {
725 a(na,nn)=-(a(nn,nn)-p)/a(nn,na);
727 std::complex<T> temp=std::complex<T>(0.0,-a(na,nn))/std::complex<T>(a(na,na)-p,q);
733 for (i=nn-2;i>=0;i--) {
736 for (j=m;j<=nn;j++) {
737 ra += a(i,j)*a(j,na);
738 sa += a(i,j)*a(j,nn);
740 if (imag(wri[i]) < 0.0) {
746 if (imag(wri[i]) == 0.0) {
747 std::complex<T> temp = std::complex<T>(-ra,-sa)/std::complex<T>(w,q);
753 vr=cgv::math::sqr(real(wri(i))-p)+cgv::math::sqr(imag(wri(i)))-q*q;
754 vi=2.0*q*(real(wri(i))-p);
755 if (
vr == 0.0 && vi == 0.0)
756 vr=EPS*anorm*(std::abs(w)+std::abs(q)+std::abs(x)+std::abs(y)+std::abs(z));
757 std::complex<T> temp=std::complex<T>(x*r-z*ra+q*sa,x*s-z*sa-q*ra)/
758 std::complex<T>(
vr,vi);
761 if (std::abs(x) > std::abs(z)+std::abs(q)) {
762 a(i+1,na)=(-ra-w*a(i,na)+q*a(i,nn))/x;
763 a(i+1,nn)=(-sa-w*a(i,nn)-q*a(i,na))/x;
765 std::complex<T> temp=std::complex<T>(-r-y*a(i,na),-s-y*a(i,nn))/
766 std::complex<T>(z,q);
767 a(i+1,na)=real(temp);
768 a(i+1,nn)=imag(temp);
772 t=std::max(std::abs(a(i,na)),std::abs(a(i,nn)));
774 for (j=i;j<=nn;j++) {
791void Unsymmeig<T>::sort()
794 for (
int j=1;j<n;j++)
796 std::complex<T> x=wri[j];
797 for (i=j-1;i>=0;i--) {
798 if (std::real(wri[i]) >= real(x))
break;
806void Unsymmeig<T>::sortvecs()
810 for (
int j=1;j<n;j++) {
811 std::complex<T> x=wri[j];
812 for (
int k=0;k<n;k++)
814 for (i=j-1;i>=0;i--) {
815 if (real(wri[i]) >= std::real(x))
break;
817 for (
int k=0;k<n;k++)
821 for (
int k=0;k<n;k++)
838 eigvals = eigsolver.wri;
850 Unsymmeig<T> eigsolver(A,
true,hessenb);
851 eigvals = eigsolver.wri;
854 for(
unsigned i = 0; i < eigsolver.zz.ncols();i++)
855 eigsolver.zz.set_col(i,cgv::math::normalize(eigsolver.zz.col(i)));
857 eigvecs=eigsolver.zz;
A matrix type (full column major storage) The matrix can be loaded directly into OpenGL without need ...
unsigned nrows() const
number of rows
void ones()
fill the vector with ones
the vr namespace for virtual reality support
A diagonal matrix type which internally stores the elements on the main diagonal in a vector.