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.

528 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1998
  6. //
  7. // File: mdvect.h
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // mdvect.h: multi-dimensional array handling
  12. //
  13. #ifndef _MDVECT_H_
  14. #define _MDVECT_H_
  15. /*
  16. Multidimensional array classes and templates.
  17. Each array carries the dimensionality of each dimension as a short integer;
  18. the signed value is reinterpreted for projections and redimensioning.
  19. Note that giving a subscript array (VIMD) whose length is less than the
  20. dimensionality of the target array produces a subscript with lower dimensions
  21. assumed to be equal to zero. This is useful for indexing to lowest-dimensioned
  22. rows for probability tables.
  23. Types used (see basics.h):
  24. REAL is a double
  25. VLREAL is valarray<REAL>
  26. IMD is an unsigned index into a multi-dimensional array
  27. VIMD is a vector of IMD
  28. SIMD is a signed index into a multi-dimensional array;
  29. it's used for projecting dimensions out
  30. VSIMD is a vector of SIMD
  31. An MDVSLICE is dimensionality and iteration information for an m-d vector or maxtrix.
  32. The template TMDVDENSE defines a generic multi-dimensional array which a pair of
  33. elements:
  34. 'first' is a flat (1-d) valarray of an unspecified type (e.g., REAL)
  35. 'second' is an MDVSLICE describing its dimensionality
  36. The nested class TMDVDENSE::Iterator (note the capital 'I') is the smart iterator
  37. for classes derived from TMDVDENSE<>.
  38. */
  39. #include <stdarg.h>
  40. #include "algos.h"
  41. typedef valarray<REAL> VLREAL;
  42. // 'valarray' comparison templates
  43. template<class _V>
  44. struct lessv : binary_function<_V, _V, bool>
  45. {
  46. bool operator()(const _V & vra, const _V & vrb) const
  47. {
  48. int cmin = _cpp_min( vra.size(), vrb.size() );
  49. for ( int i = 0 ; i < cmin ; i++ )
  50. {
  51. if ( vra[i] < vrb[i] )
  52. return true;
  53. if ( vra[i] > vrb[i] )
  54. return false;
  55. }
  56. return vra.size() < vrb.size();
  57. }
  58. };
  59. /////////////////////////////////////////////////////////////////////////////////
  60. // Class MDVSLICE:
  61. // Similar to 'gslice'. Has gslice converter (see 'valarray' header).
  62. // Contains integer array of lengths, array of strides
  63. // and starting point.
  64. /////////////////////////////////////////////////////////////////////////////////
  65. class MDVSLICE
  66. {
  67. public:
  68. // Construct a slice from complete data (like gslice)
  69. MDVSLICE ( size_t _S,
  70. const VIMD & _L,
  71. const VIMD & _D)
  72. : _Start(_S),
  73. _Len(_L),
  74. _Stride(_D)
  75. {}
  76. // Construct a slice given only the dimensions
  77. MDVSLICE ( const VIMD & _L, size_t _S = 0 )
  78. {
  79. Init( _L, _S );
  80. }
  81. MDVSLICE ( int cdim, int ibound, ... )
  82. : _Start(0)
  83. {
  84. va_list vl;
  85. va_start( vl, cdim );
  86. Init( cdim, vl );
  87. }
  88. MDVSLICE ( const VSIMD & vsimd, size_t _S = 0 )
  89. {
  90. Init( vsimd, _S );
  91. }
  92. bool operator == ( const MDVSLICE & sl ) const
  93. {
  94. return _Start == sl._Start
  95. && vequal(_Len,sl._Len)
  96. && vequal(_Stride,sl._Stride);
  97. }
  98. bool operator != ( const MDVSLICE & sl ) const
  99. {
  100. return !(*this == sl);
  101. }
  102. // Provided for compatibility with gslice
  103. MDVSLICE()
  104. : _Start(0) {}
  105. // Return an equivalent gslice for use with other 'valarray' operations
  106. gslice Gslice () const;
  107. void Init ( const VIMD & _L, size_t _S = 0 )
  108. {
  109. _Start = _S;
  110. _Len = _L;
  111. StrideFromLength();
  112. }
  113. void Init ( const VSIMD & vsimd, size_t _S = 0 )
  114. {
  115. int cd = vsimd.size();
  116. vbool vboolMissing(cd);
  117. _Len.resize(cd);
  118. _Start = _S;
  119. for ( int i = 0; i < cd; i++ )
  120. {
  121. SIMD simd = vsimd[i];
  122. if ( vboolMissing[i] = simd < 0 )
  123. _Len[i] = - simd;
  124. else
  125. _Len[i] = simd;
  126. }
  127. StrideFromLength( & vboolMissing );
  128. }
  129. void Init ( int cdim, ... )
  130. {
  131. va_list vl;
  132. va_start( vl, cdim );
  133. Init( cdim, vl );
  134. }
  135. void Init ( int cdim, va_list & vl )
  136. {
  137. _Len.resize(cdim);
  138. for ( int idim = 0; idim < cdim; idim++ )
  139. {
  140. _Len[idim] = va_arg(vl,int);
  141. }
  142. StrideFromLength();
  143. }
  144. /********************************************************
  145. * Accessors to internal data
  146. *********************************************************/
  147. size_t start() const
  148. {return _Start; }
  149. const VIMD & size() const
  150. {return _Len; }
  151. const VIMD & stride() const
  152. {return _Stride; }
  153. // Return the number of dimensions
  154. size_t _Nslice() const
  155. { return _Len.size(); }
  156. // Return the total number of elements according to this slice
  157. size_t _Totlen() const
  158. {
  159. size_t _L = _Len.size() > 0;
  160. if ( _L )
  161. {
  162. for (size_t _I = 0; _I < _Len.size(); ++_I )
  163. {
  164. if ( _Len[_I] )
  165. _L *= _Len[_I];
  166. }
  167. }
  168. return _L;
  169. }
  170. /********************************************************
  171. * Subscript handling. There are two levels, one leaves
  172. * the subscript array unchanged, the other updates it.
  173. * There is a set of overloads for these which allow
  174. * reordering of dimensions.
  175. *********************************************************/
  176. // Return the index offset based upon the subscript array given
  177. size_t _IOff ( const VIMD& _Idx ) const
  178. {
  179. size_t _K = _Start;
  180. for (size_t _I = 0; _I < _Idx.size(); ++_I)
  181. _K += _Idx[_I] * _Stride[_I];
  182. return _K;
  183. }
  184. // Return the index offset based upon the varargs array given
  185. size_t _IOff ( int i, ... ) const
  186. {
  187. va_list vl;
  188. va_start( vl, i );
  189. return _IOff( i, vl );
  190. }
  191. size_t _IOff ( int i, va_list & vl ) const
  192. {
  193. size_t ioff = _Start;
  194. int j;
  195. for ( j = 0; j < _Len.size() && i >= 0 ; ++j )
  196. {
  197. ioff += i * _Stride[j];
  198. i = va_arg(vl,int);
  199. }
  200. return j == _Len.size() ? ioff : -1;
  201. }
  202. // Bump the subscript array to its next valid index
  203. void _Upd (VIMD & _Idx) const
  204. {
  205. for (size_t _I = _Len.size(); 0 < _I--;)
  206. {
  207. if (++_Idx[_I] < _Len[_I])
  208. break;
  209. _Idx[_I] = 0;
  210. }
  211. }
  212. // Iterate to the next subscript by computing its offset and updating
  213. // THIS IS THE FUNCTION USED FOR NORMAL ITERATION
  214. size_t _Off (VIMD& _Idx) const
  215. {
  216. size_t _K = _IOff(_Idx);
  217. _Upd(_Idx);
  218. return _K;
  219. }
  220. // Dimension reordering overloads; each behaves identically to its
  221. // base function, but accepts a dimension reordering array
  222. size_t _IOff(const VIMD& _Idx, const VIMD& _Idim) const
  223. {
  224. size_t _K = _Start;
  225. for (size_t _I = 0; _I < _Idx.size(); ++_I)
  226. {
  227. size_t _II = _Idim[_I];
  228. _K += _Idx[_II] * _Stride[_II];
  229. }
  230. return _K;
  231. }
  232. void _Upd (VIMD & _Idx, const VIMD& _Idim) const
  233. {
  234. for (size_t _I = _Len.size(); 0 < _I--;)
  235. {
  236. size_t _II = _Idim[_I];
  237. if (++_Idx[_II] < _Len[_II])
  238. break;
  239. _Idx[_II] = 0;
  240. }
  241. }
  242. size_t _Off (VIMD& _Idx, const VIMD& _Idim) const
  243. {
  244. size_t _K = _IOff(_Idx,_Idim);
  245. _Upd(_Idx,_Idim);
  246. return _K;
  247. }
  248. // Return an array like (0,1,2,3,...) for use with
  249. // the dimension-reordering members above
  250. void InitDimReorder ( VIMD & vimdDim ) const
  251. {
  252. vimdDim.resize( _Nslice() );
  253. for ( size_t i = 0 ; i < vimdDim.size() ; ++i )
  254. {
  255. vimdDim[i] = i;
  256. }
  257. }
  258. protected:
  259. size_t _Start; // Absolute starting offset into array
  260. VIMD _Len; // Signed integer array of dimension lengths
  261. VIMD _Stride; // Signed integer array of strides
  262. // Given the dimension lengths, compute the array of strides.
  263. inline void StrideFromLength ( const vbool * pvboolMissing = NULL );
  264. };
  265. /////////////////////////////////////////////////////////////////////////////////
  266. //
  267. // Template TMDVDENSE: Generalized multidimensional array handling.
  268. // Base class is 'valarray', so member elements must be available
  269. // (directly or through conversion) for mathematical operations.
  270. // For example, there's a "sum()" member for valarrays.
  271. //
  272. /////////////////////////////////////////////////////////////////////////////////
  273. template<class T>
  274. class TMDVDENSE : public pair<valarray<T>,MDVSLICE>
  275. {
  276. typedef valarray<T> vr_base;
  277. typedef pair<valarray<T>,MDVSLICE> pair_base;
  278. public:
  279. TMDVDENSE ( const VIMD & vimd )
  280. : pair_base( vr_base(), vimd )
  281. { SyncSize(); }
  282. TMDVDENSE () {}
  283. ~ TMDVDENSE () {}
  284. void Init ( const VIMD & vimd, size_t start = 0 )
  285. {
  286. second.Init( vimd, start );
  287. SyncSize();
  288. }
  289. void Init ( const MDVSLICE & mdvs )
  290. {
  291. second = mdvs;
  292. SyncSize();
  293. }
  294. void Init ( int cdim, ... )
  295. {
  296. va_list vl;
  297. va_start( vl, cdim );
  298. Init( cdim, vl );
  299. }
  300. void Init ( int cdim, va_list & vl )
  301. {
  302. second.Init( cdim, vl );
  303. SyncSize();
  304. }
  305. void SyncSize ()
  306. {
  307. size_t cElem = second._Totlen();
  308. if ( first.size() != cElem )
  309. first.resize( cElem );
  310. }
  311. // Subscripting as flat array
  312. T & operator [] ( int i )
  313. { return first.operator[](i); }
  314. T operator [] ( int i ) const
  315. { return first.operator[](i); }
  316. // Subscripting as m-d array
  317. T & operator [] ( const VIMD & vimd )
  318. { return (*this)[ second._IOff(vimd) ]; }
  319. T operator [] ( const VIMD & vimd ) const
  320. { return (*this)[ second._IOff(vimd) ]; }
  321. size_t size () const
  322. { return first.size(); }
  323. const MDVSLICE & Slice () const
  324. { return second ; }
  325. const VIMD & VimdDim () const
  326. { return second.size(); }
  327. bool operator == ( const TMDVDENSE & mdv ) const
  328. {
  329. return vequal(first,mdv.first)
  330. && second == mdv.second;
  331. }
  332. bool operator != ( const TMDVDENSE & mdv ) const
  333. {
  334. return !(*this == mdv);
  335. }
  336. class Iterator
  337. {
  338. public:
  339. Iterator ( TMDVDENSE & mdv )
  340. : _mdv(mdv),
  341. _mdvSlice( mdv.Slice() ),
  342. _itcurr(0),
  343. _itend( mdv.size() ),
  344. _bDimReorder(false)
  345. {
  346. assert( _mdvSlice._Totlen() == _itend );
  347. _vimd.resize(_mdvSlice._Nslice());
  348. }
  349. Iterator ( TMDVDENSE & mdv, const MDVSLICE & mdvslice )
  350. : _mdv(mdv),
  351. _mdvSlice( mdvslice ),
  352. _itcurr(0),
  353. _itend( mdvslice._Totlen() ),
  354. _bDimReorder(false)
  355. {
  356. _vimd.resize(_mdvSlice._Nslice());
  357. }
  358. void Reset()
  359. {
  360. vclear( _vimd, 0 );
  361. _itcurr = 0;
  362. }
  363. // Return flat index given const subscript array
  364. size_t Indx ( const VIMD & vimd ) const
  365. {
  366. return _bDimReorder
  367. ? _mdvSlice._IOff( vimd, _vimdDim )
  368. : _mdvSlice._IOff( vimd );
  369. }
  370. // Return flat index given subscript array; update sub array
  371. size_t IndxUpd ( VIMD & vimd )
  372. {
  373. return _bDimReorder
  374. ? _mdvSlice._Off( vimd, _vimdDim )
  375. : _mdvSlice._Off( vimd );
  376. }
  377. // Return current flat index, no update
  378. size_t Indx () const
  379. { return Indx( _vimd ); }
  380. // Return current flat index, with update
  381. size_t IndxUpd ()
  382. {
  383. if ( _itcurr < _itend )
  384. _itcurr++;
  385. return IndxUpd( _vimd );
  386. }
  387. // Return current datum, no update
  388. T & operator[] ( VIMD & vimd )
  389. { return _mdv[Indx()]; }
  390. // Return current datum, update sub array
  391. T & Next ()
  392. { return _mdv[IndxUpd()]; }
  393. size_t ICurr () const
  394. { return _itcurr; }
  395. size_t IEnd () const
  396. { return _itend; }
  397. bool BNext () const
  398. { return _itcurr < _itend; }
  399. const VIMD & Vitmd () const
  400. { return _vimd; }
  401. const MDVSLICE & Slice() const
  402. { return _mdvSlice; }
  403. void SetDimReorder ( const VIMD & vimdDim )
  404. {
  405. _vimdDim = vimdDim;
  406. _bDimReorder = true;
  407. // MSRDEVBUG: assert that the contents mention all dimensions correctly
  408. }
  409. TMDVDENSE & Mdv ()
  410. { return _mdv; }
  411. bool BReorder () const
  412. { return _bDimReorder; }
  413. const VIMD & VimdReorder () const
  414. { return _vimdDim; }
  415. protected:
  416. TMDVDENSE & _mdv; // Flat valarray
  417. const MDVSLICE & _mdvSlice; // Multidimensional slice
  418. VIMD _vimd; // Iteration control
  419. VIMD _vimdDim; // Dimension reordering (optional)
  420. size_t _itcurr; // Current iteration point
  421. size_t _itend; // Iteration terminus
  422. bool _bDimReorder; // Dimension reordering?
  423. };
  424. friend class Iterator;
  425. };
  426. /////////////////////////////////////////////////////////////////////////////////
  427. // MDVSLICE member functions
  428. /////////////////////////////////////////////////////////////////////////////////
  429. inline
  430. void MDVSLICE :: StrideFromLength ( const vbool * pvboolMissing )
  431. {
  432. size_t cd = _Len.size();
  433. _Stride.resize(cd);
  434. size_t c = 1;
  435. size_t cmiss = pvboolMissing
  436. ? pvboolMissing->size()
  437. : 0;
  438. for ( int i = cd; --i >= 0 ; )
  439. {
  440. int l = _Len[i];
  441. if ( l == 0 )
  442. continue;
  443. if ( i < cmiss && (*pvboolMissing)[i] )
  444. {
  445. _Stride[i] = 0;
  446. }
  447. else
  448. {
  449. _Stride[i] = c;
  450. c *= l;
  451. }
  452. }
  453. }
  454. // Construct a gslice from an MDVSLICE
  455. inline
  456. gslice MDVSLICE :: Gslice () const
  457. {
  458. _Sizarray vszLength;
  459. _Sizarray vszStride;
  460. return gslice( _Start,
  461. vdup( vszLength, _Len ),
  462. vdup( vszStride, _Stride ) );
  463. }
  464. // End of mdvect.h
  465. #endif