//////////////////////////////////////////////////////////////////////////////// // Author: Andy Rushton // Copyright: (c) Southampton University 1999-2004 // (c) Andy Rushton 2004 onwards // License: BSD License, see ../docs/license.html //////////////////////////////////////////////////////////////////////////////// namespace stlplus { //////////////////////////////////////////////////////////////////////////////// template<typename T> matrix<T>::matrix(unsigned rows, unsigned cols, const T& fill) { m_rows = 0; m_cols = 0; m_data = 0; resize(rows,cols,fill); } template<typename T> matrix<T>::~matrix(void) { for (unsigned row = 0; row < m_rows; row++) delete[] m_data[row]; delete[] m_data; } template<typename T> matrix<T>::matrix(const matrix<T>& r) { m_rows = 0; m_cols = 0; m_data = 0; *this = r; } template<typename T> matrix<T>& matrix<T>::operator =(const matrix<T>& right) { // clear the old values for (unsigned row = 0; row < m_rows; row++) delete[] m_data[row]; delete[] m_data; m_rows = 0; m_cols = 0; m_data = 0; // now reconstruct with the new resize(right.m_rows, right.m_cols); for (unsigned row = 0; row < m_rows; row++) for (unsigned col = 0; col < m_cols; col++) m_data[row][col] = right.m_data[row][col]; return *this; } template<typename T> void matrix<T>::resize(unsigned rows, unsigned cols, const T& fill) { // a grid is an array of rows, where each row is an array of T // a zero-row or zero-column matrix has a null grid // TODO - make this exception-safe - new could throw here and that would cause a memory leak T** new_grid = 0; if (rows && cols) { new_grid = new T*[rows]; for (unsigned row = 0; row < rows; row++) { new_grid[row] = new T[cols]; // copy old items to the new grid but only within the bounds of the intersection of the old and new grids // fill the rest of the grid with the initial value for (unsigned col = 0; col < cols; col++) if (row < m_rows && col < m_cols) new_grid[row][col] = m_data[row][col]; else new_grid[row][col] = fill; } } // destroy the old grid for (unsigned row = 0; row < m_rows; row++) delete[] m_data[row]; delete[] m_data; // move the new data into the matrix m_data = new_grid; m_rows = rows; m_cols = cols; } template<typename T> unsigned matrix<T>::rows(void) const { return m_rows; } template<typename T> unsigned matrix<T>::columns(void) const { return m_cols; } template<typename T> void matrix<T>::erase(const T& fill) { for (unsigned row = 0; row < m_rows; row++) for (unsigned col = 0; col < m_cols; col++) insert(row,col,fill); } template<typename T> void matrix<T>::erase(unsigned row, unsigned col, const T& fill) { insert(row,col,fill); } template<typename T> void matrix<T>::insert(unsigned row, unsigned col, const T& element) { if (row >= m_rows) throw std::out_of_range("matrix::insert row"); if (col >= m_cols) throw std::out_of_range("matrix::insert col"); m_data[row][col] = element; } template<typename T> const T& matrix<T>::item(unsigned row, unsigned col) const { if (row >= m_rows) throw std::out_of_range("matrix::item row"); if (col >= m_cols) throw std::out_of_range("matrix::item col"); return m_data[row][col]; } template<typename T> T& matrix<T>::item(unsigned row, unsigned col) { if (row >= m_rows) throw std::out_of_range("matrix::item row"); if (col >= m_cols) throw std::out_of_range("matrix::item col"); return m_data[row][col]; } template<typename T> const T& matrix<T>::operator()(unsigned row, unsigned col) const { if (row >= m_rows) throw std::out_of_range("matrix::operator() row"); if (col >= m_cols) throw std::out_of_range("matrix::operator() col"); return m_data[row][col]; } template<typename T> T& matrix<T>::operator()(unsigned row, unsigned col) { if (row >= m_rows) throw std::out_of_range("matrix::operator() row"); if (col >= m_cols) throw std::out_of_range("matrix::operator() col"); return m_data[row][col]; } template<typename T> void matrix<T>::fill(const T& item) { erase(item); } template<typename T> void matrix<T>::fill_column(unsigned col, const T& item) { if (col >= m_cols) throw std::out_of_range("matrix::fill_column"); for (unsigned row = 0; row < m_rows; row++) insert(row, col, item); } template<typename T> void matrix<T>::fill_row(unsigned row, const T& item) { if (row >= m_rows) throw std::out_of_range("matrix::fill_row"); for (unsigned col = 0; col < m_cols; col++) insert(row, col, item); } template<typename T> void matrix<T>::fill_leading_diagonal(const T& item) { for (unsigned i = 0; i < m_cols && i < m_rows; i++) insert(i, i, item); } template<typename T> void matrix<T>::fill_trailing_diagonal(const T& item) { for (unsigned i = 0; i < m_cols && i < m_rows; i++) insert(i, m_cols-i-1, item); } template<typename T> void matrix<T>::make_identity(const T& one, const T& zero) { fill(zero); fill_leading_diagonal(one); } template<typename T> void matrix<T>::transpose(void) { // no gain in manipulating this, since building a new matrix is no less efficient matrix<T> transposed(columns(), rows()); for (unsigned row = 0; row < rows(); row++) for (unsigned col = 0; col < columns(); col++) transposed.insert(col,row,item(row,col)); // TODO - avoid an extra copy by swapping the member data here *this = transposed; } //////////////////////////////////////////////////////////////////////////////// } // end namespace stlplus