/*********************************************************************
 * This file is part of the PRAPI library.
 *
 * Copyright (C) 2001 Topi Mäenpää and Jaakko Viertola
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.1 $
 *********************************************************************/

#include "ExtraProximities.h"
#include <Math.h>

using namespace util;

namespace prapi { namespace extras {
		
	JHDistance::JHDistance(const List<Sample<double> >& allSamples)
	{
		int featureCnt = allSamples[0].featureVector().getLength();
		int sampleCnt = allSamples.getLength();
		List<double> stdVector(sampleCnt);
		stdVector.setLength(sampleCnt);
		_lstVarVector.setCapacity(featureCnt);
		
		for (int f=0;f<featureCnt;f++)
			{
				for (int i=0;i<sampleCnt;i++)
					stdVector[i] = allSamples[i].featureVector()[f];
				_lstVarVector += Math::variance(stdVector);
			}
	}

	double JHDistance::getProximity(const List<double>& smpl1, const List<double>& smpl2,
																	double stopAfter) const throw (ProximityException&)
	{
		double dist = 0, tmp;
		
		for (int i=0;i<_lstVarVector.getLength();i++)
			{
				tmp = smpl1[i] - smpl2[i];
				dist += tmp * tmp / _lstVarVector[i];
				if (dist > stopAfter)
					break;
			}
		return dist;
	}


	MMDistance::MMDistance(const List<Sample<double> >& allSamples)
	{
		int featureCnt = allSamples[0].featureVector().getLength();
		int sampleCnt = allSamples.getLength();
		List<double> stdVector(sampleCnt);
		stdVector.setLength(sampleCnt);
		_lstStdVector.setCapacity(featureCnt);
		
		for (int f=0;f<featureCnt;f++)
			{
				for (int i=0;i<sampleCnt;i++)
					stdVector[i] = allSamples[i].featureVector()[f];
				_lstStdVector += Math::stdev(stdVector);
			}
	}

	double MMDistance::getProximity(const List<double>& smpl1, const List<double>& smpl2,
																	double stopAfter) const throw (ProximityException&)
	{
		double dist = 0;
		
		for (int i=0;i<_lstStdVector.getLength();i++)
			{
				dist += absolute(smpl1[i] - smpl2[i]) / _lstStdVector[i];
				if (dist > stopAfter)
					break;
			}
		return dist;
	}
}}
