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 (at) 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 10 #ifndef EIGEN_DETERMINANT_H 11 #define EIGEN_DETERMINANT_H 12 13 namespace Eigen { 14 15 namespace internal { 16 17 template<typename Derived> 18 inline const typename Derived::Scalar bruteforce_det3_helper 19 (const MatrixBase<Derived>& matrix, int a, int b, int c) 20 { 21 return matrix.coeff(0,a) 22 * (matrix.coeff(1,b) * matrix.coeff(2,c) - matrix.coeff(1,c) * matrix.coeff(2,b)); 23 } 24 25 template<typename Derived> 26 const typename Derived::Scalar bruteforce_det4_helper 27 (const MatrixBase<Derived>& matrix, int j, int k, int m, int n) 28 { 29 return (matrix.coeff(j,0) * matrix.coeff(k,1) - matrix.coeff(k,0) * matrix.coeff(j,1)) 30 * (matrix.coeff(m,2) * matrix.coeff(n,3) - matrix.coeff(n,2) * matrix.coeff(m,3)); 31 } 32 33 template<typename Derived, 34 int DeterminantType = Derived::RowsAtCompileTime 35 > struct determinant_impl 36 { 37 static inline typename traits<Derived>::Scalar run(const Derived& m) 38 { 39 if(Derived::ColsAtCompileTime==Dynamic && m.rows()==0) 40 return typename traits<Derived>::Scalar(1); 41 return m.partialPivLu().determinant(); 42 } 43 }; 44 45 template<typename Derived> struct determinant_impl<Derived, 1> 46 { 47 static inline typename traits<Derived>::Scalar run(const Derived& m) 48 { 49 return m.coeff(0,0); 50 } 51 }; 52 53 template<typename Derived> struct determinant_impl<Derived, 2> 54 { 55 static inline typename traits<Derived>::Scalar run(const Derived& m) 56 { 57 return m.coeff(0,0) * m.coeff(1,1) - m.coeff(1,0) * m.coeff(0,1); 58 } 59 }; 60 61 template<typename Derived> struct determinant_impl<Derived, 3> 62 { 63 static inline typename traits<Derived>::Scalar run(const Derived& m) 64 { 65 return bruteforce_det3_helper(m,0,1,2) 66 - bruteforce_det3_helper(m,1,0,2) 67 + bruteforce_det3_helper(m,2,0,1); 68 } 69 }; 70 71 template<typename Derived> struct determinant_impl<Derived, 4> 72 { 73 static typename traits<Derived>::Scalar run(const Derived& m) 74 { 75 // trick by Martin Costabel to compute 4x4 det with only 30 muls 76 return bruteforce_det4_helper(m,0,1,2,3) 77 - bruteforce_det4_helper(m,0,2,1,3) 78 + bruteforce_det4_helper(m,0,3,1,2) 79 + bruteforce_det4_helper(m,1,2,0,3) 80 - bruteforce_det4_helper(m,1,3,0,2) 81 + bruteforce_det4_helper(m,2,3,0,1); 82 } 83 }; 84 85 } // end namespace internal 86 87 /** \lu_module 88 * 89 * \returns the determinant of this matrix 90 */ 91 template<typename Derived> 92 inline typename internal::traits<Derived>::Scalar MatrixBase<Derived>::determinant() const 93 { 94 eigen_assert(rows() == cols()); 95 typedef typename internal::nested<Derived,Base::RowsAtCompileTime>::type Nested; 96 return internal::determinant_impl<typename internal::remove_all<Nested>::type>::run(derived()); 97 } 98 99 } // end namespace Eigen 100 101 #endif // EIGEN_DETERMINANT_H 102