Determinant.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #ifndef EIGEN_DETERMINANT_H
  10. #define EIGEN_DETERMINANT_H
  11. namespace Eigen {
  12. namespace internal {
  13. template<typename Derived>
  14. EIGEN_DEVICE_FUNC
  15. inline const typename Derived::Scalar bruteforce_det3_helper
  16. (const MatrixBase<Derived>& matrix, int a, int b, int c)
  17. {
  18. return matrix.coeff(0,a)
  19. * (matrix.coeff(1,b) * matrix.coeff(2,c) - matrix.coeff(1,c) * matrix.coeff(2,b));
  20. }
  21. template<typename Derived,
  22. int DeterminantType = Derived::RowsAtCompileTime
  23. > struct determinant_impl
  24. {
  25. static inline typename traits<Derived>::Scalar run(const Derived& m)
  26. {
  27. if(Derived::ColsAtCompileTime==Dynamic && m.rows()==0)
  28. return typename traits<Derived>::Scalar(1);
  29. return m.partialPivLu().determinant();
  30. }
  31. };
  32. template<typename Derived> struct determinant_impl<Derived, 1>
  33. {
  34. static inline EIGEN_DEVICE_FUNC
  35. typename traits<Derived>::Scalar run(const Derived& m)
  36. {
  37. return m.coeff(0,0);
  38. }
  39. };
  40. template<typename Derived> struct determinant_impl<Derived, 2>
  41. {
  42. static inline EIGEN_DEVICE_FUNC
  43. typename traits<Derived>::Scalar run(const Derived& m)
  44. {
  45. return m.coeff(0,0) * m.coeff(1,1) - m.coeff(1,0) * m.coeff(0,1);
  46. }
  47. };
  48. template<typename Derived> struct determinant_impl<Derived, 3>
  49. {
  50. static inline EIGEN_DEVICE_FUNC
  51. typename traits<Derived>::Scalar run(const Derived& m)
  52. {
  53. return bruteforce_det3_helper(m,0,1,2)
  54. - bruteforce_det3_helper(m,1,0,2)
  55. + bruteforce_det3_helper(m,2,0,1);
  56. }
  57. };
  58. template<typename Derived> struct determinant_impl<Derived, 4>
  59. {
  60. typedef typename traits<Derived>::Scalar Scalar;
  61. static EIGEN_DEVICE_FUNC
  62. Scalar run(const Derived& m)
  63. {
  64. Scalar d2_01 = det2(m, 0, 1);
  65. Scalar d2_02 = det2(m, 0, 2);
  66. Scalar d2_03 = det2(m, 0, 3);
  67. Scalar d2_12 = det2(m, 1, 2);
  68. Scalar d2_13 = det2(m, 1, 3);
  69. Scalar d2_23 = det2(m, 2, 3);
  70. Scalar d3_0 = det3(m, 1,d2_23, 2,d2_13, 3,d2_12);
  71. Scalar d3_1 = det3(m, 0,d2_23, 2,d2_03, 3,d2_02);
  72. Scalar d3_2 = det3(m, 0,d2_13, 1,d2_03, 3,d2_01);
  73. Scalar d3_3 = det3(m, 0,d2_12, 1,d2_02, 2,d2_01);
  74. return internal::pmadd(-m(0,3),d3_0, m(1,3)*d3_1) +
  75. internal::pmadd(-m(2,3),d3_2, m(3,3)*d3_3);
  76. }
  77. protected:
  78. static EIGEN_DEVICE_FUNC
  79. Scalar det2(const Derived& m, Index i0, Index i1)
  80. {
  81. return m(i0,0) * m(i1,1) - m(i1,0) * m(i0,1);
  82. }
  83. static EIGEN_DEVICE_FUNC
  84. Scalar det3(const Derived& m, Index i0, const Scalar& d0, Index i1, const Scalar& d1, Index i2, const Scalar& d2)
  85. {
  86. return internal::pmadd(m(i0,2), d0, internal::pmadd(-m(i1,2), d1, m(i2,2)*d2));
  87. }
  88. };
  89. } // end namespace internal
  90. /** \lu_module
  91. *
  92. * \returns the determinant of this matrix
  93. */
  94. template<typename Derived>
  95. EIGEN_DEVICE_FUNC
  96. inline typename internal::traits<Derived>::Scalar MatrixBase<Derived>::determinant() const
  97. {
  98. eigen_assert(rows() == cols());
  99. typedef typename internal::nested_eval<Derived,Base::RowsAtCompileTime>::type Nested;
  100. return internal::determinant_impl<typename internal::remove_all<Nested>::type>::run(derived());
  101. }
  102. } // end namespace Eigen
  103. #endif // EIGEN_DETERMINANT_H