/** @(#) mathpos/array2dpos.h */
#ifndef ARRAY2DPOS_H
#define ARRAY2DPOS_H
//----------------------------------------------------------------------------
#include <iostream>
#include <string>
#include <stdexcept> // runtime_exception
using namespace std;
/**
* Reservar memoria.
* No hace operaciones aritmeticas.
* Entrada y salida de arreglos.
* @author Omar Posada Villarreal
* @version 1.1, 24/04/2002
* @version 1.0, 13/04/2002
*/
template <class TC>
class Array2DPos {
//----------------------------------------------------------------------------
private:
/** Apuntador a [firstRow][firstCol]. */
TC **pCorner;
TC **pCenterCol;
/** Apuntador a [0][0]. */
TC **pOrigin;
/** Numero de renglones. */
int row;
int col;
/** Indice del primer renglon */
int firstRow;
int firstCol;
int lastRow;
int lastCol;
//----------------------------------------------------------------------------
public:
// constructor, ~, friend-----------------------------------------------------
/**
* Reserva memoria para un arreglo bidimensional que permite indices negativos.
* DUDA Si firstRow, firstCol de signos contrarios,
* asignacion sin implementar
* Uso:
* Array2DPos<double> M(n, n);
* @param theFirstRow [-N, +N] theFirstRow <= theLastRow
* @param theFirstCol [-N, +N] theFirstCol <= theLastCol
* @param theLastRow [-N, +N]
* @param theLastCol [-N, +N] */
// templates solo en *.h
Array2DPos(int theFirstRow, int theLastRow, int theFirstCol, int theLastCol)
throw (invalid_argument){
// valida
if ((theFirstRow > theLastRow) || (theFirstCol > theLastCol)){
throw invalid_argument("Array2DPos: indices invertidos");
}
firstRow = theFirstRow;
firstCol = theFirstCol;
lastRow = theLastRow;
lastCol = theLastCol;
// Num de reng y col
row = lastRow - firstRow + 1;
col = lastCol - firstCol + 1;
// pCorner
pCorner = new TC*[row];
int i;
for (i = 0; i < row; ++i) {
pCorner[i] = new TC[col];
}
// pOrigin
pCenterCol = new TC*[row];
for (i = 0; i < row; ++i) {
pCenterCol[i] = &(pCorner[i][ -firstCol]);
}
pOrigin = &(pCenterCol[ -firstRow]);
// IMPORTANTE Previene underflow del apuntador pOrigin
// si first > 0, pOrigin < pCorner
if ((firstRow > 0) && (firstCol > 0)) {
if (pOrigin > pCorner) {
throw runtime_exception(
"Array2DPos: apuntador ArrayOrigin negativo.");
}
}
// DUDA Si firstRow, firstCol de signos contrarios,
// asignacion sin implementar
if ( (firstRow * firstCol) < 0 ) {
throw runtime_exception("Array2DPos: falta implementar.");
}
}
Array2DPos(int theRows, int theColumns) throw (invalid_argument) {
if ((theRows < 1) || (theColumns < 1)) {
throw invalid_argument("Array2DPos: indices negativos");
}
Array2DPos(0, theRows - 1, 0, theColumns - 1);
}
/**
* Libera memoria de un arreglo bidimensional de double.
* @param row Numero de renglones.
*/
// templates solo en *.h
~Array2DPos() {
deleteArray();
}
/** Libera memoria. */
void deleteArray() {
delete[] pOrigin;
delete[] pCenterCol;
int i;
for (i = 0; i < row; ++i) {
delete[] pCorner[i];
}
delete []pCorner;
//cout << "} ~Array2DPos()";
}
// inline---------------------------------------------------------------------
inline TC **getArrayOrigin() const {
return pOrigin;
}
inline int getRows() const {
return row;
}
inline int getColumns() const {
return col;
}
inline int getFirstRow() const {
return firstRow;
}
inline int getLastRow() const {
return lastRow;
}
inline int getFirstColumn() const {
return firstCol;
}
inline int getLastColumn() const {
return lastCol;
}
/** Abreviaciones */
inline int gR() const { return row; }
inline int gC() const { return col; }
inline int gFR() const { return firstRow; }
inline int gLR() const { return lastRow; }
inline int gFC() const { return firstCol; }
inline int gLC() const { return lastCol; }
// operator-------------------------------------------------------------------
/** Checa indices. */
TC operator()(int indRow, int indCol) throw (invalid_argument) {
if ( (indRow < firstRow) || (indRow > lastRow)
|| (indCol < firstCol) || (indCol > lastCol) ) {
throw invalid_argument("operator(): indices fuera de rango.");
}
return pOrigin[indRow][indCol];
}
// public---------------------------------------------------------------------
/** Muestra en salida estandar los elementos. Separados. Col:\t, Reng:\n. */
void print() {
int i, j;
for (i = 0; i < row; ++i) {
for (j = 0; j < col; ++j) {
cout << pCorner[i][j] << "\t";
}
cout << endl;
}
}
/** Asigna ceros a todos los elementos. */
void clean() {
int i, j;
for (i = 0; i < row; ++i) {
for (j = 0; j < col; ++j) {
pCorner[i][j] = static_cast<TC>(0);
}
}
}
}; // } Array2DPos------------------------------------------------------------
#endif
// Fin------------------------------------------------------------------------