/*
    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 "measures.h"

namespace Measures
{

	double CountVectorEntropy(CompressedVector& v)
	{
		double entropy = 0.;
		double p;
		double sum = CountVectorSum(v);

		for(std::map<size_t, double>::const_iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			double val = iter->second;
			p = val / sum;
			entropy += p * log(p);
		}

		return -entropy;
	}

	double CountVectorEntropy(CompressedVectorPtr v)
	{

		return CountVectorEntropy(*v);
	}

	double CountVectorSum(CompressedVector& v)
	{
		double sum = 0.;

		for(std::map<size_t, double>::const_iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			sum += iter->second;
		}

		return sum;
	}
	
    double CountVectorSum(CompressedVectorPtr v)
	{
		return CountVectorSum(*v);
	}

	void DevideBySum(CompressedVector& v)
	{
		double sum = CountVectorSum(v);
		DevideByValue(v, sum);
	}

	void DevideByValue(CompressedVector& v, double dev)
	{
		for(std::map<size_t, double>::iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			iter->second = (iter->second) / dev;
		}
	}

	void DevideByValue(CompressedVector& v, const std::vector<double> &dev)
	{
		for(std::map<size_t, double>::iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			iter->second = (iter->second) / dev[iter->first];
		}
	}

	void DevideByEntropy(CompressedVector& v)
	{
		double ent = CountVectorEntropy(v);
		DevideByValue(v, ent);
	}

	void TransformByLog(CompressedVector& v)
	{
		for(std::map<size_t, double>::iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			iter->second = log( iter->second );
		}
	}

	void TransformByLogPlus1(CompressedVector& v)
	{
		for(std::map<size_t, double>::iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			iter->second = log( iter->second +1);
		}
	}


	double CountVectorLength(CompressedVector &v)
	{
		double len2 = 0;
		for(std::map<size_t, double>::iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			len2 += iter->second * iter->second;
		}

		return sqrt(len2);
	}
	MATRICES_API double CountVectorLength(CompressedVectorPtr v)
	{
		return CountVectorLength(*v);
	}

	void NormalizeVector(CompressedVector &v)
	{
		double len = CountVectorLength(v);

		for(std::map<size_t, double>::iterator iter = v.GetValues()->begin();
		iter != v.GetValues()->end(); iter++)
		{
			iter->second = iter->second / len;
		}

	}

	MATRICES_API void NormalizeVector(CompressedVectorPtr v)
	{
		return NormalizeVector(*v);
	}

	double GetMaxValue(CompressedVectorPtr v)
	{
		double max = 0.0;		
		
		for(std::map<size_t, double>::const_iterator iter = v->GetValues()->begin();
		iter != v->GetValues()->end(); iter++)
		{
			max = iter->second > max ? iter->second : max;  
		}

		return max;
	}
}

