37 #include <TooN/lapack.h> 39 #include <TooN/TooN.h> 42 static const double root3=1.73205080756887729352744634150587236694280525381038062805580;
49 static const double symeigen_condition_no=1e9;
63 template<
int Rows,
int Cols,
typename P,
typename B>
71 FortranInteger N = evalues.size();
72 FortranInteger lda = evalues.size();
74 FortranInteger lwork=-1;
78 syev_((
char*)
"V",(
char*)
"U",&N,&evectors[0][0],&lda,&evalues[0], &size,&lwork,&info);
83 syev_((
char*)
"V",(
char*)
"U",&N,&evectors[0][0],&lda,&evalues[0], &WORK[0],&lwork,&info);
86 std::cerr <<
"In SymEigen<"<<Size<<
">: " << info
87 <<
" off-diagonal elements of an intermediate tridiagonal form did not converge to zero." << std::endl
88 <<
"M = " << m << std::endl;
104 template<
typename P,
typename B>
106 double trace = m[0][0] + m[1][1];
108 double det = m[0][0]*m[1][1] - m[0][1]*m[0][1];
109 double disc = trace*trace - 4 * det;
117 double root_disc =
sqrt(disc);
118 ev[0] = 0.5 * (trace - root_disc);
119 ev[1] = 0.5 * (trace + root_disc);
120 double a = m[0][0] - ev[0];
122 double magsq = a*a + b*b;
129 eig[0] *= 1.0/
sqrt(magsq);
131 eig[1][0] = -eig[0][1];
132 eig[1][1] = eig[0][0];
147 template<
typename P,
typename B>
154 double a_norm =
norm_1(m);
155 double eps = 1e-7 * a_norm;
159 eig = TooN::Identity;
166 const double& a11 = m[0][0];
167 const double& a12 = m[0][1];
168 const double& a13 = m[0][2];
170 const double& a22 = m[1][1];
171 const double& a23 = m[1][2];
173 const double& a33 = m[2][2];
176 double a = -a11-a22-a33;
177 double b = a11*a22+a11*a33+a22*a33-a12*a12-a13*a13-a23*a23;
178 double c = a11*(a23*a23)+(a13*a13)*a22+(a12*a12)*a33-a12*a13*a23*2.0-a11*a22*a33;
181 double p = b - a*a/3;
182 double q = c + (2*a*a*a - 9*a*b)/27;
188 double beta_descriminant = std::min(0.0, q*q/4 + p*p*p/27);
190 double beta =
sqrt(-beta_descriminant);
191 double r2 = alpha*alpha - beta_descriminant;
196 double cuberoot_r = pow(r2, 1./6);
198 double theta3 = atan2(beta, alpha)/3;
200 double A_plus_B = 2*cuberoot_r*cos(theta3);
201 double A_minus_B = -2*cuberoot_r*sin(theta3);
204 ev = makeVector(A_plus_B, -A_plus_B/2 + A_minus_B *
sqrt(3)/2, -A_plus_B/2 - A_minus_B *
sqrt(3)/2) - Ones * a/3;
222 eig[0][0]=a12 * a23 - a13 * (a22 - ev[0]);
223 eig[0][1]=a12 * a13 - a23 * (a11 - ev[0]);
224 eig[0][2]=(a11-ev[0])*(a22-ev[0]) - a12*a12;
225 eig[1][0]=a12 * a23 - a13 * (a22 - ev[1]);
226 eig[1][1]=a12 * a13 - a23 * (a11 - ev[1]);
227 eig[1][2]=(a11-ev[1])*(a22-ev[1]) - a12*a12;
228 eig[2][0]=a12 * a23 - a13 * (a22 - ev[2]);
229 eig[2][1]=a12 * a13 - a23 * (a11 - ev[2]);
230 eig[2][2]=(a11-ev[2])*(a22-ev[2]) - a12*a12;
233 double e0norm =
norm_1(eig[0]);
234 double e1norm =
norm_1(eig[1]);
235 double e2norm =
norm_1(eig[2]);
244 eig[0][0] += a12 * (ev[0] - a33) + a23 * a13;
245 eig[0][1] += (ev[0]-a11)*(ev[0]-a33) - a13*a13;
246 eig[0][2] += a23 * (ev[0] - a11) + a12 * a13;
252 eig[1][0] += a12 * (ev[1] - a33) + a23 * a13;
253 eig[1][1] += (ev[1]-a11)*(ev[1]-a33) - a13*a13;
254 eig[1][2] += a23 * (ev[1] - a11) + a12 * a13;
260 eig[2][0] += a12 * (ev[2] - a33) + a23 * a13;
261 eig[2][1] += (ev[2]-a11)*(ev[2]-a33) - a13*a13;
262 eig[2][2] += a23 * (ev[2] - a11) + a12 * a13;
271 eig[0][0] +=(ev[0]-a22)*(ev[0]-a33) - a23*a23;
272 eig[0][1] +=a12 * (ev[0] - a33) + a23 * a13;
273 eig[0][2] +=a13 * (ev[0] - a22) + a23 * a12;
279 eig[1][0] +=(ev[1]-a22)*(ev[1]-a33) - a23*a23;
280 eig[1][1] +=a12 * (ev[1] - a33) + a23 * a13;
281 eig[1][2] +=a13 * (ev[1] - a22) + a23 * a12;
287 eig[2][0] +=(ev[2]-a22)*(ev[2]-a33) - a23*a23;
288 eig[2][1] +=a12 * (ev[2] - a33) + a23 * a13;
289 eig[2][2] +=a13 * (ev[2] - a22) + a23 * a12;
294 if(e0norm < eps || e1norm < eps || e2norm < eps)
298 double ns[] = {e0norm, e1norm, e2norm};
299 double is[] = {0, 1, 2};
324 eig[is[0]] = eig[is[1]]^eig[is[2]];
326 else if(ns[2] >= eps)
331 Vector<3> p = makeVector(eig[is[2]][1], eig[is[2]][2], eig[is[2]][0]);
341 eig = TooN::Identity;
402 template <
int Size=Dynamic,
typename Precision =
double>
411 inline SymEigen(
int m) : my_evectors(m,m), my_evalues(m) {}
415 template<
int R,
int C,
typename B>
421 template<
int R,
int C,
typename B>
432 template <
int S,
typename P,
typename B>
434 return (my_evectors.T() * diagmult(get_inv_diag(Internal::symeigen_condition_no),(my_evectors * rhs)));
441 template <
int R,
int C,
typename P,
typename B>
443 return (my_evectors.T() * diagmult(get_inv_diag(Internal::symeigen_condition_no),(my_evectors * rhs)));
452 return my_evectors.T() * diagmult(get_inv_diag(condition),my_evectors);
462 Precision max_diag = -my_evalues[0] > my_evalues[my_evalues.size()-1] ? -my_evalues[0]:my_evalues[my_evalues.size()-1];
464 for(
int i=0; i<my_evalues.size(); i++){
465 if(fabs(my_evalues[i]) * condition > max_diag) {
466 invdiag[i] = 1/my_evalues[i];
496 for (
int i = 0; i < my_evalues.size(); ++i) {
497 if (my_evalues[i] <= 0.0)
505 for (
int i = 0; i < my_evalues.size(); ++i) {
506 if (my_evalues[i] >= 0.0)
515 for (
int i = 0; i < my_evalues.size(); ++i) {
516 det *= my_evalues[i];
527 for (
int i = 0; i < my_evalues.size(); ++i) {
530 return my_evectors.T() * diagmult(diag_sqrt, my_evectors);
543 Precision max_diag = -my_evalues[0] > my_evalues[my_evalues.size()-1] ? (-
std::sqrt(my_evalues[0])):(
std::sqrt(my_evalues[my_evalues.size()-1]));
546 for (
int i = 0; i < my_evalues.size(); ++i) {
547 diag_isqrt[i] =
std::sqrt(my_evalues[i]);
548 if(fabs(diag_isqrt[i]) * condition > max_diag) {
549 diag_isqrt[i] = 1/diag_isqrt[i];
554 return my_evectors.T() * diagmult(diag_isqrt, my_evectors);
const Matrix< Size, Size, Precision > & get_evectors() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: SymEigen.h:483
void compute(const Matrix< R, C, Precision, B > &m)
Perform the eigen decomposition of a matrix.
Definition: SymEigen.h:422
Precision trace(const Matrix< Rows, Cols, Precision, Base > &m)
computes the trace of a square matrix
Definition: helpers.h:432
Matrix< Size, Size, Precision > get_pinv(const double condition=Internal::symeigen_condition_no) const
Calculate (pseudo-)inverse of the matrix.
Definition: SymEigen.h:451
Matrix< Size, C, Precision > backsub(const Matrix< R, C, P, B > &rhs) const
Calculate result of multiplying the (pseudo-)inverse of M by another matrix.
Definition: SymEigen.h:442
Pretty generic SFINAE introspection generator.
Definition: vec_test.cc:21
A vector.
Definition: vector.hh:126
void normalize(Vector< Size, Precision, Base > &&v)
Normalize a vector in place.
Definition: helpers.h:162
Vector< Size, Precision > backsub(const Vector< S, P, B > &rhs) const
Calculate result of multiplying the (pseudo-)inverse of M by a vector.
Definition: SymEigen.h:433
Precision get_determinant() const
Get the determinant of the matrix.
Definition: SymEigen.h:513
A matrix.
Definition: matrix.hh:105
Matrix< Size, Size, Precision > get_sqrtm() const
Calculate the square root of a matrix which is a matrix M such that M.T*M=A.
Definition: SymEigen.h:523
Precision norm_1(const Vector< Size, Precision, Base > &v)
Compute the norm of v.
Definition: helpers.h:114
bool is_posdef() const
Is the matrix positive definite?
Definition: SymEigen.h:495
Vector< Size, Precision > & get_evalues()
Returns the eigenvalues of the matrix.
Definition: SymEigen.h:489
Vector< Size, Precision > get_inv_diag(const double condition) const
Calculates the reciprocals of the eigenvalues of the matrix.
Definition: SymEigen.h:461
Definition: SymEigen.h:56
const Vector< Size, Precision > & get_evalues() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: SymEigen.h:492
Matrix< R, C, P > sqrt(const Matrix< R, C, P, B > &m)
computes a matrix square root of a matrix m by the product form of the Denman and Beavers iteration a...
Definition: helpers.h:350
Definition: size_mismatch.hh:103
bool is_negdef() const
Is the matrix negative definite?
Definition: SymEigen.h:504
Performs eigen decomposition of a matrix.
Definition: SymEigen.h:403
Matrix< Size, Size, Precision > get_isqrtm(const double condition=Internal::symeigen_condition_no) const
Calculate the inverse square root of a matrix which is a matrix M such that M.T*M=A^-1.
Definition: SymEigen.h:539
static void compute(const Matrix< 3, 3, P, B > &m, Matrix< 3, 3, P > &eig, Vector< 3, P > &ev)
Definition: SymEigen.h:148
Matrix< Size, Size, Precision > & get_evectors()
Returns the eigenvectors of the matrix.
Definition: SymEigen.h:479
SymEigen(int m)
Initialise this eigen decomposition but do no immediately perform a decomposition.
Definition: SymEigen.h:411
SymEigen(const Matrix< R, C, Precision, B > &m)
Construct the eigen decomposition of a matrix.
Definition: SymEigen.h:416
Vector< Size, Precision > unit(const Vector< Size, Precision, Base > &v)
Compute a the unit vector .
Definition: helpers.h:153