Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_MATH_EIGEN_SYSTEM_DECOMPOSITION_H
00002 #define OPENTISSUE_CORE_MATH_MATH_EIGEN_SYSTEM_DECOMPOSITION_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <cmath>
00013
00014 namespace OpenTissue
00015 {
00016
00017 namespace math
00018 {
00037 template<typename matrix3x3_type,typename vector3_type>
00038 inline void eigen(matrix3x3_type const & A,matrix3x3_type & V,vector3_type & diag)
00039 {
00040 typedef typename vector3_type::value_type real_type;
00041 typedef typename vector3_type::value_traits value_traits;
00042
00043 using std::sqrt;
00044 using std::fabs;
00045
00046 vector3_type sub_diag;
00047
00048 sub_diag.clear();
00049 diag.clear();
00050
00051 V = A;
00052
00053 real_type const & fM00 = V(0,0);
00054 real_type fM01 = V(0,1);
00055 real_type fM02 = V(0,2);
00056 real_type const & fM11 = V(1,1);
00057 real_type const & fM12 = V(1,2);
00058 real_type const & fM22 = V(2,2);
00059
00060 diag(0) = fM00;
00061 sub_diag(2) = value_traits::zero();
00062 if ( fM02 != value_traits::zero() )
00063 {
00064 real_type fLength = sqrt(fM01*fM01+fM02*fM02);
00065 real_type fInvLength = (value_traits::one())/fLength;
00066 fM01 *= fInvLength;
00067 fM02 *= fInvLength;
00068 real_type fQ = (value_traits::two())*fM01*fM12+fM02*(fM22-fM11);
00069 diag(1) = fM11+fM02*fQ;
00070 diag(2) = fM22-fM02*fQ;
00071 sub_diag(0) = fLength;
00072 sub_diag(1) = fM12-fM01*fQ;
00073 V(0,0) = value_traits::one();
00074 V(0,1) = value_traits::zero();
00075 V(0,2) = value_traits::zero();
00076 V(1,0) = value_traits::zero();
00077 V(1,1) = fM01;
00078 V(1,2) = fM02;
00079 V(2,0) = value_traits::zero();
00080 V(2,1) = fM02;
00081 V(2,2) = -fM01;
00082 }
00083 else
00084 {
00085 diag(1) = fM11;
00086 diag(2) = fM22;
00087 sub_diag(0) = fM01;
00088 sub_diag(1) = fM12;
00089 V(0,0) = value_traits::one();
00090 V(0,1) = value_traits::zero();
00091 V(0,2) = value_traits::zero();
00092 V(1,0) = value_traits::zero();
00093 V(1,1) = value_traits::one();
00094 V(1,2) = value_traits::zero();
00095 V(2,0) = value_traits::zero();
00096 V(2,1) = value_traits::zero();
00097 V(2,2) = value_traits::one();
00098 }
00099
00100 const int max_iterations = 32;
00101 const int dim = 3;
00102 for (int i0 = 0; i0 < dim; ++i0)
00103 {
00104 int i1;
00105 for (i1 = 0; i1 < max_iterations; ++i1)
00106 {
00107 int i2;
00108 for (i2 = i0; i2 <= dim-2; ++i2)
00109 {
00110 real_type fTmp = fabs(diag(i2)) + fabs(diag(i2+1));
00111 if ( fabs(sub_diag(i2)) + fTmp == fTmp )
00112 break;
00113 }
00114 if ( i2 == i0 )
00115 break;
00116 real_type fG = (diag(i0+1) - diag(i0))/(value_traits::two()* sub_diag(i0));
00117 real_type fR = sqrt(fG*fG+value_traits::one());
00118 if ( fG < value_traits::zero() )
00119 fG = diag(i2)-diag(i0)+sub_diag(i0)/(fG-fR);
00120 else
00121 fG = diag(i2)-diag(i0)+sub_diag(i0)/(fG+fR);
00122
00123 real_type fSin = value_traits::one();
00124 real_type fCos = value_traits::one();
00125 real_type fP = value_traits::zero();
00126
00127 for (int i3 = i2-1; i3 >= i0; --i3)
00128 {
00129 real_type fF = fSin*sub_diag(i3);
00130 real_type fB = fCos*sub_diag(i3);
00131 if ( fabs(fF) >= fabs(fG) )
00132 {
00133 fCos = fG/fF;
00134 fR = sqrt(fCos*fCos+value_traits::one());
00135 sub_diag(i3+1) = fF*fR;
00136 fSin = value_traits::one()/fR;
00137 fCos *= fSin;
00138 }
00139 else
00140 {
00141 fSin = fF/fG;
00142 fR = sqrt(fSin*fSin+value_traits::one());
00143 sub_diag(i3+1) = fG*fR;
00144 fCos = value_traits::one()/fR;
00145 fSin *= fCos;
00146 }
00147 fG = diag(i3+1)-fP;
00148 fR = (diag(i3)-fG)*fSin+value_traits::two()*fB*fCos;
00149 fP = fSin*fR;
00150 diag(i3+1) = fG+fP;
00151 fG = fCos*fR-fB;
00152 for (int i4 = 0; i4 < dim; ++i4)
00153 {
00154 fF = V(i4,i3+1);
00155 V(i4,i3+1) = fSin*V(i4,i3)+fCos*fF;
00156 V(i4,i3) = fCos*V(i4,i3)-fSin*fF;
00157 }
00158 }
00159 diag(i0) -= fP;
00160 sub_diag(i0) = fG;
00161 sub_diag(i2) = value_traits::zero();
00162 }
00163 if ( i1 == max_iterations )
00164 break;
00165 }
00166 }
00167
00168 }
00169
00170 }
00171
00172
00173 #endif