00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef MECHSYS_LINALG_JACOBIROT_H
00033 #define MECHSYS_LINALG_JACOBIROT_H
00034
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #else
00038 #ifndef REAL
00039 #define REAL double
00040 #endif
00041 #ifndef ZERO
00042 #define ZERO 1.0e-10
00043 #endif
00044 #endif
00045
00046 #include <cmath>
00047
00048 #include "linalg/matrix.h"
00049 #include "linalg/vector.h"
00050
00051 namespace LinAlg
00052 {
00053
00054 namespace Sym
00055 {
00056
00057
00059
00073 inline int JacobiRot(Matrix<REAL> & A, Matrix<REAL> & Q, Vector<REAL> & v)
00074 {
00075 int N = A.Rows();
00076 assert(N>1);
00077 assert(A.Cols()==N);
00078 assert(Q.Rows()==N);
00079 assert(Q.Cols()==N);
00080
00081 const int maxIt=30;
00082 const REAL errTol=1.0e-15;
00083
00084 int j,p,q;
00085 REAL theta,tau,t,sm,s,h,g,c;
00086 REAL * b = new REAL [N];
00087 REAL * z = new REAL [N];
00088
00089 for (p=0; p<N; p++)
00090 {
00091 for (q=0; q<N; q++) Q(p,q)=0.0;
00092 Q(p,p)=1.0;
00093 }
00094 for (p=0; p<N; p++)
00095 {
00096 b[p]=v(p)=A(p,p);
00097 z[p]=0.0;
00098 }
00099
00100 for (int it=0; it<maxIt; it++)
00101 {
00102 sm=0.0;
00103 for (p=0; p<N-1; p++)
00104 {
00105 for (q=p+1; q<N; q++)
00106 sm += fabs(A(p,q));
00107 }
00108 if (sm<errTol)
00109 {
00110 delete [] b;
00111 delete [] z;
00112 return it+1;
00113 }
00114 for (p=0; p<N-1; p++)
00115 {
00116 for (q=p+1; q<N; q++)
00117 {
00118 h=v(q)-v(p);
00119 if (fabs(h)<=ZERO) t=1.0;
00120 else
00121 {
00122 theta=0.5*h/(A(p,q));
00123 t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
00124 if (theta < 0.0) t=-t;
00125 }
00126 c=1.0/sqrt(1.0+t*t);
00127 s=t*c;
00128 tau=s/(1.0+c);
00129 h=t*A(p,q);
00130 z[p] -= h;
00131 z[q] += h;
00132 v(p) -= h;
00133 v(q) += h;
00134 A(p,q)=0.0;
00135 for (j=0; j<p; j++)
00136 {
00137 g = A(j,p);
00138 h = A(j,q);
00139 A(j,p) = g - s*(h+g*tau);
00140 A(j,q) = h + s*(g-h*tau);
00141 }
00142 for (j=p+1; j<q; j++)
00143 {
00144 g = A(p,j);
00145 h = A(j,q);
00146 A(p,j) = g - s*(h+g*tau);
00147 A(j,q) = h + s*(g-h*tau);
00148 }
00149 for (j=q+1; j<N; j++)
00150 {
00151 g = A(p,j);
00152 h = A(q,j);
00153 A(p,j) = g - s*(h+g*tau);
00154 A(q,j) = h + s*(g-h*tau);
00155 }
00156 for (j=0; j<N; j++)
00157 {
00158 g = Q(j,p);
00159 h = Q(j,q);
00160 Q(j,p) = g - s*(h+g*tau);
00161 Q(j,q) = h + s*(g-h*tau);
00162 }
00163 }
00164 }
00165 for (p=0; p<N; p++)
00166 {
00167 b[p] += z[p];
00168 z[p] = 0.0;
00169 v(p) = b[p];
00170 }
00171 }
00172
00173 delete [] b;
00174 delete [] z;
00175 std::cout << "ERROR: Too many iterations in routine jacobi\n";
00176 return maxIt+1;
00177
00178 }
00179
00180 };
00181
00182 };
00183
00184 #endif // MECHSYS_LINALG_JACOBIROT_H
00185
00186