/* dtkMatrix.tpp --- * * Author: Thibaud Kloczko * Copyright (C) 2008 - Thibaud Kloczko, Inria. */ /* Commentary: * */ /* Change log: * */ #ifndef DTKMATRIX_TPP #define DTKMATRIX_TPP #include #include #include #include #include #include enum { N_NOTALLOCATED, N_ALLOCATED, N_MAPPED }; namespace dtkDeprecated { // ///////////////////////////////////////////////////////////////// // Template specializations forward declarations // ///////////////////////////////////////////////////////////////// template <> DTKMATHSUPPORT_EXPORT QByteArray *dtkMatrix::serialize(void); template <> DTKMATHSUPPORT_EXPORT void dtkMatrix::deserialize(const QByteArray& array); // ///////////////////////////////////////////////////////////////// // dtkMatrix implementation // ///////////////////////////////////////////////////////////////// //! Default constructor. template inline dtkMatrix::dtkMatrix(void) { initialize(); }; //! Creates a matrix, allocates rows and columns template inline dtkMatrix::dtkMatrix(unsigned crow, unsigned ccol) { initialize(); allocate(crow, ccol); } //! Creates a matrix, allocates rows and columns template inline dtkMatrix::dtkMatrix(T *array, unsigned crow, unsigned ccol) { initialize(); fromRawData(array, crow, ccol); } //! Copy constructor. template inline dtkMatrix::dtkMatrix(const dtkMatrix& mat) { initialize(); if (mat.m_nMatStatus == N_NOTALLOCATED) return; else (*this) = mat ; } //! Mapped matrix constructor. template inline dtkMatrix::dtkMatrix(const dtkMatrix& mat, unsigned irowStart, unsigned icolStart, unsigned irowEnd, unsigned icolEnd) { initialize(); mapInto(mat, irowStart, icolStart, irowEnd, icolEnd); } template inline dtkMatrix::~dtkMatrix(void) { if (m_crow) deallocate(); } //! Private method giving initial values for matrix attributes. template inline void dtkMatrix::initialize(void) { m_crow = 0; m_ccol = 0; m_rgrow = NULL; m_nMatStatus = N_NOTALLOCATED; } //! Returns identifier of the matrix. template QString dtkMatrix::identifier(void) const { return QString("dtkMatrix<%1>").arg(typeid(T).name()); } //! Returns description of the contain of the matrix. template QString dtkMatrix::description(void) const { QString string; string = "[ " ; for (unsigned i = 0; i < numberOfRows(); i++) { if (i > 0) string.append("; "); QString string2 = QString("%1").arg(m_rgrow[i][0]); string += string2; for (unsigned j = 1; j < numberOfColumns(); j++) { string.append(", "); QString string3 = QString("%1").arg(m_rgrow[i][j]); string += string3; } } string.append(" ]"); return string; } //! template void dtkMatrix::allocate(unsigned crowInit, unsigned ccolInit) { if (m_nMatStatus != N_NOTALLOCATED) { if (m_crow == crowInit && m_ccol == ccolInit) return; else deallocate(); } m_crow = crowInit; m_ccol = ccolInit; if ((m_crow * m_ccol) == 0) { m_nMatStatus = N_NOTALLOCATED; m_crow = 0; m_ccol = 0; return; } m_rgrow = new T*[m_crow]; T *ptTmp = new T[m_crow * m_ccol]; for (unsigned irow = 0; irow < m_crow; ++irow) m_rgrow[irow] = &(ptTmp[irow * m_ccol]); m_nMatStatus = N_ALLOCATED; } //! template void dtkMatrix::deallocate(void) { switch (m_nMatStatus) { case N_NOTALLOCATED: break; case N_MAPPED: delete [] m_rgrow; break; case N_ALLOCATED: delete [] *m_rgrow; delete [] m_rgrow; break; }; initialize(); } //! /*! * */ template void dtkMatrix::fromRawData(T *array, unsigned crowInit, unsigned ccolInit) { if (m_nMatStatus != N_NOTALLOCATED) deallocate(); m_crow = crowInit; m_ccol = ccolInit; if ((m_crow * m_ccol) == 0) { m_nMatStatus = N_NOTALLOCATED; m_crow = 0; m_ccol = 0; return; } m_rgrow = new T*[m_crow]; T *ptTmp = array; for (unsigned irow = 0; irow < m_crow; ++irow) m_rgrow[irow] = &(ptTmp[irow * m_ccol]); m_nMatStatus = N_MAPPED; } //! /*! * Maps a matrix into another matrix, deallocates first if neccesary * allocates space on the free store for a matrix, deallocates first * if neccesary. */ template void dtkMatrix::mapInto(const dtkMatrix& mat, unsigned irowStart, unsigned icolStart, unsigned irowEnd, unsigned icolEnd ) { if (m_nMatStatus != N_NOTALLOCATED) deallocate(); m_crow = irowEnd - irowStart + 1; m_ccol = icolEnd - icolStart + 1; m_rgrow = new T*[m_crow]; for (unsigned irow = 0; irow < m_crow; ++irow) m_rgrow[irow] = &mat.m_rgrow[irow + irowStart][icolStart]; m_nMatStatus = N_MAPPED; } template inline int dtkMatrix::getStatus(void) const { return m_nMatStatus; } template inline unsigned dtkMatrix::getRows(void) const { return m_crow; } template inline unsigned dtkMatrix::getCols(void) const { return m_ccol; } //! template dtkMatrix dtkMatrix::operator +(const dtkMatrix& mat) const { return dtkMatrix( *this ) += mat; } //! template dtkMatrix dtkMatrix::operator -(const dtkMatrix& mat) const { return dtkMatrix( *this ) -= mat; } //! template dtkMatrix dtkMatrix::operator -(void) const { T tTmp = dtkZero(); tTmp -= dtkUnity(); return (*this) * tTmp; } //! template dtkMatrix dtkMatrix::operator *(const T& value) const { return dtkMatrix( *this ) *= value; } //! template dtkMatrix dtkMatrix::operator *(const dtkMatrix& mat) const { dtkMatrix matResult( m_crow , mat.m_ccol ); matResult.storeProduct( *this , mat ); return matResult; } //! Assignment operator. template dtkMatrix& dtkMatrix::operator =(const dtkMatrix& mat) { if (m_nMatStatus == N_NOTALLOCATED) allocate(mat.m_crow, mat.m_ccol); for (unsigned irow = 0; irow < m_crow; ++irow) for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irow][icol] = mat.m_rgrow[irow][icol]; return *this; } //! template dtkMatrix& dtkMatrix::operator +=(const dtkMatrix& mat) { for (unsigned irow = 0; irow < m_crow; ++irow) for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irow][icol] += mat.m_rgrow[irow][icol]; return *this; } //! template dtkMatrix& dtkMatrix::operator -=(const dtkMatrix& mat) { for (unsigned irow = 0; irow < m_crow; ++irow) for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irow][icol] -= mat.m_rgrow[irow][icol]; return *this; } //! template dtkMatrix& dtkMatrix::operator *=(const T& value) { for (unsigned irow = 0; irow < m_crow; ++irow) for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irow][icol] *= value; return *this; } //! template int dtkMatrix::operator ==(const dtkMatrix& mat) const { if ((m_crow == mat.m_crow) && (m_ccol == mat.m_ccol)) { for (unsigned irow = 0; irow < m_crow; ++irow) { for (unsigned icol = 0; icol < m_ccol; ++icol) if (m_rgrow[irow][icol] != mat.m_rgrow[irow][icol]) return 0; } return 1; } else return 0; } //! Stores mat1 + mat2 in this. template void dtkMatrix::storeSum(const dtkMatrix& mat1, const dtkMatrix& mat2) { for (unsigned irow = 0; irow < m_crow; ++irow) for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irow][icol] = mat1.m_rgrow[irow][icol] + mat2.m_rgrow[irow][icol]; } //! Stores mat1*mat2 in this. template void dtkMatrix::storeProduct(const dtkMatrix& mat1, const dtkMatrix& mat2) { for (unsigned irow = 0; irow < m_crow; ++irow) { for (unsigned icol = 0; icol < m_ccol; ++icol) { m_rgrow[irow][icol] = dtkZero(); for (unsigned icol2 = 0; icol2 < mat1.m_ccol; ++icol2) m_rgrow[irow][icol] += mat1.m_rgrow[irow][icol2] * mat2.m_rgrow[icol2][icol]; } } } //! Stores a matrix mat at position (irowStart,icolStart). Matrix mat should fit in this. template void dtkMatrix::storeAtPosition(unsigned irowStart, unsigned icolStart, const dtkMatrix& mat) { for (unsigned irow = 0; irow < mat.m_crow; ++irow) for (unsigned icol = 0; icol < mat.m_ccol; ++icol) m_rgrow[irow + irowStart][icol + icolStart] = mat.m_rgrow[irow][icol]; } //! Stores transpose of mat in this. template void dtkMatrix::storeTranspose(const dtkMatrix& mat) { for (unsigned irow = 0; irow < m_crow; ++irow) for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irow][icol] = mat.m_rgrow[icol][irow]; } //! template inline void dtkMatrix::fill(const T& elemFill) { unsigned iEnd = m_crow * m_ccol; for (unsigned i = 0; i < iEnd; ++i) (*m_rgrow)[i] = elemFill; } //! template inline void dtkMatrix::makeTranspose(void) { T temp; for (unsigned irow = 0; irow < m_crow; ++irow) { for (unsigned icol = 0; icol < m_ccol; ++icol) { temp = m_rgrow[irow][icol]; m_rgrow[irow][icol] = m_rgrow[icol][irow]; m_rgrow[icol][irow] = temp; } } } //! template void dtkMatrix::interchangeRows(unsigned irow1, unsigned irow2) { T *rowSav = m_rgrow[irow1]; m_rgrow[irow1] = m_rgrow[irow2]; m_rgrow[irow2] = rowSav; } //! template void dtkMatrix::multiplyRow(unsigned irow, const T& value) { for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irow][icol] *= value; } //! template void dtkMatrix::addRowToRow(unsigned irowSrc, unsigned irowDest, const T& value) { for (unsigned icol = 0; icol < m_ccol; ++icol) m_rgrow[irowDest][icol] += m_rgrow[irowSrc][icol] * value; } //! Returns product mat*value. template inline dtkMatrix operator *(const T& value, const dtkMatrix& mat) { return mat * value; } //! Returns transpose of mat. template dtkMatrix dtkTranspose(const dtkMatrix& mat) { dtkMatrix matTranspose( mat.numberOfColumns(), mat.numberOfRows() ); matTranspose.storeTranspose(mat); return matTranspose; } //! template std::ostream& operator <<(std::ostream& os, const dtkMatrix& mat) { os << "[" ; for (unsigned i = 0; i < mat.numberOfRows(); i++) { if (i > 0) os << "; "; os << mat[i][0]; for (unsigned j = 1; j < mat.numberOfColumns(); j++) os << ", " << mat[i][j]; } os << "]"; return os; } //! template QDebug operator<<(QDebug dbg, const dtkMatrix& mat) { dbg.nospace() << "[" ; for (unsigned i = 0; i < mat.numberOfRows(); i++) { if (i > 0) dbg.nospace() << ";"; dbg.nospace() << mat[i][0]; for (unsigned j = 1; j < mat.numberOfColumns(); j++) dbg.nospace() << "," << mat[i][j]; } dbg.nospace() << "]"; return dbg.space(); } //! template QDebug operator<<(QDebug dbg, const dtkMatrix *mat) { dbg.nospace() << "[" ; for (unsigned i = 0; i < mat->numberOfRows(); i++) { if (i > 0) dbg.nospace() << ";"; dbg.nospace() << mat[i][0]; for (unsigned j = 1; j < mat->numberOfColumns(); j++) dbg.nospace() << "," << mat[i][j]; } dbg.nospace() << "]"; return dbg.space(); } template QByteArray *dtkMatrix::serialize(void) { return NULL; }; template void dtkMatrix::deserialize(const QByteArray& array) { }; } // end namespace #endif