--- trunk/OOPSE-3.0/src/math/SquareMatrix.hpp 2004/10/13 06:51:09 1563 +++ trunk/OOPSE-3.0/src/math/SquareMatrix.hpp 2004/10/17 01:19:11 1586 @@ -32,7 +32,7 @@ #ifndef MATH_SQUAREMATRIX_HPP #define MATH_SQUAREMATRIX_HPP -#include "Vector3d.hpp" +#include "math/RectMatrix.hpp" namespace oopse { @@ -43,7 +43,7 @@ namespace oopse { * @template Dim the dimension of the square matrix */ template - class SquareMatrix{ + class SquareMatrix : public RectMatrix { public: /** default constructor */ @@ -53,345 +53,42 @@ namespace oopse { data_[i][j] = 0.0; } - /** Constructs and initializes every element of this matrix to a scalar */ - SquareMatrix(double s) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] = s; - } - /** copy constructor */ - SquareMatrix(const SquareMatrix& m) { - *this = m; + SquareMatrix(const RectMatrix& m) : RectMatrix(m) { } - /** destructor*/ - ~SquareMatrix() {} - /** copy assignment operator */ - SquareMatrix& operator =(const SquareMatrix& m) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] = m.data_[i][j]; - } - - /** - * Return the reference of a single element of this matrix. - * @return the reference of a single element of this matrix - * @param i row index - * @param j colum index - */ - double& operator()(unsigned int i, unsigned int j) { - return data_[i][j]; - } - - /** - * Return the value of a single element of this matrix. - * @return the value of a single element of this matrix - * @param i row index - * @param j colum index - */ - double operator()(unsigned int i, unsigned int j) const { - return data_[i][j]; - } - - /** - * Returns a row of this matrix as a vector. - * @return a row of this matrix as a vector - * @param row the row index - */ - Vector getRow(unsigned int row) { - Vector v; - - for (unsigned int i = 0; i < Dim; i++) - v[i] = data_[row][i]; - - return v; - } - - /** - * Sets a row of this matrix - * @param row the row index - * @param v the vector to be set - */ - void setRow(unsigned int row, const Vector& v) { - Vector v; - - for (unsigned int i = 0; i < Dim; i++) - data_[row][i] = v[i]; - } - - /** - * Returns a column of this matrix as a vector. - * @return a column of this matrix as a vector - * @param col the column index - */ - Vector getColum(unsigned int col) { - Vector v; - - for (unsigned int i = 0; i < Dim; i++) - v[i] = data_[i][col]; - - return v; - } - - /** - * Sets a column of this matrix - * @param col the column index - * @param v the vector to be set - */ - void setColum(unsigned int col, const Vector& v){ - Vector v; - - for (unsigned int i = 0; i < Dim; i++) - data_[i][col] = v[i]; - } - - /** Negates the value of this matrix in place. */ - inline void negate() { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] = -data_[i][j]; - } - - /** - * Sets the value of this matrix to the negation of matrix m. - * @param m the source matrix - */ - inline void negate(const SquareMatrix& m) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] = -m.data_[i][j]; - } - - /** - * Sets the value of this matrix to the sum of itself and m (*this += m). - * @param m the other matrix - */ - inline void add( const SquareMatrix& m ) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] += m.data_[i][j]; - } - - /** - * Sets the value of this matrix to the sum of m1 and m2 (*this = m1 + m2). - * @param m1 the first matrix - * @param m2 the second matrix - */ - inline void add( const SquareMatrix& m1, const SquareMatrix& m2 ) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] = m1.data_[i][j] + m2.data_[i][j]; - } - - /** - * Sets the value of this matrix to the difference of itself and m (*this -= m). - * @param m the other matrix - */ - inline void sub( const SquareMatrix& m ) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] -= m.data_[i][j]; - } - - /** - * Sets the value of this matrix to the difference of matrix m1 and m2 (*this = m1 - m2). - * @param m1 the first matrix - * @param m2 the second matrix - */ - inline void sub( const SquareMatrix& m1, const Vector &m2){ - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] = m1.data_[i][j] - m2.data_[i][j]; - } - - /** - * Sets the value of this matrix to the scalar multiplication of itself (*this *= s). - * @param s the scalar value - */ - inline void mul( double s ) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] *= s; - } - - /** - * Sets the value of this matrix to the scalar multiplication of matrix m (*this = s * m). - * @param s the scalar value - * @param m the matrix - */ - inline void mul( double s, const SquareMatrix& m ) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] = s * m.data_[i][j]; - } - - /** - * Sets the value of this matrix to the multiplication of this matrix and matrix m - * (*this = *this * m). - * @param m the matrix - */ - inline void mul(const SquareMatrix& m ) { - SquareMatrix tmp(*this); - - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) { - - data_[i][j] = 0.0; - for (unsigned int k = 0; k < Dim; k++) - data_[i][j] = tmp.data_[i][k] * m.data_[k][j] - } - } - - /** - * Sets the value of this matrix to the left multiplication of matrix m into itself - * (*this = m * *this). - * @param m the matrix - */ - inline void leftmul(const SquareMatrix& m ) { - SquareMatrix tmp(*this); - - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) { - - data_[i][j] = 0.0; - for (unsigned int k = 0; k < Dim; k++) - data_[i][j] = m.data_[i][k] * tmp.data_[k][j] - } - } - - /** - * Sets the value of this matrix to the multiplication of matrix m1 and matrix m2 - * (*this = m1 * m2). - * @param m1 the first matrix - * @param m2 the second matrix - */ - inline void mul(const SquareMatrix& m1, - const SquareMatrix& m2 ) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) { - - data_[i][j] = 0.0; - for (unsigned int k = 0; k < Dim; k++) - data_[i][j] = m1.data_[i][k] * m2.data_[k][j] - } - - } - - /** - * Sets the value of this matrix to the scalar division of itself (*this /= s ). - * @param s the scalar value - */ - inline void div( double s) { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j = 0; j < Dim; j++) - data_[i][j] /= s; - } - - inline SquareMatrix& operator=(const SquareMatrix& v) { - if (this == &v) - return *this; - - for (unsigned int i = 0; i < Dim; i++) - data_[i] = v[i]; - + SquareMatrix& operator =(const RectMatrix& m) { + RectMatrix::operator=(m); return *this; } - - /** - * Sets the value of this matrix to the scalar division of matrix v1 (*this = v1 / s ). - * @paran v1 the source matrix - * @param s the scalar value - */ - inline void div( const SquareMatrix& v1, double s ) { - for (unsigned int i = 0; i < Dim; i++) - data_[i] = v1.data_[i] / s; - } + + /** Retunrs an identity matrix*/ - /** - * Multiples a scalar into every element of this matrix. - * @param s the scalar value - */ - SquareMatrix& operator *=(const double s) { - this->mul(s); - return *this; - } - - /** - * Divides every element of this matrix by a scalar. - * @param s the scalar value - */ - SquareMatrix& operator /=(const double s) { - this->div(s); - return *this; - } - - /** - * Sets the value of this matrix to the sum of the other matrix and itself (*this += m). - * @param m the other matrix - */ - SquareMatrix& operator += (const SquareMatrix& m) { - add(m); - return *this; - } - - /** - * Sets the value of this matrix to the differerence of itself and the other matrix (*this -= m) - * @param m the other matrix - */ - SquareMatrix& operator -= (const SquareMatrix& m){ - sub(m); - return *this; - } - - /** set this matrix to an identity matrix*/ - - void identity() { + static SquareMatrix identity() { + SquareMatrix m; + for (unsigned int i = 0; i < Dim; i++) - for (unsigned int i = 0; i < Dim; i++) + for (unsigned int j = 0; j < Dim; j++) if (i == j) - data_[i][j] = 1.0; + m(i, j) = 1.0; else - data_[i][j] = 0.0; - } + m(i, j) = 0.0; - /** Sets the value of this matrix to the inversion of itself. */ - void inverse() { - inverse(*this); + return m; } - /** - * Sets the value of this matrix to the inversion of other matrix. - * @ param m the source matrix - */ - void inverse(const SquareMatrix& m); - - /** Sets the value of this matrix to the transpose of itself. */ - void transpose() { - for (unsigned int i = 0; i < Dim - 1; i++) - for (unsigned int j = i; j < Dim; j++) - std::swap(data_[i][j], data_[j][i]); - } + /** Retunrs the inversion of this matrix. */ + SquareMatrix inverse() { + SquareMatrix result; - /** - * Sets the value of this matrix to the transpose of other matrix. - * @ param m the source matrix - */ - void transpose(const SquareMatrix& m) { - - if (this == &m) { - transpose(); - } else { - for (unsigned int i = 0; i < Dim; i++) - for (unsigned int j =0; j < Dim; j++) - data_[i][j] = m.data_[i][j]; - } - } + return result; + } /** Returns the determinant of this matrix. */ double determinant() const { - + double det; + return det; } /** Returns the trace of this matrix. */ @@ -408,26 +105,26 @@ namespace oopse { bool isSymmetric() const { for (unsigned int i = 0; i < Dim - 1; i++) for (unsigned int j = i; j < Dim; j++) - if (fabs(data_[i][j] - data_[j][i]) > epsilon) + if (fabs(data_[i][j] - data_[j][i]) > oopse::epsilon) return false; return true; } - /** Tests if this matrix is orthogona. */ - bool isOrthogonal() const { - SquareMatrix t(*this); + /** Tests if this matrix is orthogonal. */ + bool isOrthogonal() { + SquareMatrix tmp; - t.transpose(); + tmp = *this * transpose(); - return isUnitMatrix(*this * t); + return tmp.isDiagonal(); } /** Tests if this matrix is diagonal. */ bool isDiagonal() const { for (unsigned int i = 0; i < Dim ; i++) for (unsigned int j = 0; j < Dim; j++) - if (i !=j && fabs(data_[i][j]) > epsilon) + if (i !=j && fabs(data_[i][j]) > oopse::epsilon) return false; return true; @@ -439,92 +136,182 @@ namespace oopse { return false; for (unsigned int i = 0; i < Dim ; i++) - if (fabs(data_[i][i] - 1) > epsilon) + if (fabs(data_[i][i] - 1) > oopse::epsilon) return false; return true; + } + + void diagonalize() { + jacobi(m, eigenValues, ortMat); } - - protected: - double data_[Dim][Dim]; /**< matrix element */ + /** + * 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(const SquareMatrix& a, Vector& w, + SquareMatrix& v); };//end SquareMatrix - - /** Negate the value of every element of this matrix. */ - template - inline SquareMatrix operator -(const SquareMatrix& m) { - SquareMatrix result(m); - result.negate(); +#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 - return result; +template +bool SquareMatrix::jacobi(const SquareMatrix& a, Vector& w, + SquareMatrix& v) { + const int N = Dim; + int i, j, k, iq, ip; + double tresh, theta, tau, t, sm, s, h, g, c; + double tmp; + Vector b, z; + + // initialize + for (ip=0; ip - inline SquareMatrix operator + (const SquareMatrix& m1, - const SquareMatrix& m2) { - SquareMatrixresult; + for (ip=0; ip - inline SquareMatrix operator - (const SquareMatrix& m1, - const SquareMatrix& m2) { - SquareMatrixresult; + if (i < 4) + tresh = 0.2*sm/(9); + else + tresh = 0.0; - result.sub(m1, m2); + for (ip=0; ip<2; ip++) { + for (iq=ip+1; iq 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)); - return result; - } - - /** - * Return the multiplication of two matrixes (m1 * m2). - * @return the multiplication of two matrixes - * @param m1 the first matrix - * @param m2 the second matrix - */ - template - inline SquareMatrix operator *(const SquareMatrix& m1, - const SquareMatrix& m2) { - SquareMatrix result; + if (theta < 0.0) + t = -t; + } - result.mul(m1, m2); + 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); + } + } - /** - * Return the multiplication of matrixes m and vector v (m * v). - * @return the multiplication of matrixes and vector - * @param m the matrix - * @param v the vector - */ - template - inline Vector operator *(const SquareMatrix& m, - const SquareMatrix& v) { - Vector result; + if (k != j) { + w(k) = w(j); + w(j) = tmp; + for (i=0; i= 0.0 ) numPos++; + if ( numPos < 2 ) for(i=0; i