/*********************************************************
** Copyright (c) 2005
** University of Washington
** Licensed under the terms set forth by University of
** Washington. If you did not sign such a license, you
** are using this software/code illegally and you do not
** have permission to use, modify, or redistribute
** this or any files in this software package.
**
** File: VectorDataFunctions.h
**
**********************************************************/
#ifndef __VECTORDATAFUNCTIONS__
#define __VECTORDATAFUNCTIONS__

#include <vector>
#include <iostream>
#include <stdint.h>
using namespace std;

#include "ClusterNode.h"
#include "Cluster.h"

typedef vector<double> TDoubleVector;

class CAddVectors : public CCombineDataFunction
{
 public:
  virtual ~CAddVectors() {}

  void* CombineData(CClusterNode* pNode1, CClusterNode* pNode2);
  uintmax_t GetMemoryRequirement();
};

class CCentroidLinkage : public CCombineDataFunction
{
 public:
  virtual ~CCentroidLinkage() {}

  void* CombineData(CClusterNode* pNode1, CClusterNode* pNode2);
  uintmax_t GetMemoryRequirement();
};

/* Euclidean distance between two vectors.
 * Note: This is not the best distance function between
 * time-course data, because the distances between these 
 * two pairs are equal (to 2):
 * ( { 1, 0, 0, 0 } , { 0, 0, 0, 1} )
 * ( { 0, 0, 1, 0 } , { 0, 0, 1, 0} )
 *
 */
class CEuclidean : public CDistanceFunction
{
 public:

  double Distance(CClusterNode* pNode1, CClusterNode* pNode2);
  uintmax_t GetMemoryRequirement();

};

/* "Correlation distance" between two vectors.
 * i.e. distance = 1 - correlation
 *
 * Suffers from same problems as Euclidean distance.
 */
class CCorrelation : public CDistanceFunction
{
 public:
  CCorrelation(int iDataCount);
  virtual ~CCorrelation();

  double Distance(CClusterNode* pNode1, CClusterNode* pNode2);

 private:
  double GetCorrelation(CClusterNode* pData1, CClusterNode *pData2);
  void GetAverageAndStdDev(CClusterNode* pNode, TDoubleVector* pData, double* pAvg, double* pStdDev);
  double GetAverage(TDoubleVector* pData);
  double GetStandardDeviation(TDoubleVector* pData, double avg);
  uintmax_t GetMemoryRequirement();

  inline double Computed(CClusterNode* pData)
  {
    return m_pComputed[pData->GetIndex()];
  }

  char* m_pComputed;
  double* m_pAv;
  double* m_pStdDev;
  int m_memReq;
};

#endif
