/*---------------------------------------------------------------------------* * 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 Definitions of functions on vectors and matrices \author Tony Ottosson 1.21 2003/06/17 11:48:36 */ #ifndef __matfunc_h #define __matfunc_h #include "base/vec.h" #include "base/mat.h" #include "base/converters.h" #include "base/scalfunc.h" #include "base/itassert.h" #include "base/specmat.h" #include "base/binary.h" #include "base/sort.h" namespace itpp { //! Define of absolute(x) #define absolut(x) (((x)>0) ? (x) : (-(x))) /*! \defgroup 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;i 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 sum_sqr(const Vec &v) { T M=0; for (int i=0; i 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; i 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; i 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; } //! Apply arbitrary function to a vector template Vec apply_function(fT (*f)(fT), const Vec &data) { Vec out(data.length()); for (int i=0;i Mat apply_function(fT (*f)(fT), const Mat &data) { Mat out(data.rows(),data.cols()); for (int i=0;i(f(static_cast(data(i,j)))); out(i,j)=T(f(fT(data(i,j)))); return out; } //! 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 = pow2(needed_bits(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; } /*! \brief Transposition of the matrix \c m returning the transposed matrix in \c out */ template void transpose(const Mat &m, Mat &out) { out = m.T(); } /*! \brief Transposition of the matrix \c m */ template Mat transpose(const Mat &m) { return m.T(); } /*! \brief 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(); } /*! \brief Hermitian transpose (complex conjugate transpose) of the matrix \c m */ template Mat hermitian_transpose(const Mat &m) { return m.H(); } /*! \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) { int x_rows = x.rows(); int x_cols = x.cols(); int y_rows = y.rows(); int y_cols = y.cols(); 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; } //!@} // -------------------- Diagonal matrix functions --------------------------------------- /*! \defgroup diag Diagonal matrices and functions of diagonals */ //!@{ /*! \brief Returns a diagonal matrix whith the elements of the vector \c v on the diagonal and zeros elsewhere. The size of the return matrix will be \f$n \times n\f$, where \f$n\f$ is the length of the input vector \c v. */ template Mat diag(const Vec &v) { Mat m(v.size(), v.size()); m = T(0); for (int i=v.size()-1; i>=0; i--) m(i,i) = v(i); return m; } /*! \brief Returns in the output wariable \c m a diagonal matrix whith the elements of the vector \c v on the diagonal and zeros elsewhere. The size of the output matrix \c m 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 Returns the diagonal elements of the input matrix \c m. The input matrix \c m must be a square \f$n \times n\f$ matrix. The size of the output vector will be \f$n\f$. */ 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 --------------------------- /*! \defgroup reshaping Reshaping of vectors and matrices */ //!@{ //! 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_assert1(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_assert1(v.size() == rows*cols, "Mat::reshape: Sizes must match"); Mat temp(rows, cols); int i, j, ii=0; for (j=0; j Vec repeat(const Vec &v, int norepeats) { Vec temp(v.length()*norepeats); for(int i=0; i Mat repeat(const Mat &m, int norepeats) { Mat temp(m.rows(), m.cols()*norepeats); for (int j=0; j void upsample(const Vec &v, int usf, Vec &u) { it_assert1(usf >= 1, "upsample: upsampling factor must be equal or greater than one" ); u.set_size(v.length()*usf); u.clear(); for(long i=0;i Vec upsample(const Vec &v, int usf) { Vec u; upsample(v,usf,u); return u; } //! Upsample each column by incerting \a (usf-1) zeros after each column template void upsample(const Mat &v, int usf, Mat &u) { it_assert1(usf >= 1, "upsample: upsampling factor must be equal or greater than one" ); u.set_size(v.rows(),v.cols()*usf); u.clear(); for (long j=0;j Mat upsample(const Mat &v, int usf) { Mat u; upsample(v,usf,u); return u; } //! Upsample each column by a factor of \a (usf-1) by linear interpolation template void lininterp(const Mat &m, int usf, Mat &u) { it_assert1(usf >= 1, "lininterp: upsampling factor must be equal or greater than one" ); long L = (m.cols()-1)*usf+1; u.set_size(m.rows(),L); for (long i = 0; i < m.rows(); i++){ for (long j = 0; j < L-1; j++) u(i,j) = (m(i,j/usf) + (j % usf)/((double)usf)*(m(i,(j+usf)/usf)-m(i,j/usf))); u(i,L-1) = m(i,m.cols()-1); } } //! Upsample each column by a factor of \a (usf-1) by linear interpolation template Mat lininterp(const Mat &m, int usf) { Mat u; lininterp(m,usf,u); return u; } //! Upsample by a factor of \a (usf-1) by linear interpolation template void lininterp(const Vec &v, int usf, Vec &u) { it_assert1(usf >= 1, "lininterp: upsampling factor must be equal or greater than one" ); long L = (v.length()-1)*usf+1; u.set_size(L); for (long j = 0; j < L-1; j++) { u(j) = (v(j/usf) + (j % usf)/((double)usf)*(v((j+usf)/usf)-v(j/usf))); } u(L-1) = v(v.length()-1); } //! Upsample by a factor of \a (usf-1) by linear interpolation template Vec lininterp(const Vec &v, int usf) { Vec u; lininterp(v,usf,u); return u; } //!@} } //namespace itpp #endif // __matfunc_h