Delete unneeded directory
[jabaws.git] / website / archive / binaries / mac / src / muscle / clust.cpp
diff --git a/website/archive/binaries/mac/src/muscle/clust.cpp b/website/archive/binaries/mac/src/muscle/clust.cpp
deleted file mode 100644 (file)
index 97e9d7c..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-#include "muscle.h"\r
-#include "clust.h"\r
-#include "clustset.h"\r
-#include <stdio.h>\r
-\r
-#define TRACE          0\r
-\r
-Clust::Clust()\r
-       {\r
-       m_Nodes = 0;\r
-       m_uNodeCount = 0;\r
-       m_uLeafCount = 0;\r
-       m_uClusterCount = 0;\r
-       m_JoinStyle = JOIN_Undefined;\r
-       m_dDist = 0;\r
-       m_uLeafCount = 0;\r
-       m_ptrSet = 0;\r
-       }\r
-\r
-Clust::~Clust()\r
-       {\r
-       delete[] m_Nodes;\r
-       delete[] m_dDist;\r
-       delete[] m_ClusterIndexToNodeIndex;\r
-       }\r
-\r
-void Clust::Create(ClustSet &Set, CLUSTER Method)\r
-       {\r
-       m_ptrSet = &Set;\r
-\r
-       SetLeafCount(Set.GetLeafCount());\r
-\r
-       switch (Method)\r
-               {\r
-       case CLUSTER_UPGMA:\r
-               m_JoinStyle = JOIN_NearestNeighbor;\r
-               m_CentroidStyle = LINKAGE_Avg;\r
-               break;\r
-\r
-       case CLUSTER_UPGMAMax:\r
-               m_JoinStyle = JOIN_NearestNeighbor;\r
-               m_CentroidStyle = LINKAGE_Max;\r
-               break;\r
-\r
-       case CLUSTER_UPGMAMin:\r
-               m_JoinStyle = JOIN_NearestNeighbor;\r
-               m_CentroidStyle = LINKAGE_Min;\r
-               break;\r
-\r
-       case CLUSTER_UPGMB:\r
-               m_JoinStyle = JOIN_NearestNeighbor;\r
-               m_CentroidStyle = LINKAGE_Biased;\r
-               break;\r
-\r
-       case CLUSTER_NeighborJoining:\r
-               m_JoinStyle = JOIN_NeighborJoining;\r
-               m_CentroidStyle = LINKAGE_NeighborJoining;\r
-               break;\r
-\r
-       default:\r
-               Quit("Clust::Create, invalid method %d", Method);\r
-               }\r
-\r
-       if (m_uLeafCount <= 1)\r
-               Quit("Clust::Create: no leaves");\r
-\r
-       m_uNodeCount = 2*m_uLeafCount - 1;\r
-       m_Nodes = new ClustNode[m_uNodeCount];\r
-       m_ClusterIndexToNodeIndex = new unsigned[m_uLeafCount];\r
-\r
-       m_ptrClusterList = 0;\r
-       for (unsigned uNodeIndex = 0; uNodeIndex < m_uNodeCount; ++uNodeIndex)\r
-               {\r
-               ClustNode &Node = m_Nodes[uNodeIndex];\r
-               Node.m_uIndex = uNodeIndex;\r
-               if (uNodeIndex < m_uLeafCount)\r
-                       {\r
-                       Node.m_uSize = 1;\r
-                       Node.m_uLeafIndexes = new unsigned[1];\r
-                       Node.m_uLeafIndexes[0] = uNodeIndex;\r
-                       AddToClusterList(uNodeIndex);\r
-                       }\r
-               else\r
-                       Node.m_uSize = 0;\r
-               }\r
-\r
-// Compute initial distance matrix between leaves\r
-       SetProgressDesc("Build dist matrix");\r
-       unsigned uPairIndex = 0;\r
-       const unsigned uPairCount = (m_uLeafCount*(m_uLeafCount - 1))/2;\r
-       for (unsigned i = 0; i < m_uLeafCount; ++i)\r
-               for (unsigned j = 0; j < i; ++j)\r
-                       {\r
-                       const float dDist = (float) m_ptrSet->ComputeDist(*this, i, j);\r
-                       SetDist(i, j, dDist);\r
-                       if (0 == uPairIndex%10000)\r
-                               Progress(uPairIndex, uPairCount);\r
-                       ++uPairIndex;\r
-                       }\r
-       ProgressStepsDone();\r
-\r
-// Call CreateCluster once for each internal node in the tree\r
-       SetProgressDesc("Build guide tree");\r
-       m_uClusterCount = m_uLeafCount;\r
-       const unsigned uInternalNodeCount = m_uNodeCount - m_uLeafCount;\r
-       for (unsigned uNodeIndex = m_uLeafCount; uNodeIndex < m_uNodeCount; ++uNodeIndex)\r
-               {\r
-               unsigned i = uNodeIndex + 1 - m_uLeafCount;\r
-               Progress(i, uInternalNodeCount);\r
-               CreateCluster();\r
-               }\r
-       ProgressStepsDone();\r
-       }\r
-\r
-void Clust::CreateCluster()\r
-       {\r
-       unsigned uLeftNodeIndex;\r
-       unsigned uRightNodeIndex;\r
-       float dLeftLength;\r
-       float dRightLength;\r
-       ChooseJoin(&uLeftNodeIndex, &uRightNodeIndex, &dLeftLength, &dRightLength);\r
-\r
-       const unsigned uNewNodeIndex = m_uNodeCount - m_uClusterCount + 1;\r
-\r
-       JoinNodes(uLeftNodeIndex, uRightNodeIndex, dLeftLength, dRightLength,\r
-         uNewNodeIndex);\r
-\r
-#if    TRACE\r
-       Log("Merge New=%u L=%u R=%u Ld=%7.2g Rd=%7.2g\n",\r
-         uNewNodeIndex, uLeftNodeIndex, uRightNodeIndex, dLeftLength, dRightLength);\r
-#endif\r
-\r
-// Compute distances to other clusters\r
-       --m_uClusterCount;\r
-       for (unsigned uNodeIndex = GetFirstCluster(); uNodeIndex != uInsane;\r
-         uNodeIndex = GetNextCluster(uNodeIndex))\r
-               {\r
-               if (uNodeIndex == uLeftNodeIndex || uNodeIndex == uRightNodeIndex)\r
-                       continue;\r
-\r
-               if (uNewNodeIndex == uNodeIndex)\r
-                       continue;\r
-\r
-               const float dDist = ComputeDist(uNewNodeIndex, uNodeIndex);\r
-               SetDist(uNewNodeIndex, uNodeIndex, dDist);\r
-               }\r
-\r
-       for (unsigned uNodeIndex = GetFirstCluster(); uNodeIndex != uInsane;\r
-         uNodeIndex = GetNextCluster(uNodeIndex))\r
-               {\r
-               if (uNodeIndex == uLeftNodeIndex || uNodeIndex == uRightNodeIndex)\r
-                       continue;\r
-\r
-               if (uNewNodeIndex == uNodeIndex)\r
-                       continue;\r
-\r
-#if    REDLACK\r
-               const float dMetric = ComputeMetric(uNewNodeIndex, uNodeIndex);\r
-               InsertMetric(uNewNodeIndex, uNodeIndex, dMetric);\r
-#endif\r
-               }\r
-       }\r
-\r
-void Clust::ChooseJoin(unsigned *ptruLeftIndex, unsigned *ptruRightIndex,\r
-  float *ptrdLeftLength, float *ptrdRightLength)\r
-       {\r
-       switch (m_JoinStyle)\r
-               {\r
-       case JOIN_NearestNeighbor:\r
-               ChooseJoinNearestNeighbor(ptruLeftIndex, ptruRightIndex, ptrdLeftLength,\r
-                 ptrdRightLength);\r
-               return;\r
-       case JOIN_NeighborJoining:\r
-               ChooseJoinNeighborJoining(ptruLeftIndex, ptruRightIndex, ptrdLeftLength,\r
-                 ptrdRightLength);\r
-               return;\r
-               }\r
-       Quit("Clust::ChooseJoin, Invalid join style %u", m_JoinStyle);\r
-       }\r
-\r
-void Clust::ChooseJoinNearestNeighbor(unsigned *ptruLeftIndex,\r
-  unsigned *ptruRightIndex, float *ptrdLeftLength, float *ptrdRightLength)\r
-       {\r
-       const unsigned uClusterCount = GetClusterCount();\r
-\r
-       unsigned uMinLeftNodeIndex;\r
-       unsigned uMinRightNodeIndex;\r
-       GetMinMetric(&uMinLeftNodeIndex, &uMinRightNodeIndex);\r
-\r
-       float dMinDist = GetDist(uMinLeftNodeIndex, uMinRightNodeIndex);\r
-\r
-       const float dLeftHeight = GetHeight(uMinLeftNodeIndex);\r
-       const float dRightHeight = GetHeight(uMinRightNodeIndex);\r
-\r
-       *ptruLeftIndex = uMinLeftNodeIndex;\r
-       *ptruRightIndex = uMinRightNodeIndex;\r
-       *ptrdLeftLength = dMinDist/2 - dLeftHeight;\r
-       *ptrdRightLength = dMinDist/2 - dRightHeight;\r
-       }\r
-\r
-void Clust::ChooseJoinNeighborJoining(unsigned *ptruLeftIndex,\r
-  unsigned *ptruRightIndex, float *ptrdLeftLength, float *ptrdRightLength)\r
-       {\r
-       const unsigned uClusterCount = GetClusterCount();\r
-\r
-       //unsigned uMinLeftNodeIndex = uInsane;\r
-       //unsigned uMinRightNodeIndex = uInsane;\r
-       //float dMinD = PLUS_INFINITY;\r
-       //for (unsigned i = GetFirstCluster(); i != uInsane; i = GetNextCluster(i))\r
-       //      {\r
-       //      const float ri = Calc_r(i);\r
-       //      for (unsigned j = GetNextCluster(i); j != uInsane; j = GetNextCluster(j))\r
-       //              {\r
-       //              const float rj = Calc_r(j);\r
-       //              const float dij = GetDist(i, j);\r
-       //              const float Dij = dij - (ri + rj);\r
-       //              if (Dij < dMinD)\r
-       //                      {\r
-       //                      dMinD = Dij;\r
-       //                      uMinLeftNodeIndex = i;\r
-       //                      uMinRightNodeIndex = j;\r
-       //                      }\r
-       //              }\r
-       //      }\r
-\r
-       unsigned uMinLeftNodeIndex;\r
-       unsigned uMinRightNodeIndex;\r
-       GetMinMetric(&uMinLeftNodeIndex, &uMinRightNodeIndex);\r
-\r
-       const float dDistLR = GetDist(uMinLeftNodeIndex, uMinRightNodeIndex);\r
-       const float rL = Calc_r(uMinLeftNodeIndex);\r
-       const float rR = Calc_r(uMinRightNodeIndex);\r
-\r
-       const float dLeftLength = (dDistLR + rL - rR)/2;\r
-       const float dRightLength = (dDistLR - rL + rR)/2;\r
-\r
-       *ptruLeftIndex = uMinLeftNodeIndex;\r
-       *ptruRightIndex = uMinRightNodeIndex;\r
-       *ptrdLeftLength = dLeftLength;\r
-       *ptrdRightLength = dRightLength;\r
-       }\r
-\r
-void Clust::JoinNodes(unsigned uLeftIndex, unsigned uRightIndex, float dLeftLength,\r
-  float dRightLength, unsigned uNodeIndex)\r
-       {\r
-       ClustNode &Parent = m_Nodes[uNodeIndex];\r
-       ClustNode &Left = m_Nodes[uLeftIndex];\r
-       ClustNode &Right = m_Nodes[uRightIndex];\r
-\r
-       Left.m_dLength = dLeftLength;\r
-       Right.m_dLength = dRightLength;\r
-\r
-       Parent.m_ptrLeft = &Left;\r
-       Parent.m_ptrRight = &Right;\r
-\r
-       Left.m_ptrParent = &Parent;\r
-       Right.m_ptrParent = &Parent;\r
-\r
-       const unsigned uLeftSize = Left.m_uSize;\r
-       const unsigned uRightSize = Right.m_uSize;\r
-       const unsigned uParentSize = uLeftSize + uRightSize;\r
-       Parent.m_uSize = uParentSize;\r
-\r
-       assert(0 == Parent.m_uLeafIndexes);\r
-       Parent.m_uLeafIndexes = new unsigned[uParentSize];\r
-\r
-       const unsigned uLeftBytes = uLeftSize*sizeof(unsigned);\r
-       const unsigned uRightBytes = uRightSize*sizeof(unsigned);\r
-       memcpy(Parent.m_uLeafIndexes, Left.m_uLeafIndexes, uLeftBytes);\r
-       memcpy(Parent.m_uLeafIndexes + uLeftSize, Right.m_uLeafIndexes, uRightBytes);\r
-\r
-       DeleteFromClusterList(uLeftIndex);\r
-       DeleteFromClusterList(uRightIndex);\r
-       AddToClusterList(uNodeIndex);\r
-       }\r
-\r
-float Clust::Calc_r(unsigned uNodeIndex) const\r
-       {\r
-       const unsigned uClusterCount = GetClusterCount();\r
-       if (2 == uClusterCount)\r
-               return 0;\r
-\r
-       float dSum = 0;\r
-       for (unsigned i = GetFirstCluster(); i != uInsane; i = GetNextCluster(i))\r
-               {\r
-               if (i == uNodeIndex)\r
-                       continue;\r
-               dSum += GetDist(uNodeIndex, i);\r
-               }\r
-       return dSum/(uClusterCount - 2);\r
-       }\r
-\r
-float Clust::ComputeDist(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
-       {\r
-       switch (m_CentroidStyle)\r
-               {\r
-       case LINKAGE_Avg:\r
-               return ComputeDistAverageLinkage(uNewNodeIndex, uNodeIndex);\r
-\r
-       case LINKAGE_Min:\r
-               return ComputeDistMinLinkage(uNewNodeIndex, uNodeIndex);\r
-\r
-       case LINKAGE_Max:\r
-               return ComputeDistMaxLinkage(uNewNodeIndex, uNodeIndex);\r
-\r
-       case LINKAGE_Biased:\r
-               return ComputeDistMAFFT(uNewNodeIndex, uNodeIndex);\r
-\r
-       case LINKAGE_NeighborJoining:\r
-               return ComputeDistNeighborJoining(uNewNodeIndex, uNodeIndex);\r
-               }\r
-       Quit("Clust::ComputeDist, invalid centroid style %u", m_CentroidStyle);\r
-       return (float) g_dNAN;\r
-       }\r
-\r
-float Clust::ComputeDistMinLinkage(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
-       {\r
-       const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
-       const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
-       const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
-       const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
-       return (dDistL < dDistR ? dDistL : dDistR);\r
-       }\r
-\r
-float Clust::ComputeDistMaxLinkage(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
-       {\r
-       const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
-       const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
-       const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
-       const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
-       return (dDistL > dDistR ? dDistL : dDistR);\r
-       }\r
-\r
-float Clust::ComputeDistAverageLinkage(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
-       {\r
-       const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
-       const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
-       const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
-       const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
-       return (dDistL + dDistR)/2;\r
-       }\r
-\r
-float Clust::ComputeDistNeighborJoining(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
-       {\r
-       const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
-       const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
-       const float dDistLR = GetDist(uLeftNodeIndex, uRightNodeIndex);\r
-       const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
-       const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
-       const float dDist = (dDistL + dDistR - dDistLR)/2;\r
-       return dDist;\r
-       }\r
-\r
-// This is a mysterious variant of UPGMA reverse-engineered from MAFFT source.\r
-float Clust::ComputeDistMAFFT(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
-       {\r
-       const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
-       const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
-\r
-       const float dDistLR = GetDist(uLeftNodeIndex, uRightNodeIndex);\r
-       const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
-       const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
-       const float dMinDistLR = (dDistL < dDistR ? dDistL : dDistR);\r
-       const float dSumDistLR = dDistL + dDistR;\r
-       const float dDist = dMinDistLR*(1 - g_dSUEFF) + dSumDistLR*g_dSUEFF/2;\r
-       return dDist;\r
-       }\r
-\r
-unsigned Clust::GetClusterCount() const\r
-       {\r
-       return m_uClusterCount;\r
-       }\r
-\r
-void Clust::LogMe() const\r
-       {\r
-       Log("Clust %u leaves, %u nodes, %u clusters.\n",\r
-         m_uLeafCount, m_uNodeCount, m_uClusterCount);\r
-\r
-       Log("Distance matrix\n");\r
-       const unsigned uNodeCount = GetNodeCount();\r
-       Log("       ");\r
-       for (unsigned i = 0; i < uNodeCount - 1; ++i)\r
-               Log(" %7u", i);\r
-       Log("\n");\r
-\r
-       Log("       ");\r
-       for (unsigned i = 0; i < uNodeCount - 1; ++i)\r
-               Log("  ------");\r
-       Log("\n");\r
-\r
-       for (unsigned i = 0; i < uNodeCount - 1; ++i)\r
-               {\r
-               Log("%4u:  ", i);\r
-               for (unsigned j = 0; j < i; ++j)\r
-                       Log(" %7.2g", GetDist(i, j));\r
-               Log("\n");\r
-               }\r
-\r
-       Log("\n");\r
-       Log("Node  Size  Prnt  Left  Rght   Length  Name\n");\r
-       Log("----  ----  ----  ----  ----   ------  ----\n");\r
-       for (unsigned uNodeIndex = 0; uNodeIndex < m_uNodeCount; ++uNodeIndex)\r
-               {\r
-               const ClustNode &Node = m_Nodes[uNodeIndex];\r
-               Log("%4u  %4u", uNodeIndex, Node.m_uSize);\r
-               if (0 != Node.m_ptrParent)\r
-                       Log("  %4u", Node.m_ptrParent->m_uIndex);\r
-               else\r
-                       Log("      ");\r
-\r
-               if (0 != Node.m_ptrLeft)\r
-                       Log("  %4u", Node.m_ptrLeft->m_uIndex);\r
-               else\r
-                       Log("      ");\r
-\r
-               if (0 != Node.m_ptrRight)\r
-                       Log("  %4u", Node.m_ptrRight->m_uIndex);\r
-               else\r
-                       Log("      ");\r
-\r
-               if (uNodeIndex != m_uNodeCount - 1)\r
-                       Log("  %7.3g", Node.m_dLength);\r
-               if (IsLeaf(uNodeIndex))\r
-                       {\r
-                       const char *ptrName = GetNodeName(uNodeIndex);\r
-                       if (0 != ptrName)\r
-                               Log("  %s", ptrName);\r
-                       }\r
-               if (GetRootNodeIndex() == uNodeIndex)\r
-                       Log("    [ROOT]");\r
-               Log("\n");\r
-               }\r
-       }\r
-\r
-const ClustNode &Clust::GetNode(unsigned uNodeIndex) const\r
-       {\r
-       if (uNodeIndex >= m_uNodeCount)\r
-               Quit("ClustNode::GetNode(%u) %u", uNodeIndex, m_uNodeCount);\r
-       return m_Nodes[uNodeIndex];\r
-       }\r
-\r
-bool Clust::IsLeaf(unsigned uNodeIndex) const\r
-       {\r
-       return uNodeIndex < m_uLeafCount;\r
-       }\r
-\r
-unsigned Clust::GetClusterSize(unsigned uNodeIndex) const\r
-       {\r
-       const ClustNode &Node = GetNode(uNodeIndex);\r
-       return Node.m_uSize;\r
-       }\r
-\r
-unsigned Clust::GetLeftIndex(unsigned uNodeIndex) const\r
-       {\r
-       const ClustNode &Node = GetNode(uNodeIndex);\r
-       if (0 == Node.m_ptrLeft)\r
-               Quit("Clust::GetLeftIndex: leaf");\r
-       return Node.m_ptrLeft->m_uIndex;\r
-       }\r
-\r
-unsigned Clust::GetRightIndex(unsigned uNodeIndex) const\r
-       {\r
-       const ClustNode &Node = GetNode(uNodeIndex);\r
-       if (0 == Node.m_ptrRight)\r
-               Quit("Clust::GetRightIndex: leaf");\r
-       return Node.m_ptrRight->m_uIndex;\r
-       }\r
-\r
-float Clust::GetLength(unsigned uNodeIndex) const\r
-       {\r
-       const ClustNode &Node = GetNode(uNodeIndex);\r
-       return Node.m_dLength;\r
-       }\r
-\r
-void Clust::SetLeafCount(unsigned uLeafCount)\r
-       {\r
-       if (uLeafCount <= 1)\r
-               Quit("Clust::SetLeafCount(%u)", uLeafCount);\r
-\r
-       m_uLeafCount = uLeafCount;\r
-       const unsigned uNodeCount = GetNodeCount();\r
-\r
-// Triangular matrix size excluding diagonal (all zeros in our case).\r
-       m_uTriangularMatrixSize = (uNodeCount*(uNodeCount - 1))/2;\r
-       m_dDist = new float[m_uTriangularMatrixSize];\r
-       }\r
-\r
-unsigned Clust::GetLeafCount() const\r
-       {\r
-       return m_uLeafCount;\r
-       }\r
-\r
-unsigned Clust::VectorIndex(unsigned uIndex1, unsigned uIndex2) const\r
-       {\r
-       const unsigned uNodeCount = GetNodeCount();\r
-       if (uIndex1 >= uNodeCount || uIndex2 >= uNodeCount)\r
-               Quit("DistVectorIndex(%u,%u) %u", uIndex1, uIndex2, uNodeCount);\r
-       unsigned v;\r
-       if (uIndex1 >= uIndex2)\r
-               v = uIndex2 + (uIndex1*(uIndex1 - 1))/2;\r
-       else\r
-               v = uIndex1 + (uIndex2*(uIndex2 - 1))/2;\r
-       assert(v < m_uTriangularMatrixSize);\r
-       return v;\r
-       }\r
-\r
-float Clust::GetDist(unsigned uIndex1, unsigned uIndex2) const\r
-       {\r
-       unsigned v = VectorIndex(uIndex1, uIndex2);\r
-       return m_dDist[v];\r
-       }\r
-\r
-void Clust::SetDist(unsigned uIndex1, unsigned uIndex2, float dDist)\r
-       {\r
-       unsigned v = VectorIndex(uIndex1, uIndex2);\r
-       m_dDist[v] = dDist;\r
-       }\r
-\r
-float Clust::GetHeight(unsigned uNodeIndex) const\r
-       {\r
-       if (IsLeaf(uNodeIndex))\r
-               return 0;\r
-\r
-       const unsigned uLeftIndex = GetLeftIndex(uNodeIndex);\r
-       const unsigned uRightIndex = GetRightIndex(uNodeIndex);\r
-       const float dLeftLength = GetLength(uLeftIndex);\r
-       const float dRightLength = GetLength(uRightIndex);\r
-       const float dLeftHeight = dLeftLength + GetHeight(uLeftIndex);\r
-       const float dRightHeight = dRightLength + GetHeight(uRightIndex);\r
-       return (dLeftHeight + dRightHeight)/2;\r
-       }\r
-\r
-const char *Clust::GetNodeName(unsigned uNodeIndex) const\r
-       {\r
-       if (!IsLeaf(uNodeIndex))\r
-               Quit("Clust::GetNodeName, is not leaf");\r
-       return m_ptrSet->GetLeafName(uNodeIndex);\r
-       }\r
-\r
-unsigned Clust::GetNodeId(unsigned uNodeIndex) const\r
-       {\r
-       if (uNodeIndex >= GetLeafCount())\r
-               return 0;\r
-       return m_ptrSet->GetLeafId(uNodeIndex);\r
-       }\r
-\r
-unsigned Clust::GetLeaf(unsigned uNodeIndex, unsigned uLeafIndex) const\r
-       {\r
-       const ClustNode &Node = GetNode(uNodeIndex);\r
-       const unsigned uLeafCount = Node.m_uSize;\r
-       if (uLeafIndex >= uLeafCount)\r
-               Quit("Clust::GetLeaf, invalid index");\r
-       const unsigned uIndex = Node.m_uLeafIndexes[uLeafIndex];\r
-       if (uIndex >= m_uNodeCount)\r
-               Quit("Clust::GetLeaf, index out of range");\r
-       return uIndex;\r
-       }\r
-\r
-unsigned Clust::GetFirstCluster() const\r
-       {\r
-       if (0 == m_ptrClusterList)\r
-               return uInsane;\r
-       return m_ptrClusterList->m_uIndex;\r
-       }\r
-\r
-unsigned Clust::GetNextCluster(unsigned uIndex) const\r
-       {\r
-       ClustNode *ptrNode = &m_Nodes[uIndex];\r
-       if (0 == ptrNode->m_ptrNextCluster)\r
-               return uInsane;\r
-       return ptrNode->m_ptrNextCluster->m_uIndex;\r
-       }\r
-\r
-void Clust::DeleteFromClusterList(unsigned uNodeIndex)\r
-       {\r
-       assert(uNodeIndex < m_uNodeCount);\r
-       ClustNode *ptrNode = &m_Nodes[uNodeIndex];\r
-       ClustNode *ptrPrev = ptrNode->m_ptrPrevCluster;\r
-       ClustNode *ptrNext = ptrNode->m_ptrNextCluster;\r
-\r
-       if (0 != ptrNext)\r
-               ptrNext->m_ptrPrevCluster = ptrPrev;\r
-       if (0 == ptrPrev)\r
-               {\r
-               assert(m_ptrClusterList == ptrNode);\r
-               m_ptrClusterList = ptrNext;\r
-               }\r
-       else\r
-               ptrPrev->m_ptrNextCluster = ptrNext;\r
-\r
-       ptrNode->m_ptrNextCluster = 0;\r
-       ptrNode->m_ptrPrevCluster = 0;\r
-       }\r
-\r
-void Clust::AddToClusterList(unsigned uNodeIndex)\r
-       {\r
-       assert(uNodeIndex < m_uNodeCount);\r
-       ClustNode *ptrNode = &m_Nodes[uNodeIndex];\r
-\r
-       if (0 != m_ptrClusterList)\r
-               m_ptrClusterList->m_ptrPrevCluster = ptrNode;\r
-\r
-       ptrNode->m_ptrNextCluster = m_ptrClusterList;\r
-       ptrNode->m_ptrPrevCluster = 0;\r
-\r
-       m_ptrClusterList = ptrNode;\r
-       }\r
-\r
-float Clust::ComputeMetric(unsigned uIndex1, unsigned uIndex2) const\r
-       {\r
-       switch (m_JoinStyle)\r
-               {\r
-       case JOIN_NearestNeighbor:\r
-               return ComputeMetricNearestNeighbor(uIndex1, uIndex2);\r
-\r
-       case JOIN_NeighborJoining:\r
-               return ComputeMetricNeighborJoining(uIndex1, uIndex2);\r
-               }\r
-       Quit("Clust::ComputeMetric");\r
-       return 0;\r
-       }\r
-\r
-float Clust::ComputeMetricNeighborJoining(unsigned i, unsigned j) const\r
-       {\r
-       float ri = Calc_r(i);\r
-       float rj = Calc_r(j);\r
-       float dij = GetDist(i, j);\r
-       float dMetric = dij - (ri + rj);\r
-       return (float) dMetric;\r
-       }\r
-\r
-float Clust::ComputeMetricNearestNeighbor(unsigned i, unsigned j) const\r
-       {\r
-       return (float) GetDist(i, j);\r
-       }\r
-\r
-float Clust::GetMinMetricBruteForce(unsigned *ptruIndex1, unsigned *ptruIndex2) const\r
-       {\r
-       unsigned uMinLeftNodeIndex = uInsane;\r
-       unsigned uMinRightNodeIndex = uInsane;\r
-       float dMinMetric = PLUS_INFINITY;\r
-       for (unsigned uLeftNodeIndex = GetFirstCluster(); uLeftNodeIndex != uInsane;\r
-         uLeftNodeIndex = GetNextCluster(uLeftNodeIndex))\r
-               {\r
-               for (unsigned uRightNodeIndex = GetNextCluster(uLeftNodeIndex);\r
-                 uRightNodeIndex != uInsane;\r
-                 uRightNodeIndex = GetNextCluster(uRightNodeIndex))\r
-                       {\r
-                       float dMetric = ComputeMetric(uLeftNodeIndex, uRightNodeIndex);\r
-                       if (dMetric < dMinMetric)\r
-                               {\r
-                               dMinMetric = dMetric;\r
-                               uMinLeftNodeIndex = uLeftNodeIndex;\r
-                               uMinRightNodeIndex = uRightNodeIndex;\r
-                               }\r
-                       }\r
-               }\r
-       *ptruIndex1 = uMinLeftNodeIndex;\r
-       *ptruIndex2 = uMinRightNodeIndex;\r
-       return dMinMetric;\r
-       }\r
-\r
-float Clust::GetMinMetric(unsigned *ptruIndex1, unsigned *ptruIndex2) const\r
-       {\r
-       return GetMinMetricBruteForce(ptruIndex1, ptruIndex2);\r
-       }\r