#pragma once #include "vec.h" #include "mat.h" #include "low_tri_mat.h" namespace cgv { namespace math { template class up_tri_mat { protected: vec _data; unsigned _dim; public: //standard constructor of a upper triangular matrix up_tri_mat() { _dim=0; } //constructs a upper triangular matrix from the upper triangular part of m up_tri_mat(const mat& m) { assert(m.ncols()==m.nrows()); resize(m.ncols()); for(unsigned i =0; i < _dim;i++) { for(unsigned j = i; j < _dim;j++) { operator()(i,j)=m(i,j); } } } //creates a dim x dim upper triangular matrix up_tri_mat(unsigned dim) { resize(dim); fill(0); } up_tri_mat(const up_tri_mat& m) { resize(m.dim()); memcpy(_data,m._data,size()*sizeof(T)); } //create a dim x dim upper triangular matrix with all non-zero elements set to c up_tri_mat(unsigned dim, const T& c) { resize(dim); fill(c); } virtual ~up_tri_mat() { } //resize the matrix to an n x n matrix void resize(unsigned n) { _dim = n; _data.resize(n*(n+1)/2); } operator mat() { mat m(_dim,_dim); for(unsigned i =0; i < _dim; i++) { for(unsigned j = 0; j < _dim; j++) { if(i>j) m(i,j)=0; else m(i,j)=operator()(i,j); } } return m; } operator const mat() const { mat m(_dim,_dim); for(unsigned i =0; i < _dim;i++) { for(unsigned j = 0; j < _dim;j++) { if(i>j) m(i,j)=0; else m(i,j)=operator()(i,j); } } return m; } ///assignment of a matrix with the same element type up_tri_mat& operator = (const up_tri_mat& m) { _dim = m.dim(); _data = m._data; return *this; } //return number of stored elements unsigned size() const { return _data.size(); } //return number of stored elements unsigned dim() const { return _dim; } //returns the number of columns unsigned ncols() const { return _dim; } //returns the number of columns unsigned nrows() const { return _dim; } //fills all upper triangular elements with c void fill(const T& c) { for(unsigned i=0;i < size();i++) { _data[i]=c; } } //access to the element (i,j) T& operator() (unsigned i, unsigned j) { assert( j >= i && j < _dim); return _data[j*(j+1)/2+i]; } //const access to the element (i,j) const T& operator() (unsigned i, unsigned j) const { assert( j >= i && j < _dim); return _data[j*(j+1)/2+i]; } ///in place division by a scalar up_tri_mat& operator /= (const T& s) { T val = (T)s; for(unsigned i = 0; i < size(); i++) _data[i] /= val; return *this; } /// division by a scalar up_tri_mat operator / (const T& s) { up_tri_mat r=(*this); r/=s; return r; } const mat operator*( const up_tri_mat& m2) { assert(m2.nrows() == nrows()); unsigned M = m2.ncols(); mat r(nrows(),M,(T)0); for(unsigned i = 0; i < nrows(); i++) for(unsigned j = i; j < M;j++) for(unsigned k = i; k <= j; k++) r(i,j) += operator()(i,k) * (T)(m2(k,j)); return r; } const mat operator*( const mat& m2) { assert(m2.nrows() == nrows()); unsigned M = m2.ncols(); mat r(nrows(),M,(T)0); for(unsigned i = 0; i < nrows(); i++) for(unsigned j = 0; j < M;j++) for(unsigned k = i; k < nrows(); k++) r(i,j) += operator()(i,k) * (T)(m2(k,j)); return r; } }; //transpose of a matrix m template const low_tri_mat transpose(const up_tri_mat &m) { low_tri_mat r(m.nrows()); for(unsigned j = 0; j < m.ncols();j++) for(unsigned i = j; i < m.nrows();i++) r(i,j) = m(j,i); return r; } //transpose of a matrix m template const up_tri_mat transpose(const low_tri_mat &m) { up_tri_mat r(m.nrows()); for(unsigned j = 0; j < m.ncols();j++) for(unsigned i = j; i < m.nrows();i++) r(j,i) = m(i,j); return r; } template const vec operator*(const up_tri_mat& m1, const vec& v) { assert(m1.ncols() == v.size()); unsigned M = v.size(); vec r(M,(T)0); for(unsigned i = 0; i < m1.nrows(); i++) for(unsigned k = i; k < m1.ncols(); k++) r(i) += m1(i,k) * (T)(v(k)); return r; } template const mat operator*(const mat& m1, const up_tri_mat& m2) { assert(m1.ncols() == m2.nrows()); unsigned M = m2.nrows(); mat r(m1.nrows(),M,(T)0); for(unsigned i = 0; i < m1.nrows(); i++) for(unsigned j = 0; j < M;j++) for(unsigned k = 0; k <= j; k++) r(i,j) += m1(i,k) * (T)(m2(k,j)); return r; } //product of a lower and an upper triangular matrix template const mat operator*(const low_tri_mat& m1, const up_tri_mat& m2) { assert(m1.nrows() == m2.nrows()); mat r(m1.nrows(),m2.nrows(),(T)0); for(unsigned i = 0; i < m1.nrows(); i++) for(unsigned j = 0; j < m1.nrows();j++) { unsigned h = std::min(i,j); for(unsigned k = 0; k <= h; k++) r(i,j) += m1(i,k) * (T)(m2(k,j)); } return r; } //multiplies a permutation matrix from left to apply a rows permutation template mat operator*(const perm_mat& p, const up_tri_mat& m) { mat r=m; return p*r; } //multiplies a permutation matrix from right to apply a rows permutation template mat operator*(const up_tri_mat& m,const perm_mat& p) { mat r=m; return r*p; } ///output of a upper triangular matrix onto an ostream template std::ostream& operator<<(std::ostream& out, const up_tri_mat& m) { for(unsigned i =0;i< m.nrows() ;++i) { unsigned j = 0; for (; j