/*! * \file * \brief Various functions on vectors and matrices - header file * \author Tony Ottosson, Adam Piatyszek, Conrad Sanderson, Mark Dobossy * and Martin Senst * * ------------------------------------------------------------------------- * * IT++ - C++ library of mathematical, signal processing, speech processing, * and communications classes and functions * * Copyright (C) 1995-2007 (see AUTHORS file for a list of contributors) * * 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * ------------------------------------------------------------------------- */ #ifndef MATFUNC_H #define MATFUNC_H #include #include #include namespace itpp { /*! \addtogroup matrix_functions \brief Functions on vectors and matrices */ //!@{ //! Length of vector template int length(const Vec &v) { return v.length(); } //! Length of vector template int size(const Vec &v) { return v.length(); } //! Sum of all elements in the vector template T sum(const Vec &v) { T M = 0; for (int i=0;isum(m) = sum(m, 1) returns a vector where the elements are sum * over each column, whereas sum(m, 2) returns a vector where the * elements are sum over each row. */ template Vec sum(const Mat &m, int dim=1) { it_assert((dim == 1) || (dim == 2), "sum: dimension need to be 1 or 2"); Vec out; if (dim == 1) { out.set_size(m.cols(), false); for (int i=0; i T sumsum(const Mat &X) { const T * X_data = X._data(); const int X_datasize = X._datasize(); T acc = 0; for(int i=0;i T sum_sqr(const Vec &v) { T M=0; for (int i=0; isum(m) = sum(m, 1) returns a vector where the elements are sum * squared over each column, whereas sum(m, 2) returns a vector * where the elements are sum squared over each row */ template Vec sum_sqr(const Mat &m, int dim=1) { it_assert((dim == 1) || (dim == 2), "sum_sqr: dimension need to be 1 or 2"); Vec out; if (dim == 1) { out.set_size(m.cols(), false); for (int i=0; i Vec cumsum(const Vec &v) { Vec out(v.size()); out(0)=v(0); for (int i=1; icumsum(m) = cumsum(m, 1) returns a matrix where the elements * are sums over each column, whereas cumsum(m, 2) returns a * matrix where the elements are sums over each row */ template Mat cumsum(const Mat &m, int dim=1) { it_assert((dim == 1) || (dim == 2), "cumsum: dimension need to be 1 or 2"); Mat out(m.rows(), m.cols()); if (dim == 1) { for (int i=0; i T prod(const Vec &v) { it_assert(v.size() >= 1, "prod: size of vector should be at least 1"); T out = v(0); for (int i=1; iprod(m) = prod(m, 1) returns a vector where the elements are * products over each column, whereas prod(m, 2) returns a vector * where the elements are products over each row */ template Vec prod(const Mat &m, int dim=1) { it_assert((dim == 1) || (dim == 2), "prod: dimension need to be 1 or 2"); Vec out(m.cols()); if (dim == 1) { it_assert((m.cols() >= 1) && (m.rows() >= 1), "prod: number of columns should be at least 1"); out.set_size(m.cols(), false); for (int i=0; i= 1) && (m.rows() >= 1), "prod: number of rows should be at least 1"); out.set_size(m.rows(), false); for (int i=0; i Vec cross(const Vec &v1, const Vec &v2) { it_assert((v1.size() == 3) && (v2.size() == 3), "cross: vectors should be of size 3"); Vec r(3); r(0) = v1(1) * v2(2) - v1(2) * v2(1); r(1) = v1(2) * v2(0) - v1(0) * v2(2); r(2) = v1(0) * v2(1) - v1(1) * v2(0); return r; } //! Zero-pad a vector to size n template Vec zero_pad(const Vec &v, int n) { it_assert(n >= v.size(), "zero_pad() cannot shrink the vector!"); Vec v2(n); v2.set_subvector(0, v.size()-1, v); if (n > v.size()) v2.set_subvector(v.size(), n-1, T(0)); return v2; } //! Zero-pad a vector to the nearest greater power of two template Vec zero_pad(const Vec &v) { int n = pow2i(levels2bits(v.size())); return (n == v.size()) ? v : zero_pad(v, n); } //! Zero-pad a matrix to size rows x cols template Mat zero_pad(const Mat &m, int rows, int cols) { it_assert((rows >= m.rows()) && (cols >= m.cols()), "zero_pad() cannot shrink the matrix!"); Mat m2(rows, cols); m2.set_submatrix(0,m.rows()-1,0,m.cols()-1, m); if (cols > m.cols()) // Zero m2.set_submatrix(0,m.rows()-1, m.cols(),cols-1, T(0)); if (rows > m.rows()) // Zero m2.set_submatrix(m.rows(), rows-1, 0, cols-1, T(0)); return m2; } //! Return zero if indexing outside the vector \c v otherwise return the //! element \c index template T index_zero_pad(const Vec &v, const int index) { if (index >= 0 && index < v.size()) return v(index); else return T(0); } //! Transposition of the matrix \c m returning the transposed matrix in \c out template void transpose(const Mat &m, Mat &out) { out = m.T(); } //! Transposition of the matrix \c m template Mat transpose(const Mat &m) { return m.T(); } //! Hermitian transpose (complex conjugate transpose) of the matrix \c m //! returning the transposed matrix in \c out template void hermitian_transpose(const Mat &m, Mat &out) { out = m.H(); } //! Hermitian transpose (complex conjugate transpose) of the matrix \c m template Mat hermitian_transpose(const Mat &m) { return m.H(); } /*! * \brief Returns true if matrix \c X is hermitian, false otherwise * \author M. Szalay * * A square matrix \f$\mathbf{X}\f$ is hermitian if * \f[ * \mathbf{X} = \mathbf{X}^H * \f] */ template bool is_hermitian(const Mat& X) { if (X == X.H() ) return true; else return false; } /*! * \brief Returns true if matrix \c X is unitary, false otherwise * \author M. Szalay * * A square matrix \f$\mathbf{X}\f$ is unitary if * \f[ * \mathbf{X}^H = \mathbf{X}^{-1} * \f] */ template bool is_unitary(const Mat& X) { if ( inv(X) == X.H() ) return true; else return false; } /*! * \relates Vec * \brief Creates a vector with \c n copies of the vector \c v * \author Martin Senst * * \param v Vector to be repeated * \param n Number of times to repeat \c v */ template Vec repmat(const Vec &v, int n) { it_assert(n > 0, "repmat(): Wrong repetition parameter"); int data_length = v.length(); it_assert(data_length > 0, "repmat(): Input vector can not be empty"); Vec assembly(data_length * n); for (int j = 0; j < n; ++j) { assembly.set_subvector(j * data_length, v); } return assembly; } /*! * \relates Mat * \brief Creates a matrix with \c m by \c n copies of the matrix \c data * \author Mark Dobossy * * \param data Matrix to be repeated * \param m Number of times to repeat data vertically * \param n Number of times to repeat data horizontally */ template Mat repmat(const Mat &data, int m, int n) { it_assert((m > 0) && (n > 0), "repmat(): Wrong repetition parameters"); int data_rows = data.rows(); int data_cols = data.cols(); it_assert((data_rows > 0) && (data_cols > 0), "repmat(): Input matrix can " "not be empty"); Mat assembly(data_rows*m, data_cols*n); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { assembly.set_submatrix(i*data_rows, j*data_cols, data); } } return assembly; } /*! * \relates Mat * \brief Returns a matrix with \c m by \c n copies of the vector \c data * \author Adam Piatyszek * * \param v Vector to be repeated * \param m Number of times to repeat data vertically * \param n Number of times to repeat data horizontally * \param transpose Specifies the input vector orientation (column vector * by default) */ template inline Mat repmat(const Vec &v, int m, int n, bool transpose = false) { return repmat((transpose ? v.T() : Mat(v)), m, n); } /*! * \brief Computes the Kronecker product of two matrices * * K = kron(X, Y) returns the Kronecker tensor product of \c X * and \c Y. The result is a large array formed by taking all possible * products between the elements of \c X and those of \c Y. If \c X is * (m x n) and \c Y is (p x q), then kron(X, Y) * is (m*p x n*q). * * \author Adam Piatyszek */ template Mat kron(const Mat& X, const Mat& Y) { Mat result(X.rows() * Y.rows(), X.cols() * Y.cols()); for (int i = 0; i < X.rows(); i++) for (int j = 0; j < X.cols(); j++) result.set_submatrix(i * Y.rows(), j * Y.cols(), X(i, j) * Y); return result; } /*! * \brief Square root of the complex square matrix \c A * * This function computes the matrix square root of the complex square * matrix \c A. The implementation is based on the Matlab/Octave \c * sqrtm() function. * * Ref: N. J. Higham, "Numerical Analysis Report No. 336", Manchester * Centre for Computational Mathematics, Manchester, England, January 1999 * * \author Adam Piatyszek */ cmat sqrtm(const cmat& A); /*! * \brief Square root of the real square matrix \c A * * This function computes the matrix square root of the real square matrix * \c A. Please note that the returned matrix is complex. The * implementation is based on the Matlab/Octave \c sqrtm() function. * * Ref: N. J. Higham, "Numerical Analysis Report No. 336", Manchester * Centre for Computational Mathematics, Manchester, England, January 1999 * * \author Adam Piatyszek */ cmat sqrtm(const mat& A); //!@} // -------------------- Diagonal matrix functions ------------------------- //! \addtogroup diag //!@{ /*! * \brief Create a diagonal matrix using vector \c v as its diagonal * * All other matrix elements except the ones on its diagonal are set to * zero. An optional parameter \c K can be used to shift the diagonal in * the resulting matrix. By default \c K is equal to zero. * * The size of the diagonal matrix will be \f$n+|K| \times n+|K|\f$, where * \f$n\f$ is the length of the input vector \c v. */ template Mat diag(const Vec &v, const int K = 0) { Mat m(v.size() + std::abs(K), v.size() + std::abs(K)); m = T(0); if (K>0) for (int i=v.size()-1; i>=0; i--) m(i,i+K) = v(i); else for (int i=v.size()-1; i>=0; i--) m(i-K,i) = v(i); return m; } /*! * \brief Create a diagonal matrix using vector \c v as its diagonal * * All other matrix elements except the ones on its diagonal are set to * zero. * * The size of the diagonal matrix will be \f$n \times n\f$, where \f$n\f$ * is the length of the input vector \c v. */ template void diag(const Vec &v, Mat &m) { m.set_size(v.size(), v.size(), false); m = T(0); for (int i=v.size()-1; i>=0; i--) m(i,i) = v(i); } /*! * \brief Get the diagonal elements of the input matrix \c m * * The size of the output vector with diagonal elements will be * \f$n = min(r, c)\f$, where \f$r \times c\f$ are the dimensions of * matrix \c m. */ template Vec diag(const Mat &m) { Vec t(std::min(m.rows(), m.cols())); for (int i=0; i Mat bidiag(const Vec &main, const Vec &sup) { it_assert(main.size() == sup.size()+1, "bidiag()"); int n=main.size(); Mat m(n, n); m = T(0); for (int i=0; i void bidiag(const Vec &main, const Vec &sup, Mat &m) { it_assert(main.size() == sup.size()+1, "bidiag()"); int n=main.size(); m.set_size(n, n); m = T(0); for (int i=0; i void bidiag(const Mat &m, Vec &main, Vec &sup) { it_assert(m.rows() == m.cols(), "bidiag(): Matrix must be square!"); int n=m.cols(); main.set_size(n); sup.set_size(n-1); for (int i=0; i Mat tridiag(const Vec &main, const Vec &sup, const Vec &sub) { it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()"); int n=main.size(); Mat m(n, n); m = T(0); for (int i=0; i void tridiag(const Vec &main, const Vec &sup, const Vec &sub, Mat &m) { it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()"); int n=main.size(); m.set_size(n, n); m = T(0); for (int i=0; i void tridiag(const Mat &m, Vec &main, Vec &sup, Vec &sub) { it_assert(m.rows() == m.cols(), "tridiag(): Matrix must be square!"); int n=m.cols(); main.set_size(n); sup.set_size(n-1); sub.set_size(n-1); for (int i=0; i T trace(const Mat &m) { return sum(diag(m)); } //!@} // ----------------- reshaping vectors and matrices ------------------------ //! \addtogroup reshaping //!@{ //! Reverse the input vector template Vec reverse(const Vec &in) { int i, s=in.length(); Vec out(s); for (i=0;i Vec rvectorize(const Mat &m) { int i, j, n=0, r=m.rows(), c=m.cols(); Vec v(r * c); for (i=0; i Vec cvectorize(const Mat &m) { int i, j, n=0, r=m.rows(), c=m.cols(); Vec v(r * c); for (j=0; j Mat reshape(const Mat &m, int rows, int cols) { it_assert_debug(m.rows()*m.cols() == rows*cols, "Mat::reshape: Sizes must match"); Mat temp(rows, cols); int i, j, ii=0, jj=0; for (j=0; j Mat reshape(const Vec &v, int rows, int cols) { it_assert_debug(v.size() == rows*cols, "Mat::reshape: Sizes must match"); Mat temp(rows, cols); int i, j, ii=0; for (j=0; j sum(const cvec &v); extern template short sum(const svec &v); extern template int sum(const ivec &v); extern template bin sum(const bvec &v); extern template double sum_sqr(const vec &v); extern template std::complex sum_sqr(const cvec &v); extern template short sum_sqr(const svec &v); extern template int sum_sqr(const ivec &v); extern template bin sum_sqr(const bvec &v); extern template vec cumsum(const vec &v); extern template cvec cumsum(const cvec &v); extern template svec cumsum(const svec &v); extern template ivec cumsum(const ivec &v); extern template bvec cumsum(const bvec &v); extern template double prod(const vec &v); extern template std::complex prod(const cvec &v); extern template short prod(const svec &v); extern template int prod(const ivec &v); extern template bin prod(const bvec &v); extern template vec cross(const vec &v1, const vec &v2); extern template cvec cross(const cvec &v1, const cvec &v2); extern template ivec cross(const ivec &v1, const ivec &v2); extern template svec cross(const svec &v1, const svec &v2); extern template bvec cross(const bvec &v1, const bvec &v2); extern template vec reverse(const vec &in); extern template cvec reverse(const cvec &in); extern template svec reverse(const svec &in); extern template ivec reverse(const ivec &in); extern template bvec reverse(const bvec &in); extern template vec zero_pad(const vec &v, int n); extern template cvec zero_pad(const cvec &v, int n); extern template ivec zero_pad(const ivec &v, int n); extern template svec zero_pad(const svec &v, int n); extern template bvec zero_pad(const bvec &v, int n); extern template vec zero_pad(const vec &v); extern template cvec zero_pad(const cvec &v); extern template ivec zero_pad(const ivec &v); extern template svec zero_pad(const svec &v); extern template bvec zero_pad(const bvec &v); extern template mat zero_pad(const mat &, int, int); extern template cmat zero_pad(const cmat &, int, int); extern template imat zero_pad(const imat &, int, int); extern template smat zero_pad(const smat &, int, int); extern template bmat zero_pad(const bmat &, int, int); extern template vec sum(const mat &m, int dim); extern template cvec sum(const cmat &m, int dim); extern template svec sum(const smat &m, int dim); extern template ivec sum(const imat &m, int dim); extern template bvec sum(const bmat &m, int dim); extern template double sumsum(const mat &X); extern template std::complex sumsum(const cmat &X); extern template short sumsum(const smat &X); extern template int sumsum(const imat &X); extern template bin sumsum(const bmat &X); extern template vec sum_sqr(const mat & m, int dim); extern template cvec sum_sqr(const cmat &m, int dim); extern template svec sum_sqr(const smat &m, int dim); extern template ivec sum_sqr(const imat &m, int dim); extern template bvec sum_sqr(const bmat &m, int dim); extern template mat cumsum(const mat &m, int dim); extern template cmat cumsum(const cmat &m, int dim); extern template smat cumsum(const smat &m, int dim); extern template imat cumsum(const imat &m, int dim); extern template bmat cumsum(const bmat &m, int dim); extern template vec prod(const mat &m, int dim); extern template cvec prod(const cmat &v, int dim); extern template svec prod(const smat &m, int dim); extern template ivec prod(const imat &m, int dim); extern template bvec prod(const bmat &m, int dim); extern template vec diag(const mat &in); extern template cvec diag(const cmat &in); extern template void diag(const vec &in, mat &m); extern template void diag(const cvec &in, cmat &m); extern template mat diag(const vec &v, const int K); extern template cmat diag(const cvec &v, const int K); extern template mat bidiag(const vec &, const vec &); extern template cmat bidiag(const cvec &, const cvec &); extern template void bidiag(const vec &, const vec &, mat &); extern template void bidiag(const cvec &, const cvec &, cmat &); extern template void bidiag(const mat &, vec &, vec &); extern template void bidiag(const cmat &, cvec &, cvec &); extern template mat tridiag(const vec &main, const vec &, const vec &); extern template cmat tridiag(const cvec &main, const cvec &, const cvec &); extern template void tridiag(const vec &main, const vec &, const vec &, mat &); extern template void tridiag(const cvec &main, const cvec &, const cvec &, cmat &); extern template void tridiag(const mat &m, vec &, vec &, vec &); extern template void tridiag(const cmat &m, cvec &, cvec &, cvec &); extern template double trace(const mat &in); extern template std::complex trace(const cmat &in); extern template short trace(const smat &in); extern template int trace(const imat &in); extern template bin trace(const bmat &in); extern template void transpose(const mat &m, mat &out); extern template void transpose(const cmat &m, cmat &out); extern template void transpose(const smat &m, smat &out); extern template void transpose(const imat &m, imat &out); extern template void transpose(const bmat &m, bmat &out); extern template mat transpose(const mat &m); extern template cmat transpose(const cmat &m); extern template smat transpose(const smat &m); extern template imat transpose(const imat &m); extern template bmat transpose(const bmat &m); extern template void hermitian_transpose(const mat &m, mat &out); extern template void hermitian_transpose(const cmat &m, cmat &out); extern template void hermitian_transpose(const smat &m, smat &out); extern template void hermitian_transpose(const imat &m, imat &out); extern template void hermitian_transpose(const bmat &m, bmat &out); extern template mat hermitian_transpose(const mat &m); extern template cmat hermitian_transpose(const cmat &m); extern template smat hermitian_transpose(const smat &m); extern template imat hermitian_transpose(const imat &m); extern template bmat hermitian_transpose(const bmat &m); extern template bool is_hermitian(const mat &X); extern template bool is_hermitian(const cmat &X); extern template bool is_unitary(const mat &X); extern template bool is_unitary(const cmat &X); extern template vec rvectorize(const mat &m); extern template cvec rvectorize(const cmat &m); extern template ivec rvectorize(const imat &m); extern template svec rvectorize(const smat &m); extern template bvec rvectorize(const bmat &m); extern template vec cvectorize(const mat &m); extern template cvec cvectorize(const cmat &m); extern template ivec cvectorize(const imat &m); extern template svec cvectorize(const smat &m); extern template bvec cvectorize(const bmat &m); extern template mat reshape(const mat &m, int rows, int cols); extern template cmat reshape(const cmat &m, int rows, int cols); extern template imat reshape(const imat &m, int rows, int cols); extern template smat reshape(const smat &m, int rows, int cols); extern template bmat reshape(const bmat &m, int rows, int cols); extern template mat reshape(const vec &m, int rows, int cols); extern template cmat reshape(const cvec &m, int rows, int cols); extern template imat reshape(const ivec &m, int rows, int cols); extern template smat reshape(const svec &m, int rows, int cols); extern template bmat reshape(const bvec &m, int rows, int cols); extern template mat kron(const mat &X, const mat &Y); extern template cmat kron(const cmat &X, const cmat &Y); extern template imat kron(const imat &X, const imat &Y); extern template smat kron(const smat &X, const smat &Y); extern template bmat kron(const bmat &X, const bmat &Y); extern template vec repmat(const vec &v, int n); extern template cvec repmat(const cvec &v, int n); extern template ivec repmat(const ivec &v, int n); extern template svec repmat(const svec &v, int n); extern template bvec repmat(const bvec &v, int n); extern template mat repmat(const vec &v, int m, int n, bool transpose); extern template cmat repmat(const cvec &v, int m, int n, bool transpose); extern template imat repmat(const ivec &v, int m, int n, bool transpose); extern template smat repmat(const svec &v, int m, int n, bool transpose); extern template bmat repmat(const bvec &v, int m, int n, bool transpose); extern template mat repmat(const mat &data, int m, int n); extern template cmat repmat(const cmat &data, int m, int n); extern template imat repmat(const imat &data, int m, int n); extern template smat repmat(const smat &data, int m, int n); extern template bmat repmat(const bmat &data, int m, int n); #endif // HAVE_EXTERN_TEMPLATE //! \endcond } // namespace itpp #endif // #ifndef MATFUNC_H