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.

392 lines
9.2 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1998
  6. //
  7. // File: margiter.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // margiter.cpp: compiled marginals iterators
  12. //
  13. #include <basetsd.h>
  14. #include <math.h>
  15. #include "basics.h"
  16. #include "gmobj.h"
  17. #include "marginals.h"
  18. #include "margiter.h"
  19. #include "algos.h"
  20. #include "parmio.h"
  21. LEAK_VAR_DEF(VMARGSUB)
  22. LEAK_VAR_DEF(MARGSUBREF)
  23. //
  24. // Construct a VMARGSUB from a marginals iterator
  25. //
  26. VMARGSUB :: VMARGSUB ( MARGINALS::Iterator & itMarg )
  27. : _iSearchPass(0)
  28. {
  29. itMarg.Reset();
  30. resize( itMarg.IEnd() );
  31. for ( int i = 0; itMarg.BNext() ; i++)
  32. {
  33. int ix = itMarg.IndxUpd();
  34. self[i] = ix;
  35. }
  36. LEAK_VAR_UPD(1)
  37. }
  38. VMARGSUB :: ~ VMARGSUB ()
  39. {
  40. LEAK_VAR_UPD(-1)
  41. }
  42. void VMARGSUB :: NoRef ()
  43. {
  44. delete this;
  45. }
  46. MARGSUBREF :: MARGSUBREF ( VMARGSUB * pvmsub, int cSize )
  47. : _pvmsub( NULL ),
  48. _cSize( -1 )
  49. {
  50. SetVmsub( pvmsub, cSize );
  51. LEAK_VAR_UPD(1)
  52. }
  53. MARGSUBREF :: MARGSUBREF ( const MARGSUBREF & msubr )
  54. : _pvmsub( NULL ),
  55. _cSize( -1 )
  56. {
  57. self = msubr;
  58. LEAK_VAR_UPD(1)
  59. }
  60. MARGSUBREF & MARGSUBREF :: operator = ( const MARGSUBREF & msubr )
  61. {
  62. SetVmsub( msubr._pvmsub, msubr.CSize() );
  63. return self;
  64. }
  65. void MARGSUBREF :: SetVmsub ( VMARGSUB * pvmsub, int cSize )
  66. {
  67. if ( _pvmsub )
  68. {
  69. _pvmsub->Unbind();
  70. _pvmsub = NULL;
  71. }
  72. if ( pvmsub )
  73. {
  74. _cSize = cSize > 0 ? cSize : pvmsub->size();
  75. pvmsub->Bind();
  76. _pvmsub = pvmsub;
  77. }
  78. else
  79. {
  80. _cSize = 0;
  81. }
  82. }
  83. MARGSUBREF :: ~ MARGSUBREF ()
  84. {
  85. SetVmsub( NULL );
  86. LEAK_VAR_UPD(-1)
  87. }
  88. bool MARGSUBREF :: operator == ( const MARGSUBREF & msr ) const
  89. {
  90. return _pvmsub == msr._pvmsub && _cSize == msr._cSize;
  91. }
  92. bool MARGSUBREF :: operator != ( const MARGSUBREF & msr ) const
  93. {
  94. return !(self == msr);
  95. }
  96. LTMARGSUBREF :: LTMARGSUBREF ()
  97. : _iSearchPass(0),
  98. _cArrays(0),
  99. _cArrayTotalSize(0),
  100. _cSubRefs(0)
  101. {
  102. }
  103. void LTMARGSUBREF :: Dump ()
  104. {
  105. #ifdef DUMP
  106. cout << "\n\nLTMARGSUBREF::~ LTMARGSUBREF: "
  107. << "\n\tTotal search passes to create marginals iterators = "
  108. << _iSearchPass
  109. << "\n\tTotal arrays = "
  110. << _cArrays
  111. << "\n\tTotal array size = "
  112. << _cArrayTotalSize
  113. << "\n\tTotal marg iterator references = "
  114. << _cSubRefs
  115. ;
  116. cout.flush();
  117. #endif
  118. }
  119. // Iterate over the list looking for a match
  120. MARGSUBREF * LTMARGSUBREF :: PmsubrAdd ( MARGINALS::Iterator & itMarg )
  121. {
  122. // Bump the search pass
  123. _iSearchPass++;
  124. // Get the minimum number of elements
  125. int cMin = itMarg.IEnd();
  126. MARGSUBREF * pmsubrBest = NULL;
  127. MARGSUBREF * pmsubrNew = NULL;
  128. // Search the list for the longest matching subscript array
  129. // in the pool.
  130. for ( LTMSUBR::iterator itlt = _ltmsubr.begin();
  131. itlt != _ltmsubr.end();
  132. itlt++ )
  133. {
  134. MARGSUBREF & msubr = (*itlt);
  135. VMARGSUB & vmsub = msubr.Vmsub();
  136. if ( vmsub.ISearchPass() == _iSearchPass )
  137. continue; // We've already looked at this one
  138. // Mark this VMARGSUB as having been checked in this pass
  139. vmsub.ISearchPass() = _iSearchPass;
  140. // Prepare to search it
  141. itMarg.Reset();
  142. for ( int i = 0; itMarg.BNext() && i < vmsub.size() ; i++ )
  143. {
  144. int ia = vmsub[i];
  145. int ib = itMarg.IndxUpd();
  146. if ( ia != ib )
  147. break;
  148. }
  149. // If we made it to the end of the array, we found one.
  150. if ( i != cMin )
  151. continue; // Mismatch somewhere
  152. // See if it's the best (longest) found so far
  153. if ( pmsubrBest == NULL )
  154. {
  155. pmsubrBest = & msubr;
  156. }
  157. else
  158. if ( pmsubrBest->Vmsub().size() < vmsub.size()
  159. || ( pmsubrBest->Vmsub().size() == vmsub.size()
  160. && pmsubrBest->CSize() == cMin ) )
  161. {
  162. pmsubrBest = & msubr;
  163. }
  164. }
  165. // If "pmsubrBest" != NULL, we found at least one matching array.
  166. // Now see if we can find an exact match: a MARGSUBREF which has
  167. // the same base array and the same length as what we want.
  168. if ( pmsubrBest )
  169. {
  170. // If the "best" one doesn't match our size, find one that does
  171. if ( pmsubrBest->CSize() != cMin )
  172. {
  173. for ( itlt = _ltmsubr.begin();
  174. itlt != _ltmsubr.end();
  175. itlt++ )
  176. {
  177. MARGSUBREF & msubr = (*itlt);
  178. if ( msubr.Pvmsub() == pmsubrBest->Pvmsub()
  179. && msubr.CSize() == cMin )
  180. {
  181. pmsubrBest = & msubr;
  182. break;
  183. }
  184. }
  185. }
  186. // See if now have and exact match
  187. if ( pmsubrBest->CSize() == cMin )
  188. {
  189. // Exact match: best array and same length
  190. pmsubrNew = pmsubrBest;
  191. }
  192. else
  193. {
  194. // Well, we know which array to use, but we have
  195. // to create a new MARGSUBREF for it
  196. _ltmsubr.push_back( MARGSUBREF( pmsubrBest->Pvmsub(), cMin ) );
  197. pmsubrNew = & _ltmsubr.back();
  198. _cSubRefs++;
  199. }
  200. }
  201. else
  202. {
  203. // There does NOT appear to be a viable array in the ensemble,
  204. // so we have to create a new one and a MARGSUBREF for it.
  205. VMARGSUB * pvmsub = new VMARGSUB( itMarg );
  206. _cArrays++;
  207. _cArrayTotalSize += cMin;
  208. _ltmsubr.push_back( MARGSUBREF( pvmsub, cMin ) );
  209. pmsubrNew = & _ltmsubr.back();
  210. _cSubRefs++;
  211. // At this point we have a new array which may be a superset of
  212. // some other array already in the pool. Walk through the list
  213. // of MARGSUBREFs and change any references whose base arrays
  214. // are subsets of this new one to point to the new array.
  215. // Bump the search pass
  216. _iSearchPass++;
  217. for ( itlt = _ltmsubr.begin();
  218. itlt != _ltmsubr.end();
  219. itlt++ )
  220. {
  221. MARGSUBREF & msubr = (*itlt);
  222. if ( & msubr == pmsubrNew )
  223. continue;
  224. VMARGSUB & vmsub = msubr.Vmsub();
  225. if ( vmsub.ISearchPass() == _iSearchPass )
  226. continue; // We've already looked at this one
  227. // Mark this VMARGSUB as having been checked in this pass
  228. vmsub.ISearchPass() = _iSearchPass;
  229. if ( & vmsub == pvmsub || vmsub.size() > pvmsub->size() )
  230. continue; // Old array is larger; not a subset
  231. // See if the old array is a subset
  232. for ( int i = 0; i < vmsub.size(); i++ )
  233. {
  234. int ia = vmsub[i];
  235. int ib = (*pvmsub)[i];
  236. if ( ia != ib )
  237. break;
  238. }
  239. if ( i == vmsub.size() )
  240. {
  241. assert( vmsub.size() != pvmsub->size() );
  242. // The subset is identical. Change all refs that point to it.
  243. VMARGSUB * pvmsubDefunct = msubr.Pvmsub();
  244. for ( LTMSUBR::iterator itlt2 = _ltmsubr.begin();
  245. itlt2 != _ltmsubr.end();
  246. itlt2++ )
  247. {
  248. MARGSUBREF & msubr2 = (*itlt2);
  249. if ( msubr2.Pvmsub() == pvmsubDefunct )
  250. {
  251. // If the array is about to disappear, do the bookkeepping
  252. if ( pvmsubDefunct->CRef() <= 1 )
  253. {
  254. _cArrays--;
  255. _cArrayTotalSize -= pvmsubDefunct->size();
  256. }
  257. // Convert this reference to a reference to our new array
  258. msubr2.SetVmsub( pvmsub, msubr2.CSize() );
  259. }
  260. }
  261. }
  262. }
  263. }
  264. pmsubrNew->Bind();
  265. return pmsubrNew;
  266. }
  267. void LTMARGSUBREF :: Release ( MARGSUBREF * pmsubr )
  268. {
  269. if ( pmsubr == NULL )
  270. return;
  271. pmsubr->Unbind();
  272. if ( pmsubr->CRef() > 0 )
  273. return;
  274. LTMSUBR::iterator itlt = find( _ltmsubr.begin(), _ltmsubr.end(), *pmsubr );
  275. assert( itlt != _ltmsubr.end() );
  276. _cSubRefs--;
  277. MARGSUBREF & msubr = (*itlt);
  278. if ( msubr.Vmsub().CRef() <= 1 )
  279. {
  280. _cArrays--;
  281. _cArrayTotalSize -= msubr.Vmsub().size();
  282. }
  283. _ltmsubr.erase(itlt);
  284. }
  285. // The global subscript array reference list
  286. LTMARGSUBREF MARGSUBITER :: _ltmargsubr;
  287. MARGSUBITER :: MARGSUBITER ()
  288. :_pmsubr( NULL ),
  289. _pmargSelf( NULL )
  290. {
  291. }
  292. MARGSUBITER :: ~ MARGSUBITER ()
  293. {
  294. _ltmargsubr.Release( _pmsubr );
  295. }
  296. void MARGSUBITER :: Build ( MARGINALS & margSelf, MARGINALS & margSubset )
  297. {
  298. assert( margSelf.size() >= margSubset.size() );
  299. assert( _pmsubr == NULL && _pmargSelf == NULL );
  300. _pmargSelf = & margSelf;
  301. // Build the pseudo-dimension descriptor.
  302. VSIMD vsimdMarg = margSelf.VsimdSubset( margSubset.Vpgnd() );
  303. // Construct the slice which governs the missing dimensions
  304. MDVSLICE mdvs( vsimdMarg );
  305. MARGINALS::Iterator itSubset( margSubset, mdvs );
  306. // Find or construct a MARGSUBITER to match
  307. _pmsubr = _ltmargsubr.PmsubrAdd( itSubset );
  308. }
  309. // Build the iterator for a clique and a node
  310. void MARGSUBITER :: Build ( MARGINALS & margSelf, GNODEMBND * pgndd )
  311. {
  312. assert( _pmsubr == NULL && _pmargSelf == NULL );
  313. _pmargSelf = & margSelf;
  314. // Construct a dummy marginalization target
  315. MDVCPD distd;
  316. MARGINALS::ResizeDistribution( pgndd, distd );
  317. // Get the pseudo-dimension descriptor for this node
  318. VSIMD vsimdMarg = margSelf.VsimdFromNode( pgndd );
  319. // Construct the slice which governs the missing dimensions
  320. MDVSLICE mdvs( vsimdMarg );
  321. MARGINALS::Iterator itSelf( margSelf );
  322. MARGINALS::Iterator itSubset( distd, mdvs );
  323. // Find or construct a MARGSUBITER to match
  324. _pmsubr = _ltmargsubr.PmsubrAdd( itSubset );
  325. }
  326. // Verify subscripts
  327. void MARGSUBITER :: Test ( MARGINALS & margSubset )
  328. {
  329. assert( _pmsubr && _pmargSelf );
  330. assert( _pmargSelf->size() > margSubset.size() );
  331. // Build the pseudo-dimension descriptor.
  332. VSIMD vsimdMarg = _pmargSelf->VsimdSubset( margSubset.Vpgnd() );
  333. // Construct the slice which governs the missing dimensions
  334. MDVSLICE mdvs( vsimdMarg );
  335. MARGINALS::Iterator itSubset( margSubset, mdvs );
  336. MARGINALS::Iterator itSelf( *_pmargSelf );
  337. int isub = 0;
  338. VINT & vintSub = _pmsubr->VintSub();
  339. int cEnd = _pmsubr->CSize();
  340. for ( int iself = 0; itSelf.BNext(); iself++ )
  341. {
  342. int isubSelf = itSelf.IndxUpd();
  343. int isubSubset = itSubset.IndxUpd();
  344. assert( isubSelf == iself );
  345. int isubTest = vintSub[iself];
  346. assert( isubTest == isubSubset && iself < cEnd );
  347. }
  348. }