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.

143 lines
3.8 KiB

  1. //========= Copyright c 1996-2009, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Cholesky and LDL' decomposition-related code
  4. //
  5. //=====================================================================================//
  6. #include "mathlib/cholesky.h"
  7. #include "mathlib/ssecholesky.h"
  8. inline float ClampNeg( float a )
  9. {
  10. return a >= 0.0f ? a : 0.0f ; //( a + fabsf(a) ) * 0.5f;
  11. }
  12. inline float SafeSqrt( float a )
  13. {
  14. return sqrtf( ClampNeg( a ) );
  15. }
  16. inline float SafeRecip( float a )
  17. {
  18. return 1.0f / ( a > 1e-8f ? a : 1e-8f );
  19. }
  20. bool Cholesky3x3_t::IsValid( )
  21. {
  22. return m_inv00 + m_inv11 + m_inv22 < 1e+7f;
  23. }
  24. const fltx4 Four_1e7 = { 1.0e+7, 1.0e+7, 1.0e+7, 1.0e+7 };
  25. bool SimdCholesky3x3_t::IsValid( )const
  26. {
  27. return IsAllGreaterThan( Four_1e7, m_inv00 + m_inv11 + m_inv22 );
  28. }
  29. fltx4 SimdCholesky3x3_t::GetValidMask( )const
  30. {
  31. return CmpGtSIMD( Four_1e7, m_inv00 + m_inv11 + m_inv22 );
  32. }
  33. // initializes this decomposition; see formula at http://planetmath.org/encyclopedia/CholeskyDecomposition.html
  34. bool Cholesky3x3_t::Init( float a00, float a10, float a11, float a20, float a21, float a22 )
  35. {
  36. #ifdef _DEBUG
  37. memset( this, 0xCD, sizeof(*this) ); // to see what's changing easily
  38. #endif
  39. m_00 = SafeSqrt( a00 ); m_inv00 = SafeRecip( m_00 );
  40. m_10 = ( a10 ) * m_inv00;
  41. m_11 = SafeSqrt( a11 - Sqr( m_10 ) ); m_inv11 = SafeRecip( m_11 );
  42. m_20 = ( a20 ) * m_inv00;
  43. m_21 = ( a21 - m_20 * m_10) * m_inv11;
  44. m_22 = SafeSqrt( a22 - Sqr( m_20 ) - Sqr( m_21 ) ); m_inv22 = SafeRecip( m_22 );
  45. #ifdef _DEBUG
  46. if( IsValid() )
  47. {
  48. matrix3x4_t l,r, a;
  49. FillLeft(l);
  50. FillRight(r);
  51. MatrixMultiply(l, r, a);
  52. float flError = Sqr( a00 - a[0][0] ) + Sqr( a10 - a[1][0] ) + Sqr( a20 - a[2][0] ) +
  53. Sqr( a11 - a[1][1] ) + Sqr( a21 - a[2][1] ) + Sqr( a22 - a[2][2] );
  54. Assert( flError < 1e-5f );
  55. }
  56. #endif
  57. return IsValid();
  58. }
  59. void Cholesky3x3_t::FillLeft( matrix3x4_t & l )
  60. {
  61. l[0][0] = m_00;
  62. l[0][1] = l[0][2] = l[0][3] = 0;
  63. l[1][0] = m_10; l[1][1] = m_11;
  64. l[1][2] = l[1][3] = 0;
  65. l[2][0] = m_20; l[2][1] = m_21; l[2][2] = m_22;
  66. l[2][3] = 0;
  67. }
  68. void Cholesky3x3_t::FillRight( matrix3x4_t & r )
  69. {
  70. r[0][0] = m_00;
  71. r[1][0] = r[2][0] = 0;
  72. r[0][1] = m_10; r[1][1] = m_11;
  73. r[2][1] = 0;
  74. r[0][2] = m_20; r[1][2] = m_21; r[2][2] = m_22;
  75. r[0][3] = r[1][3] = r[2][3] = 0;
  76. }
  77. // solve this : L x = b
  78. const Vector Cholesky3x3_t::SolveLeft( const Vector &b )
  79. {
  80. Vector result;
  81. result.x = m_inv00 * b.x;
  82. result.y = m_inv11 * ( b.y - m_10 * result.x );
  83. result.z = m_inv22 * ( b.z - m_20 * result.x - m_21 * result.y );
  84. return result;
  85. }
  86. const Vector Cholesky3x3_t::SolveRight( const Vector &b )
  87. {
  88. Vector result;
  89. result.z = m_inv22 * b.z;
  90. result.y = m_inv11 * ( b.y - m_21 * result.z );
  91. result.x = m_inv00 * ( b.x - m_20 * result.z - m_10 * result.y );
  92. return result;
  93. }
  94. // initializes this decomposition; see formula at http://planetmath.org/encyclopedia/CholeskyDecomposition.html
  95. void SimdCholesky3x3_t::Init( const fltx4 & a00, const fltx4 & a10, const fltx4 & a11, const fltx4 & a20, const fltx4 & a21, const fltx4 & a22 )
  96. {
  97. m_inv00 = ReciprocalSqrtSIMD( a00 );
  98. m_10 = ( a10 ) * m_inv00;
  99. m_inv11 = ReciprocalSqrtSIMD( a11 - ( m_10 * m_10 ) );
  100. m_20 = ( a20 ) * m_inv00;
  101. m_21 = ( a21 - m_20 * m_10 ) * m_inv11;
  102. m_inv22 = ReciprocalSqrtSIMD( a22 - ( m_20 * m_20 ) - ( m_21 * m_21 ) );
  103. }
  104. // solve this : L x = b
  105. const FourVectors SimdCholesky3x3_t::SolveLeft( const FourVectors &b )
  106. {
  107. FourVectors result;
  108. result.x = m_inv00 * b.x;
  109. result.y = m_inv11 * ( b.y - m_10 * result.x );
  110. result.z = m_inv22 * ( b.z - m_20 * result.x - m_21 * result.y );
  111. return result;
  112. }
  113. const FourVectors SimdCholesky3x3_t::SolveRight( const FourVectors &b )
  114. {
  115. FourVectors result;
  116. result.z = m_inv22 * b.z;
  117. result.y = m_inv11 * ( b.y - m_21 * result.z );
  118. result.x = m_inv00 * ( b.x - m_20 * result.z - m_10 * result.y );
  119. return result;
  120. }