Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
5.7 KiB

  1. #include <stdlib.h>
  2. #include "viterbi.h"
  3. #include <float.h>
  4. CPtrArray::CPtrArray()
  5. {
  6. m_iSize=0;
  7. m_rgpv=NULL;
  8. m_iTop=0;
  9. m_iGrow=10;
  10. }
  11. CPtrArray::~CPtrArray()
  12. {
  13. if (m_rgpv)
  14. free (m_rgpv);
  15. }
  16. void CPtrArray::SetSize(int iSize, int iGrowSize)
  17. {
  18. if (iSize > m_iSize)
  19. {
  20. m_rgpv = (void **)realloc (m_rgpv, iSize*sizeof(void *));
  21. m_iSize = iSize;
  22. }
  23. if (0 < iGrowSize)
  24. m_iGrow = iGrowSize;
  25. else
  26. m_iGrow = 10;
  27. }
  28. int CPtrArray::Add(void *pElem)
  29. {
  30. if (m_iTop >= m_iSize)
  31. {
  32. m_iSize += m_iGrow;
  33. m_rgpv = (void **)realloc (m_rgpv, m_iSize*sizeof(void *));
  34. }
  35. m_rgpv[m_iTop] = pElem;
  36. return (m_iTop++);
  37. }
  38. /*
  39. void *CPtrArray::Get(int iElem)
  40. {
  41. if ((iElem >= m_iTop) || (iElem < 0))
  42. return NULL;
  43. return m_rgpv[iElem];
  44. }
  45. */
  46. /*
  47. __inline int CPtrArray::GetSize()
  48. {
  49. return m_iSize;
  50. }
  51. */
  52. CViterbi::CViterbi ()
  53. {
  54. m_fPruneLevel = 0.f;
  55. m_pConcatCostFunction = NULL;
  56. m_pUnitCostFunction = NULL;
  57. m_rgpBestElems = NULL;
  58. m_rgpElemArray = NULL;
  59. m_iLen = 0;
  60. }
  61. CViterbi::~CViterbi ()
  62. {
  63. int i;
  64. for (i=0; i < m_iLen; i++)
  65. delete m_rgpElemArray[i];
  66. if (m_rgpElemArray)
  67. free (m_rgpElemArray);
  68. if (m_rgpBestElems)
  69. free (m_rgpBestElems);
  70. }
  71. int CViterbi::Init (int iLen, int iInitialDepth, int iGrowSize)
  72. {
  73. int i;
  74. m_iLen = iLen;
  75. if (NULL == (m_rgpElemArray = (CPtrArray **)malloc (sizeof (CPtrArray*)*m_iLen)))
  76. return -1;
  77. for (i=0; i < m_iLen; i++)
  78. {
  79. m_rgpElemArray[i] = new CPtrArray;
  80. if (NULL == m_rgpElemArray[i])
  81. {
  82. m_iLen = i;
  83. return -1;
  84. }
  85. m_rgpElemArray[i]->SetSize (iInitialDepth, iGrowSize);
  86. }
  87. return 0;
  88. }
  89. int CViterbi::Add (int iPos, void *pElem)
  90. {
  91. if ((iPos > m_iLen) || (iPos < 0))
  92. return -1;
  93. m_rgpElemArray[iPos]->Add(pElem);
  94. return 0;
  95. }
  96. int CViterbi::FindBestPath(ConcatCostFn pConcatCostFunction, UnitCostFn pUnitCostFunction, float *pfCost)
  97. {
  98. if (pConcatCostFunction)
  99. m_pConcatCostFunction = pConcatCostFunction;
  100. if (pUnitCostFunction)
  101. m_pUnitCostFunction = pUnitCostFunction;
  102. float **rgrgfCosts=NULL, *rgfBuf=NULL;
  103. int **rgrgiBestLeft=NULL, *rgiBuf=NULL;
  104. int iMaxLen, iLLen, iRLen, iTotalLen, iPos, iLElem, iRElem, iBestElem, iTempLen;
  105. float fCost, fUnitCost;
  106. int iRet=-1;
  107. iMaxLen = m_rgpElemArray[0]->GetUsed();
  108. iRLen = iMaxLen;
  109. if (0 == iMaxLen)
  110. iMaxLen=1;
  111. iTotalLen = iMaxLen;
  112. for (iPos=1; iPos < m_iLen; iPos++)
  113. {
  114. iTempLen = m_rgpElemArray[iPos]->GetUsed();
  115. if (0 == iTempLen)
  116. iTempLen=1;
  117. if (iTempLen > iMaxLen)
  118. iMaxLen = iTempLen;
  119. iTotalLen += iTempLen;
  120. }
  121. rgfBuf = (float *)calloc (iTotalLen, sizeof (float));
  122. rgiBuf = (int *)calloc (iTotalLen, sizeof(int));
  123. iTotalLen=0;
  124. rgrgfCosts = (float **)malloc (m_iLen * sizeof (float*));
  125. rgrgiBestLeft = (int **)malloc (sizeof (int)*m_iLen);
  126. if ((NULL == rgrgfCosts) || (NULL == rgfBuf) || (NULL == rgrgiBestLeft) || (NULL == rgiBuf))
  127. goto Err;
  128. rgrgfCosts[0] = rgfBuf+iTotalLen;
  129. rgrgiBestLeft[0] = rgiBuf+iTotalLen;
  130. if (0 == iRLen)
  131. iTotalLen++;
  132. else
  133. iTotalLen += iRLen;
  134. for (iLElem=0; iLElem < iRLen; iLElem++)
  135. if (NULL != (*m_rgpElemArray[0])[iLElem])
  136. rgrgfCosts[0][iLElem] = m_pUnitCostFunction((*m_rgpElemArray[0])[iLElem],0);
  137. for (iPos=1; iPos < m_iLen; iPos++)
  138. {
  139. iLLen = iRLen;
  140. iRLen = m_rgpElemArray[iPos]->GetUsed();
  141. rgrgfCosts[iPos] = rgfBuf+iTotalLen;
  142. rgrgiBestLeft[iPos] = rgiBuf+iTotalLen;
  143. if (0 == iRLen)
  144. iTotalLen++;
  145. else
  146. iTotalLen += iRLen;
  147. for (iRElem=0; iRElem < iRLen; iRElem++)
  148. {
  149. rgrgfCosts[iPos][iRElem] = FLT_MAX; // much bigger than any potential cost.
  150. fUnitCost = m_pUnitCostFunction((*m_rgpElemArray[iPos])[iRElem],iPos);
  151. for (iLElem=0; iLElem < iLLen; iLElem++)
  152. {
  153. if (NULL != (*m_rgpElemArray[iPos-1])[iLElem])
  154. {
  155. fCost = m_pConcatCostFunction((*m_rgpElemArray[iPos-1])[iLElem],
  156. (*m_rgpElemArray[iPos])[iRElem], fUnitCost) +
  157. rgrgfCosts[iPos-1][iLElem];// + fUnitCost;
  158. if (fCost <= rgrgfCosts[iPos][iRElem])
  159. {
  160. rgrgfCosts[iPos][iRElem] = fCost;
  161. rgrgiBestLeft[iPos][iRElem] = iLElem;
  162. }
  163. }
  164. // else it was pruned earlier
  165. }
  166. if ((0.f != m_fPruneLevel) && (rgrgfCosts[iPos][iRElem] > m_fPruneLevel))
  167. (*m_rgpElemArray[iPos])[iRElem] = NULL;
  168. }
  169. }
  170. *pfCost = 0.f;
  171. fCost = rgrgfCosts[m_iLen-1][0];
  172. iBestElem = 0;
  173. for (iRElem=1; iRElem < iRLen; iRElem++)
  174. if (rgrgfCosts[m_iLen-1][iRElem] < fCost)
  175. {
  176. iBestElem = iRElem;
  177. fCost = rgrgfCosts[m_iLen-1][iRElem];
  178. }
  179. m_rgpBestElems = (void **)calloc (m_iLen, sizeof (void *));
  180. if (NULL == m_rgpBestElems)
  181. goto Err;
  182. if (iBestElem >= m_rgpElemArray[m_iLen-1]->GetUsed())
  183. m_rgpBestElems[m_iLen-1] = NULL;
  184. else
  185. {
  186. m_rgpBestElems[m_iLen-1] = (*m_rgpElemArray[m_iLen-1])[iBestElem];
  187. *pfCost = fCost;
  188. }
  189. for (iPos=m_iLen-2; iPos >= 0; iPos--)
  190. {
  191. if (0 == m_rgpElemArray[iPos+1]->GetUsed())
  192. {
  193. iRLen = m_rgpElemArray[iPos]->GetUsed();
  194. fCost = rgrgfCosts[iPos][0];
  195. for (iRElem=1; iRElem < iRLen; iRElem++)
  196. if (rgrgfCosts[iPos][iRElem] < fCost)
  197. {
  198. iBestElem = iRElem;
  199. fCost = rgrgfCosts[iPos][iRElem];
  200. }
  201. }
  202. else
  203. iBestElem = rgrgiBestLeft[iPos+1][iBestElem];
  204. if (iBestElem >= m_rgpElemArray[iPos]->GetUsed())
  205. m_rgpBestElems[iPos] = NULL;
  206. else
  207. {
  208. m_rgpBestElems[iPos] = (*m_rgpElemArray[iPos])[iBestElem];
  209. if (0 == *pfCost)
  210. *pfCost = fCost;
  211. }
  212. }
  213. iRet = 0;
  214. Err:
  215. if (rgrgfCosts)
  216. free (rgrgfCosts);
  217. if (rgfBuf)
  218. free (rgfBuf);
  219. if (rgrgiBestLeft)
  220. free (rgrgiBestLeft);
  221. if (rgiBuf)
  222. free (rgiBuf);
  223. return iRet;
  224. }