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 10#ifndef EIGEN_DETERMINANT_H 11#define EIGEN_DETERMINANT_H 12 13namespace Eigen { 14 15namespace internal { 16 17template<typename Derived> 18inline 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 25template<typename Derived> 26const 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 33template<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 45template<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 53template<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 61template<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 71template<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 */ 91template<typename Derived> 92inline 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