Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / extern / Eigen2 / Eigen / src / LU / Determinant.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra. Eigen itself is part of the KDE project.
3 //
4 // Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
5 //
6 // Eigen is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // Alternatively, you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 2 of
14 // the License, or (at your option) any later version.
15 //
16 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License and a copy of the GNU General Public License along with
23 // Eigen. If not, see <http://www.gnu.org/licenses/>.
24
25 #ifndef EIGEN_DETERMINANT_H
26 #define EIGEN_DETERMINANT_H
27
28 template<typename Derived>
29 inline const typename Derived::Scalar ei_bruteforce_det3_helper
30 (const MatrixBase<Derived>& matrix, int a, int b, int c)
31 {
32   return matrix.coeff(0,a)
33          * (matrix.coeff(1,b) * matrix.coeff(2,c) - matrix.coeff(1,c) * matrix.coeff(2,b));
34 }
35
36 template<typename Derived>
37 const typename Derived::Scalar ei_bruteforce_det4_helper
38 (const MatrixBase<Derived>& matrix, int j, int k, int m, int n)
39 {
40   return (matrix.coeff(j,0) * matrix.coeff(k,1) - matrix.coeff(k,0) * matrix.coeff(j,1))
41        * (matrix.coeff(m,2) * matrix.coeff(n,3) - matrix.coeff(n,2) * matrix.coeff(m,3));
42 }
43
44 const int TriangularDeterminant = 0;
45
46 template<typename Derived,
47          int DeterminantType =
48            (Derived::Flags & (UpperTriangularBit | LowerTriangularBit))
49            ? TriangularDeterminant : Derived::RowsAtCompileTime
50 > struct ei_determinant_impl
51 {
52   static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
53   {
54     return m.lu().determinant();
55   }
56 };
57
58 template<typename Derived> struct ei_determinant_impl<Derived, TriangularDeterminant>
59 {
60   static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
61   {
62     if (Derived::Flags & UnitDiagBit)
63       return 1;
64     else if (Derived::Flags & ZeroDiagBit)
65       return 0;
66     else
67       return m.diagonal().redux(ei_scalar_product_op<typename ei_traits<Derived>::Scalar>());
68   }
69 };
70
71 template<typename Derived> struct ei_determinant_impl<Derived, 1>
72 {
73   static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
74   {
75     return m.coeff(0,0);
76   }
77 };
78
79 template<typename Derived> struct ei_determinant_impl<Derived, 2>
80 {
81   static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
82   {
83     return m.coeff(0,0) * m.coeff(1,1) - m.coeff(1,0) * m.coeff(0,1);
84   }
85 };
86
87 template<typename Derived> struct ei_determinant_impl<Derived, 3>
88 {
89   static typename ei_traits<Derived>::Scalar run(const Derived& m)
90   {
91     return ei_bruteforce_det3_helper(m,0,1,2)
92           - ei_bruteforce_det3_helper(m,1,0,2)
93           + ei_bruteforce_det3_helper(m,2,0,1);
94   }
95 };
96
97 template<typename Derived> struct ei_determinant_impl<Derived, 4>
98 {
99   static typename ei_traits<Derived>::Scalar run(const Derived& m)
100   {
101     // trick by Martin Costabel to compute 4x4 det with only 30 muls
102     return ei_bruteforce_det4_helper(m,0,1,2,3)
103           - ei_bruteforce_det4_helper(m,0,2,1,3)
104           + ei_bruteforce_det4_helper(m,0,3,1,2)
105           + ei_bruteforce_det4_helper(m,1,2,0,3)
106           - ei_bruteforce_det4_helper(m,1,3,0,2)
107           + ei_bruteforce_det4_helper(m,2,3,0,1);
108   }
109 };
110
111 /** \lu_module
112   *
113   * \returns the determinant of this matrix
114   */
115 template<typename Derived>
116 inline typename ei_traits<Derived>::Scalar MatrixBase<Derived>::determinant() const
117 {
118   assert(rows() == cols());
119   return ei_determinant_impl<Derived>::run(derived());
120 }
121
122 #endif // EIGEN_DETERMINANT_H