/*---------------------------------------------------------------------------* * IT++ * *---------------------------------------------------------------------------* * Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger, * * Tobias Ringström, and Jonas Samuelsson. * * * * Permission to use, copy, modify, and distribute this software and its * * documentation under the terms of the GNU General Public License is hereby * * granted. No representations are made about the suitability of this * * software for any purpose. It is provided "as is" without expressed or * * implied warranty. See the GNU General Public License for more details. * *---------------------------------------------------------------------------*/ /*! \file \brief Sparse Matrix Class Definitions \author Tony Ottosson and Tobias Ringström 1.11 2003/06/06 10:16:12 */ #ifndef __smat_h #define __smat_h #include "itconfig.h" #include "base/svec.h" #include "base/vec.h" #include "base/mat.h" namespace itpp { // Declaration of class Vec template class Vec; // Declaration of class Mat template class Mat; // Declaration of class Sparse_Vec template class Sparse_Vec; // Declaration of class Sparse_Mat template class Sparse_Mat; // ------------------------ Sparse_Mat Friends ------------------------------------- //! m1+m2 where m1 and m2 are sparse matrices template Sparse_Mat operator+(const Sparse_Mat &m1, const Sparse_Mat &m2); //! m1*m2 where m1 and m2 are sparse matrices template Sparse_Mat operator*(const Sparse_Mat &m1, const Sparse_Mat &m2); //! m*v where m is a sparse matrix and v is a full column vector template Vec operator*(const Sparse_Mat &m, const Vec &v); //! v'*m where m is a sparse matrix and v is a full column vector template Vec operator*(const Vec &v, const Sparse_Mat &m); //! m'*m where m is a sparse matrix template Mat trans_mult(const Sparse_Mat &m); //! m'*m where m is a sparse matrix template Sparse_Mat trans_mult_s(const Sparse_Mat &m); //! m1'*m2 where m1 and m2 are sparse matrices template Sparse_Mat trans_mult(const Sparse_Mat &m1, const Sparse_Mat &m2); //! m'*v where m is a sparse matrix and v is a full column vector template Vec trans_mult(const Sparse_Mat &m, const Vec &v); //! m1*m2' where m1 and m2 are sparse matrices template Sparse_Mat mult_trans(const Sparse_Mat &m1, const Sparse_Mat &m2); /*! \brief Templated Sparse Matrix Class \author Tony Ottosson and Tobias Ringstrom */ template class Sparse_Mat { public: //! Default constructor Sparse_Mat(); /*! \brief Initiate an empty sparse vector A Sparse_Mat consists of colums that have the type Sparse_Vec. The maximum number of non-zero elements is each column is denoted \c row_data_init. \param rows Number of rows in the matrix \param cols Number of columns in the matrix \param row_data_init The maximum number of non-zero elements in each column (default value is 200) */ Sparse_Mat(int rows, int cols, int row_data_init=200); //! Initiate a new sparse matrix. The elements of \c m are copied into the new sparse matrix Sparse_Mat(const Sparse_Mat &m); //! Initiate a new sparse matrix from a dense matrix. The elements of \c m are copied into the new sparse matrix Sparse_Mat(const Mat &m); /*! \brief Initiate a new sparse matrix from a dense matrix. Elements of \c m larger than \c epsilon are copied into the new sparse matrix. \note If the type T is double complex, then the elements of \c m larger than \c abs(epsilon) are copied into the new sparse matrix. */ Sparse_Mat(const Mat &m, T epsilon); //! Destructor ~Sparse_Mat(); /*! \brief Set the size of the sparse matrix A Sparse_Mat consists of colums that have the type Sparse_Vec. The maximum number of non-zero elements is each column is denoted \c row_data_init, with default value =-1 indicating that the number of data elements is not changed. \param rows Number of rows in the matrix \param cols Number of columns in the matrix \param row_data_init The maximum number of non-zero elements in each column (default value -1 \c => allocated size for the data is not changed) */ void set_size(int rows, int cols, int row_data_init=-1); //! Returns the number of rows of the sparse matrix int rows() const { return n_rows; } //! Returns the number of columns of the sparse matrix int cols() const { return n_cols; } //! The number of non-zero elements in the sparse matrix int nnz(); //! Returns the density of the sparse matrix: (number of non-zero elements)/(total number of elements) double density(); //! Set the maximum number of non-zero elements in each column equal to the actual number of non-zero elements in each column void compact(); //! Returns a full, dense matrix in \c m void full(Mat &m) const; //! Returns a full, dense matrix Mat full() const; //! Returns element of row \c r and column \c c T operator()(int r, int c) const; //! Set element (\c r, \c c ) equal to \c v void set(int r, int c, T v); //! Set a new element with index (\c r, \c c ) equal to \c v void set_new(int r, int c, T v); //! Add the element in row \c r and column \c c with \c v void add_elem(const int r, const int c, const T v); //! Set the sparse matrix to the all zero matrix (removes all non-zero elements) void zeros(); //! Set the element in row \c r and column \c c to zero (i.e. clear that element if it contains a non-zero value) void zero_elem(const int r, const int c); //! Clear all non-zero elements of the sparse matrix void clear(); //! Clear the element in row \c r and column \c c (if it contains a non-zero value) void clear_elem(const int r, const int c); //! Set submatrix defined by rows r1,r2 and columns c1,c2 to matrix m void set_submatrix(int r1, int r2, int c1, int c2, const Mat &m); //! Set submatrix defined by upper-left element (\c r,\c c) and the size of matrix \c m to \c m void set_submatrix(int r, int c, const Mat& m); //! Returns the sub-matrix from rows \c r1 to \c r2 and columns \c c1 to \c c2 Sparse_Mat get_submatrix(int r1, int r2, int c1, int c2) const; //! Returns the sub-matrix from columns \c c1 to \c c2 (all rows) Sparse_Mat get_submatrix_cols(int c1, int c2) const; //! Returns column \c c of the Sparse_Mat in the Sparse_Vec \c v void get_col(int c, Sparse_Vec &v) const; //! Returns column \c c of the Sparse_Mat Sparse_Vec get_col(int c) const; //! Set column \c c of the Sparse_Mat void set_col(int c, const Sparse_Vec &v); //! Transpose the sparse matrix, return the result in \c m void transpose(Sparse_Mat &m) const; //! Returns the transpose of the sparse matrix Sparse_Mat transpose() const; //! Returns the transpose of the sparse matrix // Sparse_Mat T() const { return this->transpose(); }; //! Assign sparse matrix the value and dimensions of the sparse matrix \c m void operator=(const Sparse_Mat &m); //! Assign sparse matrix the value and dimensions of the dense matrix \c m void operator=(const Mat &m); //! Returns the sign inverse of all elements in the sparse matrix Sparse_Mat operator-() const; //! Compare two sparse matricies. False if wrong sizes or different values bool operator==(const Sparse_Mat &m) const; //! Add sparse matrix \c v to all non-zero elements of the sparse matrix void operator+=(const Sparse_Mat &v); //! Add matrix \c v to all non-zero elements of the sparse matrix void operator+=(const Mat &v); //! Subtract sparse matrix \c v from all non-zero elements of the sparse matrix void operator-=(const Sparse_Mat &v); //! Subtract matrix \c v from all non-zero elements of the sparse matrix void operator-=(const Mat &v); //! Multiply all non-zero elements of the sparse matrix with the scalar \c v void operator*=(const T &v); //! Divide all non-zero elements of the sparse matrix with the scalar \c v void operator/=(const T &v); //! Addition m1+m2 where m1 and m2 are sparse matrices friend Sparse_Mat operator+<>(const Sparse_Mat &m1, const Sparse_Mat &m2); //! Multiplication m1*m2 where m1 and m2 are sparse matrices friend Sparse_Mat operator*<>(const Sparse_Mat &m1, const Sparse_Mat &m2); //! Multiplication m*v where m is a sparse matrix and v is a full column vector friend Vec operator*<>(const Sparse_Mat &m, const Vec &v); //! Multiplication v'*m where m is a sparse matrix and v is a full column vector friend Vec operator*<>(const Vec &v, const Sparse_Mat &m); //! Multiplication m'*m where m is a sparse matrix. Returns a full, dense matrix friend Mat trans_mult <>(const Sparse_Mat &m); //! Multiplication m'*m where m is a sparse matrix, Returns a sparse matrix friend Sparse_Mat trans_mult_s <>(const Sparse_Mat &m); //! Multiplication m1'*m2 where m1 and m2 are sparse matrices friend Sparse_Mat trans_mult <>(const Sparse_Mat &m1, const Sparse_Mat &m2); //! Multiplication m'*v where m is a sparse matrix and v is a full column vector friend Vec trans_mult <>(const Sparse_Mat &m, const Vec &v); //! Multiplication m1*m2' where m1 and m2 are sparse matrices friend Sparse_Mat mult_trans <>(const Sparse_Mat &m1, const Sparse_Mat &m2); private: void init(); void alloc_empty(); void alloc(int row_data_size=200); void free(); int n_rows, n_cols; Sparse_Vec *col; }; /*! \relates Sparse_Mat \brief Sparse integer matrix */ typedef Sparse_Mat sparse_imat; /*! \relates Sparse_Mat \brief Sparse double matrix */ typedef Sparse_Mat sparse_mat; /*! \relates Sparse_Mat \brief Sparse complex matrix */ typedef Sparse_Mat > sparse_cmat; //---------------------- Implementation starts here -------------------------------- template void Sparse_Mat::init() { n_rows = 0; n_cols = 0; col = 0; } template void Sparse_Mat::alloc_empty() { if (n_cols == 0) col = 0; else col = new Sparse_Vec[n_cols]; } template void Sparse_Mat::alloc(int row_data_init) { if (n_cols == 0) col = 0; else col = new Sparse_Vec[n_cols]; for (int c=0; c void Sparse_Mat::free() { delete [] col; col = 0; } template Sparse_Mat::Sparse_Mat() { init(); } template Sparse_Mat::Sparse_Mat(int rows, int cols, int row_data_init) { init(); n_rows = rows; n_cols = cols; alloc(row_data_init); } template Sparse_Mat::Sparse_Mat(const Sparse_Mat &m) { init(); n_rows = m.n_rows; n_cols = m.n_cols; alloc_empty(); for (int c=0; c Sparse_Mat::Sparse_Mat(const Mat &m) { init(); n_rows = m.rows(); n_cols = m.cols(); alloc(); for (int c=0; c Sparse_Mat::Sparse_Mat(const Mat &m, T epsilon) { init(); n_rows = m.rows(); n_cols = m.cols(); alloc(); for (int c=0; c std::abs(epsilon)) col[c].set_new(r, m(r,c)); } col[c].compact(); } } template Sparse_Mat::~Sparse_Mat() { free(); } template void Sparse_Mat::set_size(int rows, int cols, int row_data_init) { n_rows = rows; //Allocate new memory for data if the number of columns has changed or if row_data_init != -1 if (cols!=n_cols||row_data_init!=-1) { n_cols = cols; free(); alloc(row_data_init); } } template int Sparse_Mat::nnz() { int n=0; for (int c=0; c double Sparse_Mat::density() { //return static_cast(nnz())/(n_rows*n_cols); return double(nnz())/(n_rows*n_cols); } template void Sparse_Mat::compact() { for (int c=0; c void Sparse_Mat::full(Mat &m) const { m.set_size(n_rows, n_cols); m = T(0); for (int c=0; c Mat Sparse_Mat::full() const { Mat r(n_rows, n_cols); full(r); return r; } template T Sparse_Mat::operator()(int r, int c) const { it_assert0(r>=0&&r=0&&c void Sparse_Mat::set(int r, int c, T v) { it_assert0(r>=0&&r=0&&c void Sparse_Mat::set_new(int r, int c, T v) { it_assert0(r>=0&&r=0&&c void Sparse_Mat::add_elem(int r, int c, T v) { it_assert0(r>=0&&r=0&&c void Sparse_Mat::zeros() { for (int c=0; c void Sparse_Mat::zero_elem(const int r, const int c) { it_assert0(r>=0&&r=0&&c void Sparse_Mat::clear() { for (int c=0; c void Sparse_Mat::clear_elem(const int r, const int c) { it_assert0(r>=0&&r=0&&c void Sparse_Mat::set_submatrix(int r1, int r2, int c1, int c2, const Mat& m) { if (r1 == -1) r1 = n_rows-1; if (r2 == -1) r2 = n_rows-1; if (c1 == -1) c1 = n_cols-1; if (c2 == -1) c2 = n_cols-1; it_assert1(r1>=0 && r2>=0 && r1=0 && c2>=0 && c1::set_submatrix(): index out of range"); it_assert1(r2>=r1 && c2>=c1, "Sparse_Mat::set_submatrix: r2::set_submatrix(): sizes don't match"); for (int i=0 ; i void Sparse_Mat::set_submatrix(int r, int c, const Mat& m) { it_assert1(r>=0 && r+m.rows()<=n_rows && c>=0 && c+m.cols()<=n_cols, "Sparse_Mat::set_submatrix(): index out of range"); for (int i=0 ; i Sparse_Mat Sparse_Mat::get_submatrix(int r1, int r2, int c1, int c2) const { it_assert0(r1<=r2 && r1>=0 && r1=0 && c1::get_submatrix(): illegal input variables"); Sparse_Mat r(r2-r1+1, c2-c1+1); for (int c=c1; c<=c2; c++) r.col[c-c1] = col[c].get_subvector(r1, r2); r.compact(); return r; } template Sparse_Mat Sparse_Mat::get_submatrix_cols(int c1, int c2) const { it_assert0(c1<=c2 && c1>=0 && c1::get_submatrix_cols()"); Sparse_Mat r(n_rows, c2-c1+1, 0); for (int c=c1; c<=c2; c++) r.col[c-c1] = col[c]; r.compact(); return r; } template void Sparse_Mat::get_col(int c, Sparse_Vec &v) const { it_assert(c>=0 && c::get_col()"); v = col[c]; } template Sparse_Vec Sparse_Mat::get_col(int c) const { it_assert(c>=0 && c::get_col()"); return col[c]; } template void Sparse_Mat::set_col(int c, const Sparse_Vec &v) { it_assert(c>=0 && c::set_col()"); col[c] = v; } template void Sparse_Mat::transpose(Sparse_Mat &m) const { m.set_size(n_cols, n_rows); for (int c=0; c Sparse_Mat Sparse_Mat::transpose() const { Sparse_Mat m; transpose(m); return m; } template void Sparse_Mat::operator=(const Sparse_Mat &m) { free(); n_rows = m.n_rows; n_cols = m.n_cols; alloc_empty(); for (int c=0; c void Sparse_Mat::operator=(const Mat &m) { free(); n_rows = m.rows(); n_cols = m.cols(); alloc(); for (int c=0; c Sparse_Mat Sparse_Mat::operator-() const { Sparse_Mat r(n_rows, n_cols, 0); for (int c=0; c bool Sparse_Mat::operator==(const Sparse_Mat &m) const { if (n_rows!=m.n_rows || n_cols!=m.n_cols) return false; for (int c=0; c void Sparse_Mat::operator+=(const Sparse_Mat &m) { it_assert0(m.rows()==n_rows&&m.cols()==n_cols, "Addition of unequal sized matrices is not allowed"); Sparse_Vec v; for (int c=0; c void Sparse_Mat::operator+=(const Mat &m) { it_assert0(m.rows()==n_rows&&m.cols()==n_cols, "Addition of unequal sized matrices is not allowed"); for (int c=0; c void Sparse_Mat::operator-=(const Sparse_Mat &m) { it_assert0(m.rows()==n_rows&&m.cols()==n_cols, "Subtraction of unequal sized matrices is not allowed"); Sparse_Vec v; for (int c=0; c void Sparse_Mat::operator-=(const Mat &m) { it_assert0(m.rows()==n_rows&&m.cols()==n_cols, "Subtraction of unequal sized matrices is not allowed"); for (int c=0; c void Sparse_Mat::operator*=(const T &m) { for (int c=0; c void Sparse_Mat::operator/=(const T &m) { for (int c=0; c Sparse_Mat operator+(const Sparse_Mat &m1, const Sparse_Mat &m2) { it_assert0(m1.n_cols == m2.n_cols && m1.n_rows == m2.n_rows , "Sparse_Mat + Sparse_Mat"); Sparse_Mat m(m1.n_rows, m1.n_cols, 0); for (int c=0; c Sparse_Mat operator*(const Sparse_Mat &m1, const Sparse_Mat &m2) { it_assert0(m1.n_cols == m2.n_rows, "Sparse_Mat * Sparse_Mat"); Sparse_Mat ret(m1.n_rows, m2.n_cols); ivec occupied_by(ret.n_rows), pos(ret.n_rows); for (int rp=0; rp &m2col = m2.col[c]; for (int p2=0; p2 &m1col = m1.col[m2col.get_nz_index(p2)]; for (int p1=0; p1 Vec operator*(const Sparse_Mat &m, const Vec &v) { it_assert0(m.n_cols == v.size(), "Sparse_Mat * Vec"); Vec r(m.n_rows); r.clear(); //r = T(0); for (int c=0; c Vec operator*(const Vec &v, const Sparse_Mat &m) { it_assert0(v.size() == m.n_rows, "Vec * Sparse_Mat"); Vec r(m.n_cols); r.clear(); //r = T(0); for (int c=0; c Mat trans_mult(const Sparse_Mat &m) { Mat ret(m.n_cols, m.n_cols); Vec col; for (int c=0; c Sparse_Mat trans_mult_s(const Sparse_Mat &m) { Sparse_Mat ret(m.n_cols, m.n_cols); Vec col; T tmp; for (int c=0; c Sparse_Mat trans_mult(const Sparse_Mat &m1, const Sparse_Mat &m2) { it_assert0(m1.n_rows == m2.n_rows, "trans_mult()"); Sparse_Mat ret(m1.n_cols, m2.n_cols); Vec col; for (int c=0; c Vec trans_mult(const Sparse_Mat &m, const Vec &v) { Vec r(m.n_cols); for (int c=0; c Sparse_Mat mult_trans(const Sparse_Mat &m1, const Sparse_Mat &m2) { return trans_mult(m1.transpose(),m2.transpose()); } template inline Sparse_Mat sparse(const Mat &m, T epsilon) { Sparse_Mat s(m, epsilon); return s; } template inline Mat full(const Sparse_Mat &s) { Mat m; s.full(m); return m; } template inline Sparse_Mat transpose(const Sparse_Mat &s) { Sparse_Mat m; s.transpose(m); return m; } } //namespace itpp #endif //__smat_h