00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __VMML__JACOBI_SOLVER__H__
00018 #define __VMML__JACOBI_SOLVER__H__
00019
00020 #include <vmmlib/vmmlib.h>
00021
00022 #include <cmath>
00023 #include <cassert>
00024
00025 namespace vmml
00026 {
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 template < typename Real >
00043 bool solveJacobi3x3( Matrix3< Real >& a, Vector3< Real >& d,
00044 Matrix3< Real >& v, size_t& rotationCount )
00045 {
00046 v = Matrix3< Real >::IDENTITY;
00047
00048 Vector3< Real > b, z;
00049
00050 for ( size_t i = 0; i < 3; ++i )
00051 {
00052 b[i] = d[i] = a.m[i][i];
00053 z[i] = 0.0;
00054 }
00055 Real t, theta, s, c, tau;
00056 size_t rot = 0;
00057 for ( size_t i = 1; i <= 150; ++i )
00058 {
00059 Real sm = 0.0;
00060 for ( size_t ip = 0; ip < 2; ++ip )
00061 {
00062 for ( size_t iq = ip + 1; iq < 3; ++iq )
00063 {
00064 sm += fabs( a.m[ip][iq] );
00065 }
00066 }
00067 if ( sm == 0.0 )
00068 {
00069 rotationCount = rot;
00070 return true;
00071 }
00072 Real tresh = ( i < 4 ) ? 0.2 * sm / 9.0 : 0.0;
00073
00074 for ( ssize_t ip = 0; ip < 2; ++ip )
00075 {
00076 for ( ssize_t iq = ip + 1; iq < 3; ++iq )
00077 {
00078 Real g = 100.0 * fabs( a.m[ip][iq] );
00079
00080
00081
00082 if ( i > 4
00083 && fabs( d[ip] ) + g == fabs( d[ip] )
00084 && fabs( d[iq] ) + g == fabs( d[iq] )
00085 )
00086 {
00087 a.m[ip][iq] = 0.0;
00088 }
00089 else
00090 {
00091 if ( fabs( a.m[ip][iq] ) > tresh )
00092 {
00093 Real h = d[iq] - d[ip];
00094 if ( fabs( h ) + g == fabs( h ) )
00095 {
00096 if ( h != 0.0 )
00097 t = ( a.m[ip][iq] ) / h;
00098 else
00099 t = 0.0;
00100 }
00101 else
00102 {
00103 if( a.m[ip][iq] != 0.0 )
00104 theta = 0.5 * h / ( a.m[ip][iq] );
00105 else
00106 theta = 0.0;
00107 t = 1.0 / ( fabs( theta ) + sqrt( 1.0 + theta * theta ) );
00108 if ( theta < 0.0 )
00109 t = -t;
00110 }
00111 c = 1.0 / sqrt( 1 + t * t );
00112 s = t * c;
00113 tau = s / ( 1.0 + c );
00114 h = t * a.m[ip][iq];
00115 z[ip] -= h;
00116 z[iq] += h;
00117 d[ip] -= h;
00118 d[iq] += h;
00119 a.m[ip][iq] = 0.0;
00120
00121 for ( ssize_t j = 0; j <= ip - 1; ++j )
00122 {
00123 g = a.m[j][ip];
00124 h = a.m[j][iq];
00125 a.m[j][ip] = g - s * ( h + g * tau );
00126 a.m[j][iq] = h + s * ( g - h * tau );
00127 }
00128 for ( ssize_t j = ip + 1; j <= iq - 1; ++j )
00129 {
00130 g = a.m[ip][j];
00131 h = a.m[j][iq];
00132 a.m[ip][j] = g - s * ( h + g * tau );
00133 a.m[j][iq] = h + s * ( g - h * tau );
00134 }
00135 for ( size_t j = iq + 1; j < 3; ++j )
00136 {
00137 g = a.m[ip][j];
00138 h = a.m[iq][j];
00139 a.m[ip][j] = g - s * ( h + g * tau );
00140 a.m[iq][j] = h + s * ( g - h * tau );
00141 }
00142 for ( size_t j = 0; j < 3; ++j )
00143 {
00144 g = v.m[j][ip];
00145 h = v.m[j][iq];
00146 v.m[j][ip] = g - s * ( h + g * tau );
00147 v.m[j][iq] = h + s * ( g - h * tau );
00148 }
00149 ++rot;
00150 }
00151 }
00152 }
00153 }
00154
00155 for ( size_t ip = 0; ip < 3; ++ip )
00156 {
00157 b[ip] += z[ip];
00158 d[ip] = b[ip];
00159 z[ip] = 0.0;
00160 }
00161 }
00162 return false;
00163
00164 }
00165
00166 }
00167
00168 #endif