#pragma once #include "vec.h" #include "mat.h" #include "up_tri_mat.h" namespace cgv{ namespace math{ /** * A diagonal matrix type which internally stores the * elements on the main diagonal in a vector. **/ template struct diag_mat { public: ///pointer to data storage vec _data; public: typedef typename vec::value_type value_type; typedef typename vec::reference reference; typedef typename vec::const_reference const_reference; typedef typename vec::pointer pointer; typedef typename vec::const_pointer const_pointer; typedef typename vec::iterator iterator; typedef typename vec::const_iterator const_iterator; typedef typename vec::reverse_iterator reverse_iterator; typedef typename vec::const_reverse_iterator const_reverse_iterator; typedef iterator diag_iterator; typedef const diag_iterator const_diag_iterator; typedef std::reverse_iterator reverse_diag_iterator; typedef std::reverse_iterator const_reverse_diag_iterator; iterator begin(){return _data.begin();} iterator end(){return _data.end();} const_iterator begin() const{return _data.begin();} const_iterator end() const{return _data.end();} reverse_iterator rbegin(){return _data.rbegin();} reverse_iterator rend(){return _data.rend();} const_reverse_iterator rbegin() const{return _data.rbegin();} const_reverse_iterator rend() const {return _data.rend();} diag_iterator diag_begin(){return _data.begin();} diag_iterator diag_end(){return _data.end();} const_diag_iterator diag_begin() const{return _data.begin();} const_diag_iterator diag_end() const{return _data.end();} reverse_diag_iterator diag_rbegin(){return _data.rbegin();} reverse_diag_iterator diag_rend(){return _data.rend();} const_reverse_diag_iterator diag_rbegin() const{return _data.rbegin();} const_reverse_diag_iterator diag_rend() const {return _data.rend();} ///size of storage unsigned size() const { return _data.size(); } ///number of rows unsigned nrows() const { return size(); } ///number of columns unsigned ncols() const { return size(); } ///standard constructor diag_mat() { } ///creates nxn diagonal matrix explicit diag_mat(unsigned n):_data(n) { } ///creates nxn diagonal matrix and set all diagonal elements to c diag_mat(unsigned n, const T& c) { resize(n); fill(c); } //creates nxn diagonal matrix from array containing the diagonal elements diag_mat(unsigned n, const T* marray):_data(n,marray) { } ///creates a diagonal matrix and set the diagonal vector to dv diag_mat(const vec& dv):_data(dv) { } ///creates a diagonal matrix and set the diagonal vector to diagonal entries of m diag_mat(const mat& m) { int n = std::min(m.ncols(),m.nrows()); resize(n); for(int i =0; i < n; i++) _data[i]=m(i,i); } ///copy constructor diag_mat(const diag_mat& m) { _data=m._data; } ///destructor virtual ~diag_mat() { } ///cast into array of element type operator T*() { return (T*)_data; } ///cast into array of const element type operator const T*() const { return (const T*)_data; } ///create sub diagonal matrix d(top_left)...d(top_left+size) diag_mat sub_mat(unsigned top_left, unsigned size) const { diag_mat D(size); for (unsigned int i=0; i() const { mat m; m.zeros(size(),size()); for(unsigned i =0; i < size();i++) m(i,i)=operator()(i); return m; } //resize the diagonal matrix to nxn void resize(unsigned n) { _data.resize(n); } ///set diagonal matrix to identity void identity() { fill((T)1); } ///fills all diagonal entries with c void fill(const T& c) { for(unsigned i=0;i < size();i++) { _data[i]=c; } } ///fills all diagonal entries with zero void zeros() { fill((T)0); } ///exchange diagonal elements i and j void exchange_diagonal_elements(unsigned i, unsigned j) { std::swap(_data[i],_data[j]); } ///const access to the ith diagonal element const T& operator() (unsigned i) const { return _data[i]; } ///non const access to the ith diagonal element T& operator() (unsigned i) { return _data[i]; } ///returns true because diagonal matrices are always square bool is_square() { return true; } //transpose (does nothing) void transpose(){} ///assignment of a matrix with the same element type diag_mat& operator = (const diag_mat& m) { _data =m._data; return *this; } ///assignment of a matrix with a different element type template diag_mat& operator = (const diag_mat& m) { resize(m.size()); for(unsigned i = 0; i < size(); i++) _data[i]=(T)m(i); return *this; } ///assignment of a vector with a vector ///to set the diagonal template diag_mat& operator = (const vec& v) { _data=v; return *this; } ///assignment of a scalar s to each element of the matrix diag_mat& operator = (const T& s) { fill (s); return *this; } ///returns the frobenius norm of matrix m T frobenius_norm() const { T n=0; for(int i =0; i < size();i++) n+=_data[i]*_data[i]; return (T)sqrt((double)n); } ///set dim x dim identity matrix void identity(unsigned dim) { resize(dim); for(unsigned i = 0; i < size();++i) _data[i]=1; } ///set zero matrix void zero() { fill(0); } ///in place addition of diagonal matrix diag_mat& operator+=(const diag_mat& d) { assert(d.nrows() == nrows()); _data += d._data; return *this; } ///in place subtraction of diagonal matrix diag_mat& operator-=(const diag_mat& d) { assert(d.nrows() == nrows()); _data -= d._data; return *this; } ///in place multiplication with scalar s diag_mat& operator*=(const T& s) { _data *=s; return *this; } ///multiplication with scalar s diag_mat operator*(const T& s) const { diag_mat r=*this; r*=s; return r; } ///addition of diagonal matrix diag_mat operator+(const diag_mat& d) const { diag_mat r=*this; r += d; return r; } ///subtraction of diagonal matrix diag_mat operator-(const diag_mat& d) const { diag_matr = *this; r-= d; return r; } ///multiplication with vector vec operator*(const vec& v) const { assert(v.dim() == ncols()); vec r(size()); for(unsigned i = 0; i < size();i++) r(i) = _data[i]*v(i); return r; } ///matrix multiplication of matrix m by a diagonal matrix s const up_tri_mat operator*( const up_tri_mat& m) { assert(m.nrows() == size()); up_tri_mat r(size()); for(unsigned i = 0; i < size(); i++) for(unsigned j = 0; j < m.ncols();j++) r(i,j) = operator()(i)*m(i,j); return r; } ///cast into full matrix type operator mat() { mat m(size(),size(),(T)0); for(unsigned i = 0; i < size();i++) { m(i,i)=_data[i]; } return m; } }; //matrix multiplication of matrix m by a diagonal matrix s template const mat operator*(const mat& m,const diag_mat& s) { assert(m.ncols() == s.size()); mat r(m.nrows(),s.size()); for(unsigned i = 0; i < m.nrows(); i++) for(unsigned j = 0; j < s.size();j++) r(i,j) = s(j)*m(i,j); return r; } ///multiplication of scalar s and diagonal matrix m template const diag_mat operator*(const T& s, const diag_mat& m) { return m*s; } ///matrix multiplication of diagonal matrix s and m template const diag_mat operator*(const diag_mat& s, const diag_mat& m) { assert(m.size() == s.size()); diag_mat r(s.size()); for(unsigned i = 0; i < s.size(); i++) r(i) = s(i)*m(i); return r; } ///multiplies a permutation matrix from left to apply a rows permutation template mat operator*(const perm_mat& p, const diag_mat& m) { mat r=m; return p*r; } ///multiplies a permutation matrix from right to apply a rows permutation template mat operator*(const diag_mat& m,const perm_mat& p) { mat r=m; return r*p; } ///matrix multiplication of matrix m by a diagonal matrix s template const mat operator*(const diag_mat& s, const mat& m) { assert(m.nrows() == s.size()); mat r(s.size(),m.ncols()); for(unsigned i = 0; i < s.size(); i++) for(unsigned j = 0; j < m.ncols();j++) r(i,j) = s(i)*m(i,j); return r; } ///matrix multiplication of upper triangular matrix m by a diagonal matrix s template const up_tri_mat operator*(const up_tri_mat& m,const diag_mat& s) { assert(m.ncols() == s.size()); up_tri_mat r(s.size()); for(unsigned i = 0; i < m.nrows(); i++) for(unsigned j = i; j < s.size();j++) r(i,j) = s(j)*m(i,j); return r; } ///output of a diagonal matrix onto an ostream template std::ostream& operator<<(std::ostream& out, const diag_mat& m) { for (int i=0;i<(int)m.size();++i) out << m(i)<<" "; return out; } ///input of a diagonal matrix from an istream template std::istream& operator>>(std::istream& in, diag_mat& m) { assert(m.size() > 0); for (int i=0;i<(int)m.size();++i) in >> m(i); return in; } } }