--- trunk/OOPSE-2.0/src/math/SquareMatrix.hpp 2004/10/13 23:53:40 1567 +++ trunk/OOPSE-2.0/src/math/SquareMatrix.hpp 2004/10/19 23:01:03 1606 @@ -78,24 +78,28 @@ namespace oopse { return m; } - /** Retunrs the inversion of this matrix. */ + /** + * Retunrs the inversion of this matrix. + * @todo need implementation + */ SquareMatrix inverse() { SquareMatrix result; return result; - } + } - - - /** Returns the determinant of this matrix. */ - double determinant() const { - double det; + /** + * Returns the determinant of this matrix. + * @todo need implementation + */ + Real determinant() const { + Real det; return det; } /** Returns the trace of this matrix. */ - double trace() const { - double tmp = 0; + Real trace() const { + Real tmp = 0; for (unsigned int i = 0; i < Dim ; i++) tmp += data_[i][i]; @@ -113,13 +117,13 @@ namespace oopse { return true; } - /** Tests if this matrix is orthogona. */ + /** Tests if this matrix is orthogonal. */ bool isOrthogonal() { SquareMatrix tmp; tmp = *this * transpose(); - return tmp.isUnitMatrix(); + return tmp.isDiagonal(); } /** Tests if this matrix is diagonal. */ @@ -144,7 +148,178 @@ namespace oopse { return true; } + /** @todo need implementation */ + void diagonalize() { + //jacobi(m, eigenValues, ortMat); + } + + /** + * Finds the eigenvalues and eigenvectors of a symmetric matrix + * @param eigenvals a reference to a vector3 where the + * eigenvalues will be stored. The eigenvalues are ordered so + * that eigenvals[0] <= eigenvals[1] <= eigenvals[2]. + * @return an orthogonal matrix whose ith column is an + * eigenvector for the eigenvalue eigenvals[i] + */ + SquareMatrix findEigenvectors(Vector& eigenValues) { + SquareMatrix ortMat; + + if ( !isSymmetric()){ + //throw(); + } + + SquareMatrix m(*this); + jacobi(m, eigenValues, ortMat); + + return ortMat; + } + /** + * Jacobi iteration routines for computing eigenvalues/eigenvectors of + * real symmetric matrix + * + * @return true if success, otherwise return false + * @param a source matrix + * @param w output eigenvalues + * @param v output eigenvectors + */ + bool jacobi(SquareMatrix& a, Vector& w, + SquareMatrix& v); };//end SquareMatrix + +#define ROT(a,i,j,k,l) g=a(i, j);h=a(k, l);a(i, j)=g-s*(h+g*tau);a(k, l)=h+s*(g-h*tau) +#define MAX_ROTATIONS 60 + +template +bool SquareMatrix::jacobi(SquareMatrix& a, Vector& w, + SquareMatrix& v) { + const int N = Dim; + int i, j, k, iq, ip; + Real tresh, theta, tau, t, sm, s, h, g, c; + Real tmp; + Vector b, z; + + // initialize + for (ip=0; ip 4 && (fabs(w(ip))+g) == fabs(w(ip)) + && (fabs(w(iq))+g) == fabs(w(iq))) { + a(ip, iq) = 0.0; + } else if (fabs(a(ip, iq)) > tresh) { + h = w(iq) - w(ip); + if ( (fabs(h)+g) == fabs(h)) { + t = (a(ip, iq)) / h; + } else { + theta = 0.5*h / (a(ip, iq)); + t = 1.0 / (fabs(theta)+sqrt(1.0+theta*theta)); + + if (theta < 0.0) + t = -t; + } + + c = 1.0 / sqrt(1+t*t); + s = t*c; + tau = s/(1.0+c); + h = t*a(ip, iq); + z(ip) -= h; + z(iq) += h; + w(ip) -= h; + w(iq) += h; + a(ip, iq)=0.0; + + for (j=0;j= MAX_ROTATIONS ) + return false; + + // sort eigenfunctions + for (j=0; j= tmp) { + k = i; + tmp = w(k); + } + } + + if (k != j) { + w(k) = w(j); + w(j) = tmp; + for (i=0; i= 0.0 ) numPos++; + if ( numPos < 2 ) for(i=0; i