/*
    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.
*/

#include "matrices_headers.h"
#include "CompressedVector.h"

namespace Matrices
{
	CompressedVector::CompressedVector(size_t uncompressedSize, double* uncompressedData) 
		: m_stUncompressed(uncompressedSize),uncompressed(NULL) 
	{
		m_pVals = new std::map<size_t, double> ();
		Compress(uncompressedSize, uncompressedData);
	}

	CompressedVector::CompressedVector(const std::vector<double> &uncompressedData)
		: m_stUncompressed(uncompressedData.size()),uncompressed(NULL) 
	{
		m_pVals = new std::map<size_t, double> ();
		Compress(uncompressedData.size(), &uncompressedData[0]);
	}

	CompressedVector::~CompressedVector()
	{
		if(uncompressed)
		{
			delete uncompressed;
			uncompressed = NULL;
		}
		
		if(m_pVals)
		{
			delete m_pVals;
			m_pVals = 0;
		}
	}

	CompressedVector::CompressedVector(const CompressedVector& v) 
		: m_stUncompressed(v.m_stUncompressed), uncompressed(NULL)

	{
		m_pVals = new std::map<size_t, double> ();

		*m_pVals = *(v.m_pVals);

	}

	CompressedVector& CompressedVector::operator=(CompressedVector&v)
	{
		*m_pVals = *(v.m_pVals);
		return *this;
	}

	CompressedVector::CompressedVector(const std::map<size_t, double> &mapVal, size_t uncompressedSize)
		: m_stUncompressed(uncompressedSize),
		uncompressed(NULL)
	{
		m_pVals = new std::map<size_t, double> ();

		*m_pVals = mapVal;
	}

	void CompressedVector::Compress(size_t size,const double* data)
	{
		if(!data)
			return;

		for(size_t i = 0; i < size; i++)
		{
			if(data[i] != 0)
			{
				(*m_pVals).insert( std::pair<size_t, double>( i , data[i] ) );
			}
		}
	}

	double CompressedVector::operator[](size_t n) const
	{
		std::map<size_t, double>::iterator i = m_pVals->find(n);

		if( i != m_pVals->end() )
			return i->second;

		return 0;
	}

	void CompressedVector::SetElement(size_t index, double val)
	{
		if(index >= m_stUncompressed)
			return;

		if(val == 0)
			m_pVals->erase(index);
		else
			(*m_pVals)[index] = val;

		if(uncompressed)
		{
			uncompressed[index] = val;
		}

	}

	double* CompressedVector::DecompressData() const
	{
		if(!uncompressed)
			uncompressed = new double[m_stUncompressed];

		memset(uncompressed, 0, sizeof(double) *m_stUncompressed);

		for(std::map<size_t, double>::iterator iter = m_pVals->begin(); iter != m_pVals->end(); iter++)
			uncompressed[iter->first] = iter->second;

		return uncompressed;
	}

	void CompressedVector::FreeBuffer() const
	{
		if(uncompressed)
		{
			delete uncompressed;
			uncompressed = 0;
		}

	}

	size_t CompressedVector::GetUncompresseSize() const
	{
		return m_stUncompressed;
	}

	std::map<size_t, double>* CompressedVector::GetValues()
	{
		return m_pVals;
	}


	CompressedVector& CompressedVector::operator += (const CompressedVector& v)
	{
		for(std::map<size_t, double>::const_iterator index = v.m_pVals->begin();
			index != v.m_pVals->end(); index++)
		{
			std::map<size_t, double>::iterator find = m_pVals->find(index->first);

			if(find != m_pVals->end() )
				find->second = find->second + index->second;
			else
				m_pVals->insert( std::pair<size_t, double>(index->first, index->second));
		}

		return *this;
	}

	CompressedVector& CompressedVector::operator /= (const size_t & number)
	{
		std::map<size_t, double>::iterator iter = m_pVals->begin();

		for (; iter != m_pVals->end(); ++iter)
		{
			iter->second /= number;
		}
		return *this;
	}
}

