// // $Source: /cvsroot/gambit/gambit/sources/libgambit/recarray.h,v $ // $Date: 2006/02/02 19:36:52 $ // $Revision: 1.5 $ // // DESCRIPTION: // Rectangular array base class // // This file is part of Gambit // Copyright (c) 2002, The Gambit Project // // 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // #ifndef LIBGAMBIT_RECARRAY_H #define LIBGAMBIT_RECARRAY_H #include "libgambit.h" namespace Gambit { /// This class implements a rectangular (two-dimensional) array template class RectArray { protected: int minrow, maxrow, mincol, maxcol; T **data; /// @name Range checking functions; returns true only if valid index/size //@{ /// check for correct row index bool CheckRow(int row) const; /// check row vector for correct column boundaries bool CheckRow(const Array &) const; /// check for correct column index bool CheckColumn(int col) const; /// check column vector for correct row boundaries bool CheckColumn(const Array &) const; /// check row and column indices bool Check(int row, int col) const; /// check matrix for same row and column boundaries bool CheckBounds(const RectArray &) const; //@ public: /// @name Lifecycle //@{ RectArray(void); RectArray(unsigned int nrows, unsigned int ncols); RectArray(int minr, int maxr, int minc, int maxc); RectArray(const RectArray &); virtual ~RectArray(); RectArray &operator=(const RectArray &); //@} /// @name General data access //@{ int NumRows(void) const; int NumColumns(void) const; int MinRow(void) const; int MaxRow(void) const; int MinCol(void) const; int MaxCol(void) const; //@} /// @name Indexing operations //@{ T &operator()(int r, int c); const T &operator()(int r, int c) const; //@} /// @name Row and column rotation operators //@{ void RotateUp(int lo, int hi); void RotateDown(int lo, int hi); void RotateLeft(int lo, int hi); void RotateRight(int lo, int hi); //@} /// @name Row and column manipulation functions //@{ void SwitchRow(int, Array &); void SwitchRows(int, int); void GetRow(int, Array &) const; void SetRow(int, const Array &); void SwitchColumn(int, Array &); void SwitchColumns(int, int); void GetColumn(int, Array &) const; void SetColumn(int, const Array &); /// Returns the transpose of the rectangular array RectArray Transpose(void) const; }; //------------------------------------------------------------------------ // RectArray: Private/protected member functions //------------------------------------------------------------------------ template bool RectArray::CheckRow(int row) const { return (minrow <= row && row <= maxrow); } template bool RectArray::CheckRow(const Array &v) const { return (v.First() == mincol && v.Last() == maxcol); } template bool RectArray::CheckColumn(int col) const { return (mincol <= col && col <= maxcol); } template bool RectArray::CheckColumn(const Array &v) const { return (v.First() == minrow && v.Last() == maxrow); } template bool RectArray::Check(int row, int col) const { return (CheckRow(row) && CheckColumn(col)); } template bool RectArray::CheckBounds(const RectArray &m) const { return (minrow == m.minrow && maxrow == m.maxrow && mincol == m.mincol && maxcol == m.maxcol); } //------------------------------------------------------------------------ // RectArray: Constructors, destructor, constructive operators //------------------------------------------------------------------------ template RectArray::RectArray(void) : minrow(1), maxrow(0), mincol(1), maxcol(0), data(0) { } template RectArray::RectArray(unsigned int rows, unsigned int cols) : minrow(1), maxrow(rows), mincol(1), maxcol(cols) { data = (rows > 0) ? new T *[maxrow] - 1 : 0; for (int i = 1; i <= maxrow; data[i++] = (cols > 0) ? new T[maxcol] - 1 : 0); } template RectArray::RectArray(int minr, int maxr, int minc, int maxc) : minrow(minr), maxrow(maxr), mincol(minc), maxcol(maxc) { data = (maxrow >= minrow) ? new T *[maxrow - minrow + 1] - minrow : 0; for (int i = minrow; i <= maxrow; data[i++] = (maxcol - mincol + 1) ? new T[maxcol - mincol + 1] - mincol : 0); } template RectArray::RectArray(const RectArray &a) : minrow(a.minrow), maxrow(a.maxrow), mincol(a.mincol), maxcol(a.maxcol) { data = (maxrow >= minrow) ? new T *[maxrow - minrow + 1] - minrow : 0; for (int i = minrow; i <= maxrow; i++) { data[i] = (maxcol >= mincol) ? new T[maxcol - mincol + 1] - mincol : 0; for (int j = mincol; j <= maxcol; j++) data[i][j] = a.data[i][j]; } } template RectArray::~RectArray() { for (int i = minrow; i <= maxrow; i++) if (data[i]) delete [] (data[i] + mincol); if (data) delete [] (data + minrow); } template RectArray &RectArray::operator=(const RectArray &a) { if (this != &a) { int i; for (i = minrow; i <= maxrow; i++) if (data[i]) delete [] (data[i] + mincol); if (data) delete [] (data + minrow); minrow = a.minrow; maxrow = a.maxrow; mincol = a.mincol; maxcol = a.maxcol; data = (maxrow >= minrow) ? new T *[maxrow - minrow + 1] - minrow : 0; for (i = minrow; i <= maxrow; i++) { data[i] = (maxcol >= mincol) ? new T[maxcol - mincol + 1] - mincol : 0; for (int j = mincol; j <= maxcol; j++) data[i][j] = a.data[i][j]; } } return *this; } //------------------------------------------------------------------------ // RectArray: Data access members //------------------------------------------------------------------------ template int RectArray::NumRows(void) const { return maxrow - minrow + 1; } template int RectArray::NumColumns(void) const { return maxcol - mincol + 1; } template int RectArray::MinRow(void) const { return minrow; } template int RectArray::MaxRow(void) const { return maxrow; } template int RectArray::MinCol(void) const { return mincol; } template int RectArray::MaxCol(void) const { return maxcol; } template T &RectArray::operator()(int r, int c) { if (!Check(r, c)) throw IndexException(); return data[r][c]; } template const T &RectArray::operator()(int r, int c) const { if (!Check(r, c)) throw IndexException(); return data[r][c]; } //------------------------------------------------------------------------ // RectArray: Row and column rotation //------------------------------------------------------------------------ template void RectArray::RotateUp(int lo, int hi) { if (lo < minrow || hi < lo || maxrow < hi) throw IndexException(); T *temp = data[lo]; for (int k = lo; k < hi; k++) data[k] = data[k + 1]; data[hi] = temp; } template void RectArray::RotateDown(int lo, int hi) { if (lo < minrow || hi < lo || maxrow < hi) throw IndexException(); T *temp = data[hi]; for (int k = hi; k > lo; k--) data[k] = data[k - 1]; data[lo] = temp; } template void RectArray::RotateLeft(int lo, int hi) { if (lo < mincol || hi < lo || maxcol < hi) throw IndexException(); T temp; for (int i = minrow; i <= maxrow; i++) { T *row = data[i]; temp = row[lo]; for (int j = lo; j < hi; j++) row[j] = row[j + 1]; row[hi] = temp; } } template void RectArray::RotateRight(int lo, int hi) { if (lo < mincol || hi < lo || maxcol < hi) throw IndexException(); for (int i = minrow; i <= maxrow; i++) { T *row = data[i]; T temp = row[hi]; for (int j = hi; j > lo; j--) row[j] = row[j - 1]; row[lo] = temp; } } //------------------------------------------------------------------------- // RectArray: Row manipulation functions //------------------------------------------------------------------------- template void RectArray::SwitchRow(int row, Array &v) { if (!CheckRow(row)) throw IndexException(); if (!CheckRow(v)) throw DimensionException(); T *rowptr = data[row]; T tmp; for (int i = mincol; i <= maxcol; i++) { tmp = rowptr[i]; rowptr[i] = v[i]; v[i] = tmp; } } template void RectArray::SwitchRows(int i, int j) { if (!CheckRow(i) || !CheckRow(j)) throw IndexException(); T *temp = data[j]; data[j] = data[i]; data[i] = temp; } template void RectArray::GetRow(int row, Array &v) const { if (!CheckRow(row)) throw IndexException(); if (!CheckRow(v)) throw DimensionException(); T *rowptr = data[row]; for (int i = mincol; i <= maxcol; i++) v[i] = rowptr[i]; } template void RectArray::SetRow(int row, const Array &v) { if (!CheckRow(row)) throw IndexException(); if (!CheckRow(v)) throw DimensionException(); T *rowptr = data[row]; for (int i = mincol; i <= maxcol; i++) rowptr[i] = v[i]; } //------------------------------------------------------------------------- // RectArray: Column manipulation functions //------------------------------------------------------------------------- template void RectArray::SwitchColumn(int col, Array &v) { if (!CheckColumn(col)) throw IndexException(); if (!CheckColumn(v)) throw DimensionException(); for (int i = minrow; i <= maxrow; i++) { T tmp = data[i][col]; data[i][col] = v[i]; v[i] = tmp; } } template void RectArray::SwitchColumns(int a, int b) { if (!CheckColumn(a) || !CheckColumn(b)) throw IndexException(); for (int i = minrow; i <= maxrow; i++) { T tmp = data[i][a]; data[i][a] = data[i][b]; data[i][b] = tmp; } } template void RectArray::GetColumn(int col, Array &v) const { if (!CheckColumn(col)) throw IndexException(); if (!CheckColumn(v)) throw DimensionException(); for (int i = minrow; i <= maxrow; i++) v[i] = data[i][col]; } template void RectArray::SetColumn(int col, const Array &v) { if (!CheckColumn(col)) throw IndexException(); if (!CheckColumn(v)) throw DimensionException(); for (int i = minrow; i <= maxrow; i++) data[i][col] = v[i]; } //------------------------------------------------------------------------- // RectArray: Transpose //------------------------------------------------------------------------- template RectArray RectArray::Transpose(void) const { RectArray tmp(mincol, maxcol, minrow, maxrow); for (int i = minrow; i <= maxrow; i++) for (int j = mincol; j <= maxrow; j++) tmp(j,i) = (*this)(i,j); return tmp; } } // end namespace Gambit #endif // LIBGAMBIT_RECARRAY_H