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.

284 lines
6.9 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1997
  6. //
  7. // File: vrmatrx.h
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifndef _MATRIX_H_
  11. #define _MATRIX_H_
  12. #include <memory.h>
  13. #include "basics.h"
  14. #include "mdvect.h"
  15. //
  16. // VRMATRIXSQ.H: Matrix handling
  17. //
  18. template<class T>
  19. void fastMemMove(const T * ptfrom, T * ptto, int ct)
  20. {
  21. ::memmove( (void*) ptto, (void*) ptfrom, ct * sizeof(T) );
  22. }
  23. class VRMATRIX : public TMDVDENSE<REAL>
  24. {
  25. public:
  26. VRMATRIX ( int cRow, int cCol = 0 )
  27. {
  28. Init( cRow, cCol );
  29. }
  30. VRMATRIX () {}
  31. void Init ( int cRow, int cCol = 0 )
  32. {
  33. second.Init( 2, cRow, cCol != 0 ? cCol : cRow );
  34. first.resize( second._Totlen() );
  35. }
  36. void Init ( const VRMATRIX & vrmat )
  37. {
  38. Init( vrmat.CRow(), vrmat.CCol() );
  39. }
  40. bool BCanMultiply( const VRMATRIX & mat ) const
  41. {
  42. return CCol() == mat.CRow();
  43. }
  44. bool BSameDimension( const VRMATRIX & mat ) const
  45. {
  46. return CRow() == mat.CRow() && CCol() == mat.CCol() ;
  47. }
  48. int CDim ( int iDim ) const
  49. {
  50. return second.size().size() > iDim
  51. ? second.size()[iDim]
  52. : 0 ;
  53. }
  54. int CRow () const
  55. { return CDim(0); }
  56. int CCol () const
  57. { return CDim(1); }
  58. bool BSquare() const
  59. { return CRow() == CCol() ; }
  60. int IOffset ( int irow, int icol ) const
  61. {
  62. int cRow = CRow();
  63. int cCol = CCol();
  64. if ( irow >= CRow()
  65. || icol >= CCol() )
  66. throw GMException(EC_MDVECT_MISUSE,"subscript error on matrix");
  67. return second.stride()[0] * irow
  68. + second.stride()[1] * icol;
  69. }
  70. REAL & operator () ( int irow, int icol )
  71. { return first[ IOffset(irow,icol) ]; }
  72. const REAL & operator () ( int irow, int icol ) const
  73. {
  74. VRMATRIX & vrmx = const_cast<VRMATRIX&>(self);
  75. return vrmx.first[ IOffset(irow,icol) ];
  76. }
  77. void InterchangeRows ( int irow1, int irow2 )
  78. {
  79. if ( irow1 >= CRow()
  80. && irow2 >= CRow() )
  81. throw GMException(EC_MDVECT_MISUSE,"subscript error on matrix");
  82. if ( irow1 == irow2 )
  83. return;
  84. REAL * pr1 = & self(irow1,0);
  85. REAL * pr2 = & self(irow2,0);
  86. assert( & self(irow1,1) - pr1 == 1 );
  87. for ( int icol = 0; icol < CCol(); icol++ )
  88. {
  89. REAL r = *pr1;
  90. *pr1++ = *pr2;
  91. *pr2++ = r;
  92. }
  93. }
  94. void InterchangeCols ( int icol1, int icol2 )
  95. {
  96. if ( icol1 >= CCol()
  97. && icol2 >= CCol() )
  98. throw GMException(EC_MDVECT_MISUSE,"subscript error on matrix");
  99. if ( icol1 == icol2 )
  100. return;
  101. REAL * pr1 = & self(0,icol1);
  102. REAL * pr2 = & self(0,icol2);
  103. int icolInc = CCol();
  104. for ( int irow = 0; irow < CRow(); irow++ )
  105. {
  106. REAL r = *pr1;
  107. *pr1 = *pr2;
  108. *pr2 = r;
  109. pr1 += icolInc;
  110. pr2 += icolInc;
  111. }
  112. }
  113. // Return the transpose of the matrix
  114. VRMATRIX VrmatrixTranspose () const;
  115. // Return a row vector
  116. VLREAL VectorRow ( int irow ) const;
  117. // Return a column vector
  118. VLREAL VectorColumn ( int icol ) const;
  119. // Project a view of the matrix (see documentation below).
  120. VRMATRIX VrmatrixProject ( const VIMD & vimdRowColumnRetain ) const;
  121. VRMATRIX operator * ( const VRMATRIX & matrix ) const;
  122. VRMATRIX operator * ( const VLREAL & vreal ) const;
  123. VRMATRIX & operator += ( const VRMATRIX & matrix );
  124. VRMATRIX & operator -= ( const VRMATRIX & matrix );
  125. VRMATRIX & operator *= ( REAL rScalar );
  126. VRMATRIX & operator += ( REAL rScalar );
  127. VRMATRIX & operator -= ( REAL rScalar );
  128. VRMATRIX & operator /= ( REAL rScalar );
  129. };
  130. class VRMATRIXSQ : public VRMATRIX
  131. {
  132. public:
  133. VRMATRIXSQ(int cdim)
  134. : VRMATRIX(cdim,cdim),
  135. _iSign(1)
  136. {}
  137. VRMATRIXSQ () {}
  138. // Construct a square matrix as the product of a column
  139. // and a row vector.
  140. VRMATRIXSQ ( const VLREAL & vrColumn, const VLREAL & vrRow );
  141. ~ VRMATRIXSQ() {}
  142. // Return true if matrix is in L-U decomposition form
  143. bool BIsLUDecomposed () const
  144. { return _vimdRow.size() > 0 ; }
  145. // Destructive computation routines
  146. VRMATRIXSQ & operator *= ( REAL rScalar )
  147. {
  148. VRMATRIX::operator*=(rScalar);
  149. return self;
  150. }
  151. VRMATRIXSQ & operator /= ( REAL rScalar )
  152. {
  153. VRMATRIX::operator/=(rScalar);
  154. return self;
  155. }
  156. VRMATRIXSQ & operator += ( REAL rScalar )
  157. {
  158. VRMATRIX::operator+=(rScalar);
  159. return self;
  160. }
  161. VRMATRIXSQ & operator -= ( REAL rScalar )
  162. {
  163. VRMATRIX::operator-=(rScalar);
  164. return self;
  165. }
  166. VRMATRIXSQ & operator += ( const VRMATRIXSQ & matrix )
  167. {
  168. VRMATRIX::operator+=(matrix);
  169. return self;
  170. }
  171. VRMATRIXSQ & operator -= ( const VRMATRIXSQ & matrix )
  172. {
  173. VRMATRIX::operator-=(matrix);
  174. return self;
  175. }
  176. VRMATRIXSQ & operator *= ( const VRMATRIXSQ & matrix );
  177. // Perform L-U decomposition; throw exception if singular
  178. // If "use tiny" is set, pivots at zero are replaced with
  179. // RTINY value (1.0e-20)
  180. void LUDecompose( bool bUseTinyIfSingular = false );
  181. // Invert; throw exception singular. If not in L-U form,
  182. // L-U Decomp is called.
  183. void Invert( bool bUseTinyIfSingular = false );
  184. // Return the determinant. If not in L-U form,
  185. // L-U Decomp is called.
  186. DBL DblDeterminant();
  187. // Return the log of the determinant. If not in L-U form,
  188. // L-U Decomp is called. Throws exception if negative.
  189. DBL DblLogDeterminant();
  190. // ------------------------------------
  191. // Non-destructive computation routines
  192. // ------------------------------------
  193. // Adds the log of each element in the diagonal and returns the sum.
  194. DBL DblAddLogDiagonal() const;
  195. // Set vrmatResult to be the result of performing an L-U
  196. // decomposition on the matrix. Will throw exception if
  197. // the matrix is singular
  198. // If "use tiny" is set, pivots at zero are replaced with
  199. // RTINY value (1.0e-20)
  200. void GetLUDecompose( VRMATRIXSQ & vrmatResult, bool bUseTinyIfSingular = false ) const;
  201. // Set vrmatResult to the inverse of the matrix.
  202. // Will throw an exception if the matrix is singular.
  203. void GetInverse( VRMATRIXSQ & vrmatResult, bool bUseTinyIfSingular = false ) const;
  204. // Get the determinant without modifying (LU decomposing) the matrix.
  205. // vrmatResult will contain the LU decomposed version of the matrix.
  206. void GetDblDeterminant( DBL& dblDeterm, VRMATRIXSQ & vrmatResult ) const;
  207. // Get the log of determinant without modifying (LU decomposing) the matrix.
  208. // vrmatResult will contain the LU decomposed version of the matrix.
  209. void GetDblLogDeterminant( DBL& dblLogDeterm, VRMATRIXSQ & vrmatResult) const;
  210. // Project a view of the matrix (see documentation below).
  211. VRMATRIXSQ VrmatrixProject ( const VIMD & vimdRowColumnRetain ) const;
  212. protected:
  213. int _iSign;
  214. VIMD _vimdRow;
  215. void LUDBackSub(const VRMATRIXSQ & matrix);
  216. };
  217. /*
  218. How to use the VRMATRIX::Project() function.
  219. Original matrix:
  220. 1 2 3
  221. 4 5 6
  222. 7 8 9
  223. The (0,2) projection is obtained by deleting the 2nd row and 2nd column:
  224. 1 3
  225. 7 9
  226. The (0,1) projection is obtained by deleting the 3rd row (and third column):
  227. 1 2
  228. 4 5
  229. The (1,2) projeciton is obtained by deleting the 1st row and 1st column:
  230. 5 6
  231. 8 9
  232. The (0) projection is obtained by deleting the 2nd and 3rd rows and columns:
  233. 1
  234. */
  235. #endif