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.

305 lines
6.2 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1998
  6. //
  7. // File: mddist.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // MDDIST.CPP
  12. //
  13. #include <basetsd.h>
  14. #include <iostream>
  15. #include <fstream>
  16. #include "symtmbn.h"
  17. LEAK_VAR_DEF(BNDIST)
  18. static void dumpVimd ( const VIMD & vimd )
  19. {
  20. for ( int i = 0 ; i < vimd.size(); i++ )
  21. {
  22. cout << vimd[i];
  23. if ( i + 1 < vimd.size() )
  24. cout << ",";
  25. }
  26. }
  27. static void dumpVlr ( const VLREAL & vlr )
  28. {
  29. for ( int i = 0 ; i < vlr.size(); i++ )
  30. {
  31. cout << vlr[i];
  32. if ( i + 1 < vlr.size() )
  33. cout << ",";
  34. }
  35. }
  36. static void dumpSlice ( const MDVSLICE & mslice, bool bStrides = true)
  37. {
  38. VIMD vimdLengths = mslice.size();
  39. VIMD vimdStrides = mslice.stride();
  40. size_t iStart = mslice.start();
  41. cout << "\nslice start="
  42. << iStart
  43. << "\tlengths=";
  44. dumpVimd( vimdLengths );
  45. if ( bStrides )
  46. {
  47. cout << "\tstrides=" ;
  48. dumpVimd( vimdStrides );
  49. }
  50. cout << "\ttotlen="
  51. << mslice._Totlen();
  52. }
  53. static void dumpMdv ( DISTDD & mdv, const MDVSLICE * pslice = NULL )
  54. {
  55. if ( pslice == NULL )
  56. pslice = & mdv.Slice();
  57. dumpSlice( *pslice );
  58. DISTDD::Iterator itmd(mdv, *pslice );
  59. while (itmd.BNext())
  60. {
  61. size_t icurr = itmd.ICurr();
  62. cout << "\n";
  63. dumpVimd( itmd.Vitmd() );
  64. REAL & r = itmd.Next();
  65. cout << "\t["
  66. << icurr
  67. << "] = "
  68. << r ;
  69. }
  70. cout << "\n";
  71. }
  72. BNDIST :: BNDIST ()
  73. :_edist(ED_NONE),
  74. _pmvd(NULL),
  75. _pdrmap(NULL)
  76. {
  77. LEAK_VAR_UPD(1)
  78. }
  79. BNDIST :: ~ BNDIST ()
  80. {
  81. Clear();
  82. LEAK_VAR_UPD(-1)
  83. }
  84. void BNDIST :: NoRef ()
  85. {
  86. delete this;
  87. }
  88. BNDIST & BNDIST :: operator = ( const BNDIST & bnd )
  89. {
  90. Clear();
  91. switch ( _edist = bnd._edist )
  92. {
  93. default:
  94. case ED_NONE:
  95. break;
  96. case ED_DENSE:
  97. _pmvd = new DISTDD( bnd.Mvd() );
  98. assert( _pmvd->first.size() == bnd.Mvd().first.size() );
  99. break;
  100. case ED_CI_MAX:
  101. case ED_CI_PLUS:
  102. case ED_SPARSE:
  103. _pdrmap = new DISTMAP( bnd.Distmap() ) ;
  104. assert( _pdrmap->size() == bnd.Distmap().size() );
  105. break;
  106. }
  107. return self;
  108. }
  109. BNDIST :: BNDIST ( const BNDIST & bnd )
  110. :_edist(ED_NONE),
  111. _pmvd(NULL),
  112. _pdrmap(NULL)
  113. {
  114. (*this) = bnd;
  115. LEAK_VAR_UPD(1)
  116. }
  117. bool BNDIST :: BChangeSubtype ( EDIST edist )
  118. {
  119. if ( BDenseType(edist) ^ BDense() )
  120. return false;
  121. _edist = edist;
  122. return true;
  123. }
  124. void BNDIST :: Dump ()
  125. {
  126. if ( _pmvd )
  127. {
  128. cout << "\n\tDense version:";
  129. DumpDense();
  130. }
  131. if ( _pdrmap )
  132. {
  133. cout << "\n\tSparse version:";
  134. DumpSparse();
  135. }
  136. cout << "\n\n";
  137. }
  138. void BNDIST :: DumpSparse ()
  139. {
  140. assert( _pdrmap );
  141. DISTMAP & dmap = *_pdrmap;
  142. int i = 0;
  143. for ( DISTMAP::iterator itdm = dmap.begin();
  144. itdm != dmap.end();
  145. ++itdm, ++i )
  146. {
  147. const VIMD & vimd = (*itdm).first;
  148. const VLREAL & vlr = (*itdm).second;
  149. cout << "\n["
  150. << i
  151. << "] (";
  152. dumpVimd(vimd);
  153. cout << ")\t";
  154. dumpVlr(vlr);
  155. }
  156. }
  157. void BNDIST :: DumpDense ()
  158. {
  159. assert( _pmvd );
  160. dumpMdv( *_pmvd );
  161. }
  162. void BNDIST :: ConvertToDense ( const VIMD & vimd )
  163. {
  164. assert( _edist == ED_NONE || _edist == ED_SPARSE );
  165. if ( _edist == ED_NONE )
  166. {
  167. assert( ! _pdrmap );
  168. return;
  169. }
  170. // See if there is a sparse distribution to convert
  171. if ( ! _pdrmap )
  172. throw GMException( EC_DIST_MISUSE, "no prior sparse distribution to convert" );
  173. int cParent = vimd.size() - 1;
  174. int cState = vimd[cParent];
  175. DISTMAP & dmap = *_pdrmap;
  176. VIMD vimdMt; // Empty subscript array
  177. VLREAL vlrDefault(cState); // Default value array
  178. // First, try to find the default entry; use -1 if not found
  179. DISTMAP::iterator itdm = dmap.find(vimdMt);
  180. if ( itdm != dmap.end() )
  181. vlrDefault = (*itdm).second;
  182. else
  183. vlrDefault = -1; // fill the array with -1.
  184. assert( vlrDefault.size() == cState );
  185. // Allocate the new dense m-d array
  186. delete _pmvd;
  187. _pmvd = new DISTDD( vimd );
  188. DISTDD & mdv = *_pmvd;
  189. // Fill each DPI with the appropriate default value
  190. DISTDD::Iterator itmdv(mdv);
  191. for ( int iState = 0; itmdv.BNext() ; iState++ )
  192. {
  193. itmdv.Next() = vlrDefault[ iState % cState ];
  194. }
  195. //
  196. // Now, iterate over the sparse array and store in the appropriate locations.
  197. // Each entry in the sparse map is a complete state set for the target node.
  198. // Since the child (target) node probabilities are the fastest varying subscript,
  199. // each entry in sparse map is spread across "cState" entries in the dense map.
  200. //
  201. // Of course, this could be more efficient, but we're just testing for now.
  202. //
  203. VIMD vimdDense(vimd.size());
  204. for ( itdm = dmap.begin(); itdm != dmap.end() ; ++itdm )
  205. {
  206. const VIMD & vimdSub = (*itdm).first;
  207. VLREAL & vlrNext = (*itdm).second;
  208. for ( int ip = 0 ; ip < cParent; ip++ )
  209. {
  210. vimdDense[ip] = vimdSub[ip];
  211. }
  212. for ( int ist = 0 ; ist < cState; ++ist )
  213. {
  214. vimdDense[cParent] = ist;
  215. mdv[vimdDense] = vlrNext[ist];
  216. }
  217. }
  218. // Finally, nuke the old sparse distribution
  219. delete _pdrmap;
  220. _pdrmap = NULL;
  221. // Set distribution type
  222. _edist = ED_DENSE;
  223. }
  224. // Set distribution to "dense"
  225. void BNDIST :: SetDense ( const VIMD & vimd )
  226. {
  227. Clear();
  228. _vimdDim = vimd;
  229. _pmvd = new DISTDD( vimd );
  230. _edist = ED_DENSE;
  231. }
  232. // Set distribution to sparse
  233. void BNDIST :: SetSparse ( const VIMD & vimd )
  234. {
  235. Clear();
  236. _vimdDim = vimd;
  237. _pdrmap = new DISTMAP;
  238. _edist = ED_SPARSE;
  239. }
  240. // Return the "leak" or "default" vector from a sparse distribution
  241. VLREAL * BNDIST :: PVlrLeak ()
  242. {
  243. assert( BSparse() );
  244. const DISTMAP & dmap = Distmap();
  245. const VIMD & vimdDim = VimdDim();
  246. VIMD vimdLeak;
  247. // First try to find the dimensionless "default" vector.
  248. VLREAL * pvlrDefault = NULL;
  249. DISTMAP::iterator itdm = dmap.find( vimdLeak );
  250. if ( itdm != dmap.end() )
  251. pvlrDefault = & (*itdm).second;
  252. // Now try to find a specific zeroth vector; note that valarray<T>::resize
  253. // stores all zeroes into the valarray by default. Also, skip the
  254. // loweest dimension, since that's the size of each vector in the
  255. // sparse map.
  256. vimdLeak.resize( vimdDim.size() - 1 );
  257. VLREAL * pvlrLeak = NULL;
  258. itdm = dmap.find( vimdLeak );
  259. if ( itdm != dmap.end() )
  260. pvlrLeak = & (*itdm).second;
  261. return pvlrLeak
  262. ? pvlrLeak
  263. : pvlrDefault;
  264. }
  265. void BNDIST :: Clone ( const BNDIST & bndist )
  266. {
  267. ASSERT_THROW( _edist == ED_NONE,
  268. EC_INVALID_CLONE,
  269. "cannot clone into non-empty structure" );
  270. self = bndist;
  271. }