diff --git a/vcg/math/lin_algebra.h b/vcg/math/lin_algebra.h new file mode 100644 index 00000000..0f9c8422 --- /dev/null +++ b/vcg/math/lin_algebra.h @@ -0,0 +1,178 @@ +#include + +namespace vcg +{ + /** \addtogroup math */ + /* @{ */ + + /*! + * Computes all eigenvalues and eigenvectors of a real symmetric matrix . + * On output, elements of the input matrix above the diagonal are destroyed. + * \param d returns the eigenvalues of a. + * \param v is a matrix whose columns contain, the normalized eigenvectors + * \param nrot returns the number of Jacobi rotations that were required. + */ + template + static void Jacobi(Matrix44 &w, Point4 &d, Matrix44 &v, int &nrot) + { + int j,iq,ip,i; + //assert(w.IsSymmetric()); + TYPE tresh, theta, tau, t, sm, s, h, g, c; + Point4 b, z; + + v.SetIdentity(); + + for (ip=0;ip<4;++ip) //Initialize b and d to the diagonal of a. + { + b[ip]=d[ip]=w[ip][ip]; + z[ip]=0.0; //This vector will accumulate terms of the form tapq as in equation (11.1.14). + } + nrot=0; + for (i=0;i<50;i++) + { + sm=0.0; + for (ip=0;ip<3;++ip) // Sum off diagonal elements + { + for (iq=ip+1;iq<4;++iq) + sm += fabs(w[ip][iq]); + } + if (sm == 0.0) //The normal return, which relies on quadratic convergence to machine underflow. + { + return; + } + if (i < 4) + tresh=0.2*sm/(4*4); //...on the first three sweeps. + else + tresh=0.0; //...thereafter. + for (ip=0;ip<4-1;++ip) + { + for (iq=ip+1;iq<4;iq++) + { + g=100.0*fabs(w[ip][iq]); + //After four sweeps, skip the rotation if the off-diagonal element is small. + if(i>4 && (float)(fabs(d[ip])+g) == (float)fabs(d[ip]) && (float)(fabs(d[iq])+g) == (float)fabs(d[iq])) + w[ip][iq]=0.0; + else if (fabs(w[ip][iq]) > tresh) + { + h=d[iq]-d[ip]; + if ((float)(fabs(h)+g) == (float)fabs(h)) + t=(w[ip][iq])/h; //t =1/(2#) + else + { + theta=0.5*h/(w[ip][iq]); //Equation (11.1.10). + 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*w[ip][iq]; + z[ip] -= h; + z[iq] += h; + d[ip] -= h; + d[iq] += h; + w[ip][iq]=0.0; + for (j=0;j<=ip-1;j++) { //Case of rotations 1 <= j < p. + JacobiRotate(w,s,tau,j,ip,j,iq) ; + } + for (j=ip+1;j<=iq-1;j++) { //Case of rotations p < j < q. + JacobiRotate(w,s,tau,ip,j,j,iq); + } + for (j=iq+1;j<4;j++) { //Case of rotations q< j <= n. + JacobiRotate(w,s,tau,ip,j,iq,j); + } + for (j=0;j<4;j++) { + JacobiRotate(w,s,tau,j,ip,j,iq); + } + ++nrot; + } + } + } + for (ip=0;ip<4;ip++) + { + b[ip] += z[ip]; + d[ip]=b[ip]; //Update d with the sum of ta_pq , + z[ip]=0.0; //and reinitialize z. + } + } + }; + + /*! + * + */ + template< typename TYPE > + void JacobiRotate(Matrix44 &A, TYPE s, TYPE tau, int i,int j,int k,int l) + { + TYPE g=A[i][j]; + TYPE h=A[k][l]; + A[i][j]=g-s*(h+g*tau); + A[k][l]=h+s*(g-h*tau); + }; + + /*! + * Given a matrix Am×n, this routine computes its singular value decomposition, + * i.e. A=U·W·VT. The matrix A will be destroyed! + * \param A ... + * \param W the diagonal matrix of singular values W, stored as a vector W[1...N] + * \param V the matrix V (not the transpose VT) + */ + template + static void SingularValueDecomposition(MATRIX_TYPE &A, typename MATRIX_TYPE::ScalarType *W, MATRIX_TYPE &V) + { + typedef typename MATRIX_TYPE::ScalarType ScalarType; + + }; + + + /*! + * Solves A·X = B for a vector X, where A is specified by the matrices Um×n, + * Wn×1 and Vn×n as returned by SingularValueDecomposition. + * No input quantities are destroyed, so the routine may be called sequentially with different b’s. + * \param x is the output solution vector (xn×1) + * \param b is the input right-hand side (bn×1) + */ + template + static void SingularValueBacksubstitution(const MATRIX_TYPE &U, + const typename MATRIX_TYPE::ScalarType *W, + const MATRIX_TYPE &V, + typename MATRIX_TYPE::ScalarType *x, + const typename MATRIX_TYPE::ScalarType *b) + { + unsigned int jj, j, i; + ScalarType s; + ScalarType tmp = new ScalarType[U._columns]; + for (j=0; j + inline TYPE pythagora(TYPE a, TYPE b) + { + TYPE abs_a = fabs(a); + TYPE abs_b = fabs(b); + if (abs_a > abs_b) + return abs_a*sqrt(1.0+sqr(abs_b/abs_a)); + else + return (abs_b == 0.0 ? 0.0 : abs_b*sqrt(1.0+sqr(abs_a/abs_b))); + }; + + /*! @} */ +}; // end of namespace \ No newline at end of file diff --git a/vcg/math/matrix.h b/vcg/math/matrix.h new file mode 100644 index 00000000..af39a425 --- /dev/null +++ b/vcg/math/matrix.h @@ -0,0 +1,557 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include +#include +#include +#include +#include + + +namespace vcg +{ + /** \addtogroup math */ + /* @{ */ + +/*! + * This class represent a generic m×n matrix. The class is templated over the scalar type field. + * @param TYPE (Templete Parameter) Specifies the ScalarType field. + */ + template + class Matrix + { + + public: + typedef TYPE ScalarType; + + /*! + * Default constructor + * All the elements are initialized to zero. + * \param m the number of matrix rows + * \param n the number of matrix columns + */ + Matrix(unsigned int m, unsigned int n) + { + _rows = m; + _columns = n; + _data = new ScalarType[m*n]; + memset(_data, ScalarType(0.0), m*n*sizeof(ScalarType)); + }; + + /*! + * Constructor + * The matrix elements are initialized with the values of the elements in \i values. + * \param m the number of matrix rows + * \param n the number of matrix columns + * \param values the values of the matrix elements + */ + Matrix(unsigned int m, unsigned int n, TYPE *values) + { + _rows = m; + _columns = n; + _data = new ScalarType[m*n]; + unsigned int i; + for (i=0; i<_rows*_columns; i++) + _data[i] = values[i]; + }; + + /*! + * Copy constructor + * The matrix elements are initialized with the value of the corresponding element in \i m + * \param m the matrix to be copied + */ + Matrix(const Matrix &m) + { + _rows = m._rows; + _columns = m._columns; + _data = new ScalarType[_rows*_columns]; + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] = m._data[i]; + }; + + /*! + * Default destructor + */ + ~Matrix() + { + delete []_data; + }; + + /*! + * Number of columns + */ + inline unsigned int ColumnsNumber() + { + return _columns; + }; + + + /*! + * Number of rows + */ + inline unsigned int RowsNumber() + { + return _rows; + }; + + /*! + * Equality operator. + * \param m + * \return true iff the matrices have same size and its elements have same values. + */ + bool operator==(const Matrix &m) const + { + if (_rows==m._rows && _columns==m._columns) + { + bool result = true; + for (unsigned int i=0; i<_rows*_columns && result; i++) + result = (_data[i]==m._data[i]); + return result; + } + return false; + }; + + /*! + * Inequality operator + * \param m + * \return true iff the matrices have different size or if their elements have different values. + */ + bool operator!=(const Matrix &m) const + { + if (_rows==m._rows && _columns==m._columns) + { + bool result = false; + for (unsigned int i=0; i<_rows*_columns && !result; i++) + result = (_data[i]!=m._data[i]); + return result; + } + return true; + }; + + /*! + * Return the element stored in the i-th rows at the j-th column + * \param i the row index + * \param j the column index + * \return the element + */ + inline TYPE ElementAt(unsigned int i, unsigned int j) + { + assert(i>=0 && i<_rows); + assert(j>=0 && j<_columns); + return _data[i*_columns+j]; + }; + + /*! + * Calculate and return the matrix determinant (Laplace) + * \return the matrix determinant + */ + TYPE Determinant() const + { + assert(_rows == _columns); + switch (_rows) + { + case 2: + { + return _data[0]*_data[3]-_data[1]*_data[2]; + break; + }; + case 3: + { + return _data[0]*(_data[4]*_data[8]-_data[5]*_data[7]) - + _data[1]*(_data[3]*_data[8]-_data[5]*_data[6]) + + _data[2]*(_data[3]*_data[7]-_data[4]*_data[6]) ; + break; + }; + default: + { + // da migliorare: si puo' cercare la riga/colonna con maggior numero di zeri + ScalarType det = 0; + for (unsigned int j=0; j<_columns; j++) + if (_data[j]!=0) + det += _data[j]*this->Cofactor(0, j); + + return det; + } + }; + }; + + /*! + * Return the cofactor Ai,j of the ai,j element + * \return ... + */ + TYPE Cofactor(unsigned int i, unsigned int j) const + { + assert(_rows == _columns); + assert(_rows>2); + TYPE *values = new TYPE[(_rows-1)*(_columns-1)]; + unsigned int u, v, p, q, s, t; + for (u=0, p=0, s=0, t=0; u<_rows; u++, t+=_rows) + { + if (i==u) + continue; + + for (v=0, q=0; v<_columns; v++) + { + if (j==v) + continue; + values[s+q] = _data[t+v]; + q++; + } + p++; + s+=(_rows-1); + } + Matrix temp(_rows-1, _columns-1, values); + return (pow(-1, i+j)*temp.Determinant()); + }; + + /*! + * Subscript operator: + * \param i the index of the row + * \return a reference to the i-th matrix row + */ + inline TYPE* operator[](const unsigned int i) + { + assert(i>=0 && i<_columns); + return _data + i*_columns; + }; + + /*! + * Const subscript operator + * \param i the index of the row + * \return a reference to the i-th matrix row + */ + inline const TYPE* operator[](const unsigned int i) const + { + assert(i>=0 && i<_columns); + return _data + i*_columns; + }; + + /*! + * Get the j-th column on the matrix. + * \param j the column index. + * \return the reference to the column elements. + */ + TYPE* GetColumn(const unsigned int j) + { + assert(j>=0 && j<_columns); + ScalarType *v = new ScalarType[_columns]; + unsigned int i, p; + for (i=0, p=j; i<_rows; i++, p+=_columns) + v[i] = _data[p]; + return v; + }; + + /*! + * Get the i-th row on the matrix. + * \param i the column index. + * \return the reference to the row elements. + */ + TYPE* GetRow(const unsigned int i) + { + assert(i>=0 && i<_rows); + ScalarType *v = new ScalarType[_rows]; + unsigned int j, p; + for (j=0, p=i*_columns; j<_columns; j++, p++) + v[j] = _data[p]; + return v; + }; + + /*! + * Assignment operator + * \param m ... + */ + Matrix& operator=(const Matrix &m) + { + if (this != &m) + { + assert(_rows == m._rows); + assert(_columns == m._columns); + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] = m._data[i]; + } + return *this; + }; + + /*! + * Adds a matrix m to this matrix. + * \param m reference to matrix to add to this + * \return the matrix sum. + */ + Matrix& operator+=(const Matrix &m) + { + assert(_rows == m._rows); + assert(_columns == m._columns); + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] += m._data[i]; + return *this; + }; + + /*! + * Subtracts a matrix m to this matrix. + * \param m reference to matrix to subtract + * \return the matrix difference. + */ + Matrix& operator-=(const Matrix &m) + { + assert(_rows == m._rows); + assert(_columns == m._columns); + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] -= m._data[i]; + return *this; + }; + + /*! + * (Modifier) Add to each element of this matrix the scalar constant k. + * \param k the scalar constant + * \return the modified matrix + */ + Matrix& operator+=(const TYPE k) + { + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] += k; + return *this; + }; + + /*! + * (Modifier) Subtract from each element of this matrix the scalar constant k. + * \param k the scalar constant + * \return the modified matrix + */ + Matrix& operator-=(const TYPE k) + { + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] -= k; + return *this; + }; + + /*! + * (Modifier) Multiplies each element of this matrix by the scalar constant k. + * \param k the scalar constant + * \return the modified matrix + */ + Matrix& operator*=(const TYPE k) + { + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] *= k; + return *this; + }; + + /*! + * (Modifier) Divides each element of this matrix by the scalar constant k. + * \param k the scalar constant + * \return the modified matrix + */ + Matrix& operator/=(const TYPE k) + { + assert(k!=0); + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] /= k; + return *this; + }; + + /*! + * Matrix multiplication: calculates the cross product. + * \param reference to the matrix to multiply by + * \result the matrix product + */ + Matrix operator*(const Matrix &m) + { + assert(_columns == m._rows); + Matrix result(_rows, m._columns); + unsigned int i, j, k, p, q, r; + for (i=0, p=0, r=0; i operator+(const TYPE k) + { + Matrix result(_rows, _columns); + for (unsigned int i=0; i<_rows*_columns; i++) + result._data[i] = _data[i]+k; + return result; + }; + + /*! + * Scalar difference. + * \param k + * \return the resultant matrix + */ + Matrix operator-(const TYPE k) + { + Matrix result(_rows, _columns); + for (unsigned int i=0; i<_rows*_columns; i++) + results._data[i] = _data[i]-k; + return result; + }; + + /*! + * Negate all matrix elements + * \return ... + */ + Matrix operator-() const + { + Matrix result(_rows, _columns, _data); + for (unsigned int i=0; i<_columns*_rows; i++) + result._data[i] = -1*_data[i]; + return result; + }; + + /*! + * Scalar multiplication. + * \param k value to multiply every member by + * \return the resultant matrix + */ + Matrix operator*(const TYPE k) + { + Matrix result(_rows, _columns); + for (unsigned int i=0; i<_rows*_columns; i++) + results._data[i] = _data[i]*k; + return result; + }; + + /*! + * Scalar division. + * \param k value to divide every member by + * \return the resultant matrix + */ + Matrix operator/(const TYPE k) + { + Matrix result(_rows, _columns); + for (unsigned int i=0; i<_rows*_columns; i++) + results._data[i] = _data[i]/k; + return result; + }; + + + /*! + * Set all the matrix elements to zero. + */ + void SetZero() + { + for (unsigned int i=0; i<_rows*_columns; i++) + _data[i] = ScalarType(0.0); + }; + + /*! + * Set the values of j-th column to v[j] + * \param j the column index + * \param v ... + */ + void SetColumn(const unsigned int j, TYPE* v) + { + assert(j>=0 && j<_columns); + unsigned int i, p; + for (i=0, p=0; i<_rows; i++, p+=_columns) + _data[p] = v[i]; + }; + + /*! + * Set the elements of the i-th row to v[j] + * \param i the row index + * \param v ... + */ + void SetRow(const unsigned int i, TYPE* v) + { + assert(i>=0 && i<_rows); + unsigned int j, p; + for (j=0, p=i*_rows; j<_columns; j++, p++) + _data[p] = v[j]; + }; + + /*! + * Resize the current matrix. + * \param m the number of matrix rows. + * \param n the number of matrix columns. + */ + void Resize(const unsigned int m, const unsigned int n) + { + assert(m>=2); + assert(n>=2); + _rows = m; + _columns = n; + delete []_data; + _data = new ScalarType[m*n]; + for (unsigned int i=0; i