Counter Strike : Global Offensive Source Code
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.

123 lines
3.2 KiB

  1. //===== Copyright � 1996-2011, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // A class allowing storage of a sparse NxN matirx as an array of sparse rows
  6. //===========================================================================//
  7. #ifndef SPARSEMATRIX_H
  8. #define SPARSEMATRIX_H
  9. #include "tier1/utlvector.h"
  10. /// CSparseMatrix is a matrix which compresses each row individually, not storing the zeros. NOte,
  11. /// that while you can randomly set any element in a CSparseMatrix, you really want to do it top to
  12. /// bottom or you will have bad perf as data is moved around to insert new elements.
  13. class CSparseMatrix
  14. {
  15. public:
  16. struct NonZeroValueDescriptor_t
  17. {
  18. int m_nColumnNumber;
  19. float m_flValue;
  20. };
  21. struct RowDescriptor_t
  22. {
  23. int m_nNonZeroCount; // number of non-zero elements in the row
  24. int m_nDataIndex; // index of NonZeroValueDescriptor_t for the first non-zero value
  25. };
  26. int m_nNumRows;
  27. int m_nNumCols;
  28. CUtlVector<RowDescriptor_t> m_rowDescriptors;
  29. CUtlVector<NonZeroValueDescriptor_t> m_entries;
  30. int m_nHighestRowAppendedTo;
  31. void AdjustAllRowIndicesAfter( int nStartRow, int nDelta );
  32. public:
  33. FORCEINLINE float Element( int nRow, int nCol ) const;
  34. void SetElement( int nRow, int nCol, float flValue );
  35. void SetDimensions( int nNumRows, int nNumCols );
  36. void AppendElement( int nRow, int nCol, float flValue );
  37. void FinishedAppending( void );
  38. FORCEINLINE int Height( void ) const { return m_nNumRows; }
  39. FORCEINLINE int Width( void ) const { return m_nNumCols; }
  40. };
  41. FORCEINLINE float CSparseMatrix::Element( int nRow, int nCol ) const
  42. {
  43. Assert( nCol < m_nNumCols );
  44. int nCount = m_rowDescriptors[nRow].m_nNonZeroCount;
  45. if ( nCount )
  46. {
  47. NonZeroValueDescriptor_t const *pValue = &(m_entries[m_rowDescriptors[nRow].m_nDataIndex]);
  48. do
  49. {
  50. int nIdx = pValue->m_nColumnNumber;
  51. if ( nIdx == nCol )
  52. {
  53. return pValue->m_flValue;
  54. }
  55. if ( nIdx > nCol )
  56. {
  57. break;
  58. }
  59. pValue++;
  60. } while( --nCount );
  61. }
  62. return 0;
  63. }
  64. // type-specific overrides of matrixmath template for special case sparse routines
  65. namespace MatrixMath
  66. {
  67. /// sparse * dense matrix x matrix multiplication
  68. template<class BTYPE, class OUTTYPE>
  69. void MatrixMultiply( CSparseMatrix const &matA, BTYPE const &matB, OUTTYPE *pMatrixOut )
  70. {
  71. Assert( matA.Width() == matB.Height() );
  72. pMatrixOut->SetDimensions( matA.Height(), matB.Width() );
  73. for( int i = 0; i < matA.Height(); i++ )
  74. {
  75. for( int j = 0; j < matB.Width(); j++ )
  76. {
  77. // compute inner product efficiently because of sparsity
  78. int nCnt = matA.m_rowDescriptors[i].m_nNonZeroCount;
  79. int nDataIdx = matA.m_rowDescriptors[i].m_nDataIndex;
  80. float flDot = 0.0;
  81. for( int nIdx = 0; nIdx < nCnt; nIdx++ )
  82. {
  83. float flAValue = matA.m_entries[nIdx + nDataIdx].m_flValue;
  84. int nCol = matA.m_entries[nIdx + nDataIdx].m_nColumnNumber;
  85. flDot += flAValue * matB.Element( nCol, j );
  86. }
  87. pMatrixOut->SetElement( i, j, flDot );
  88. }
  89. }
  90. }
  91. FORCEINLINE void AppendElement( CSparseMatrix &matrix, int nRow, int nCol, float flValue )
  92. {
  93. matrix.AppendElement( nRow, nCol, flValue ); // default implementation
  94. }
  95. FORCEINLINE void FinishedAppending( CSparseMatrix &matrix )
  96. {
  97. matrix.FinishedAppending();
  98. }
  99. };
  100. #endif // SPARSEMATRIX_H