/** @(#) matrixdouble/rectangularmatrix.h */
#ifndef RECTANGULARMATRIX_H
#define RECTANGULARMATRIX_H
//----------------------------------------------------------------------------
#include "matrixdouble.h"
#include "vectordouble.h"
#include "../mathpos/arraypos.h"
#include "../utilpos/interfacepos.h"
#include <limits>	// numeric_limits<float>::min()
#include <iomanip>
#include <iostream>
#include <string>
#include <stdexcept>	// runtime_error
using namespace std;

/**
*
* Caso: Logica uno.
* 	La memoria solicitada es de (nr x nc).
* 	No necesita desperdicio de memoria para funcionar con Numerical Recipes.
*
* @author Omar Posada Villarreal
* @version 1.3, 12/03/2002 actualizar <<, print
* @version 1.2, 04/03/2002 VectorDouble *m;
* @version 1.1, 02/03/2002
* @version 1.0, 27/02/2002
*/
class RectangularMatrix : public MatrixDouble {
	friend ostream & operator<<(
        	ostream &outStr, const RectangularMatrix &matrix);
        friend istream & operator>>(istream &inpStr, RectangularMatrix &matrix);
private:

protected:
       	/**
        * No debe ser publico.
        * por Numerical Recipes en logica uno.
        * El tipo de elementos es "double".
        */
	VectorDouble *m;


public:

// IMPORTANTE: Por el uso de VectorDouble,
// regresar RectangularMatrix causa error de apuntadores
	RectangularMatrix(int theRows, int theColumns,
        	int theLogic, bool cleanMe = true);
	~RectangularMatrix();

	void deleteRectangular();
        // No valores por omision
	void resize(int theRows, int theColumns,
        	int theLogic, bool cleanMe);

	double & operator()(int row, int column)
        		throw (invalid_argument);
	const double & operator()(int row, int column) const
        		throw (invalid_argument);
	VectorDouble operator*(VectorDouble &left);

	static void multiply(
		RectangularMatrix &right, double left,
                RectangularMatrix &res)
		throw (runtime_error);

	static void multiply(
		RectangularMatrix &right, RectangularMatrix &left,
                RectangularMatrix &res);
	static void add(
		RectangularMatrix &right, RectangularMatrix &left,
                RectangularMatrix &res);
	static void substract(
		RectangularMatrix &right, RectangularMatrix &left,
                RectangularMatrix &res);
/* No se puede regresar RectangularMatrix, error con el destructor
	RectangularMatrix operator*(double left);
	RectangularMatrix operator*(RectangularMatrix &left);
        RectangularMatrix operator+(RectangularMatrix &left);
        RectangularMatrix operator-(RectangularMatrix &left);
*/

	void fill(double value);
	void print() const;
	void print(int digits) const;
	void readElements();
	void setLogic(int theLogic);
	VectorDouble takeDiagonal();
	void copyFrom(RectangularMatrix &matrix);
	void transpose(RectangularMatrix &matrix);

        /**
        * Proteger a la matriz de reasignacion de memoria.
        * Permite asignacion (operator=).
        * Logica 0, (0, 0) apunta al matematico A 1,1 esq sup izq
        * @param row Logica cero: [0, row -1]. Logica uno: [1, row]
        * @param column Logica cero: [0, col -1]. Logica uno: [1, col]
        */
	VectorDouble & operator[](int row) {
		return m[row -logic];
        }

        /** Protege de no usarlo. */
	const RectangularMatrix & operator=(const RectangularMatrix &right)
        		throw (runtime_error) {
        	throw runtime_error(
                "operator=: No se puede implementar por VectorDouble.");
		//return NULL;
        }
        /** @version const Sino error por rvalue. */
	const VectorDouble & operator[](int row) const {
        	return m[row-logic];
        }

        /** Limpia la matriz. */
        void clean() {
        	fill(0.0);
        }
};
//----------------------------------------------------------------------------
#endif
// Fin------------------------------------------------------------------------