/*
    Copyright (C) 2012 Bartosz Broda, Jacek Bochenek, Łukasz Biłeńkij, 
    Damian Jaworski, Wojciech Mazur, Dominik Piasecki, Maciej Piasecki, 
    Radosław Ramocki
    
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 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 LICENSE and COPYING files for more details.
*/

#ifndef MEMORYMATRIX
#define MEMORYMATRIX

#include "matrices_headers.h"

#include "Matrix.h"

namespace Matrices
{
	/**
	 * Matrix that stores matrix in memory in row-wise fashion.
	 */
	class MATRICES_API MemoryMatrix : public Matrix
	{
		/// Matrix data
		double **m_pdMatrix;
		/// Frees m_pdMatrix
		void FreeMemory();
		/// Allocates memory for matrix
		void AllocateMemory();
	public:
		/**
		 * Standard matrix consturctor.
		 */ 
		MemoryMatrix(const std::string &name, size_t rows, size_t columns);
		~MemoryMatrix(void);

		/**
		  * Retrieves a copy column. Column is dynamically allocated every time, so for large matrices calls to this method
		  * can seriously affect performance. Memory should be freed by calling Matrix::FreeMem.
		  */
		virtual double* GetColumn(size_t colNo) ;
		/**
		  * Retrieves a copy of a row. Row is dynamically allocated every time, so for large matrices calls to this method
		  * can seriously affect performance. Memory should be freed by calling Matrix::FreeMem.
		  */
		virtual double* GetRow(size_t rowNo) ;

		/**
		 * Retrieves a pointer to a row.
		 */
		virtual double* operator[](size_t rowNo);

		/// Acts as described in base class
		virtual void SetRow(std::vector<double> &row, size_t rowIndex);
		/// Acts as described in base class
		virtual void SetRow(double* row, size_t rowIndex);
		/// Acts as described in base class
		virtual void SetColumn(double* col, size_t colIndex);
		/// Acts as described in base class
		virtual void SumRows(double *row, size_t rowIndex);

		/**
		  * Matrix transposition. Matrix is dynamically allocated, so it should be freed by calling to Matrix::FreeMem. 
		  * \param returnMatrix will hold resulting matrix
		  * \throws std::runtime_error if returnMatrix was not null.
		  */
		virtual Matrix*& Transpose(Matrix*&  returnMatrix);
		/// Acts as described in base class
		virtual void SetCell(double val, size_t rowInd, size_t colInd);
		/// Acts as described in base class
		virtual double GetCell(size_t rowInd, size_t colInd);
		/// Acts as described in base class
		virtual void Clear();
		/// Acts as described in base class
		virtual void AddToCell(double value, size_t rowIndex, size_t columnIndex);
		/**
		 * Clones a matrix. If input parameter is null, then matrix will be allocated dynamically. In other cases,
		 * matrix will be cleared (matrix->Clear()) and all rows will be set. It is assumed that in the second case matrix 
		 * has the same dimensions as cloned matrix.
		 */ 
		virtual void Clone(Matrix* matrix) ;
	};

	/// Shared pointer on memory matrix.
	typedef boost::shared_ptr<MemoryMatrix> MemoryMatrixPtr;
}

#endif

