/*
    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 MATRICES_COMPRESSEDVECTOR_H
#define MATRICES_COMPRESSEDVECTOR_H

#include "matrices_headers.h"

namespace Matrices
{
	typedef std::map<size_t, double> STDoubleMap;
	typedef std::map<size_t, double>::iterator STDoubleMapIter;
	typedef STDoubleMap* STDoubleMapPtr;
	/**
	 * Compressed vector represents a data in sparse matrices. It can be a single row or a single column of a matrix.
	 **/
	class MATRICES_API CompressedVector
	{
	public:
		/**
		 * Creates sparse vector from dense vector given as standard c array.
		 * \param uncompressedData Data to "compress" (copy to CompressedVector), if uncompressedData == NULL then
		 * nothing will be copied, only size of the vector will be set.
		 * \param uncompressedSize Size of the compressed vector (and obviously also size of uncompressedData)
		 **/
		CompressedVector(size_t uncompressedSize, double* uncompressedData = NULL);
		/**
		 * Creates sparse vector from dense vector given as STL vector
		 */
		CompressedVector(const std::vector<double> &uncompressedData);

		/**
		 * Creates sparse vector from sparse data represented as STL map. The map holds a mapping between vector
		 * coordinates and vector values.
		 * \param mapVal mapping between vector coordinates and vector values.
		 * \param uncompressedSize uncompressed (dense) size must be explicitly specified, because it may differ from
		 * maximum value of key in mapVal.
		 */
		CompressedVector(const std::map<size_t, double> &mapVal, size_t uncompressedSize);
		virtual ~CompressedVector();
		CompressedVector(const CompressedVector& v);
		CompressedVector& operator=(CompressedVector&v);

		/**
		 * Retrieves value of vector in the nth dimension.
		*/
		double operator[](size_t n) const;

		/**
		 * Returns uncompressed vector. The memory returned is managed by this class, so subsequent calls to this method
		 * will not result in duplication of memory and extra effort in coping of the data. When data is not needed
		 * memory should be freed by calling FreeBuffer() method.
		 **/
		virtual double* DecompressData() const;
		/**
		 * Clears temporary buffer for dense (uncompressed) data.
		 * \see operator[]
		 **/
		virtual void FreeBuffer() const;

		/**
		 * Sets given element and sets also data in the buffor (if the buffor is actually in use)
		 */
		void SetElement(size_t index, double val);

		/**
		 * Retrives mapping of vector_position->value. Retrieves actual data, not the copy!
		 * \todo Removal of this method, because it exposes CompressedVector internals
		*/
		STDoubleMapPtr GetValues();

		/// Returns size of vector after uncompressing.
		size_t GetUncompresseSize() const;

		/// Sums a vector
		CompressedVector& operator += (const CompressedVector &v);

		/// Divides vector by constant number
		CompressedVector& operator /= (const size_t & number);

	protected:
		/**
		  * "Compresses" vector to sparse format.
		  */
		void Compress(size_t size,const double* data);

		/**
		  * size of uncompressed vector.
		*/
		size_t m_stUncompressed;


		/**
		  * Non-zero values of vector
		*/
		std::map<size_t, double> *m_pVals;

	private:
		/// data buffor
		mutable double *uncompressed;
	};

	typedef boost::shared_ptr<CompressedVector> CompressedVectorPtr;
}

#endif //MATRICES_COMPRESSEDVECTOR_H

