00001
00002
00003
00004
00005
00006
00007
00008
00015 #ifndef determinant_h
00016 #define determinant_h
00017
00018 #include <cml/matrix/lu.h>
00019
00020 namespace cml {
00021 namespace detail {
00022
00023
00024
00025
00026
00027 template<typename MatT, int N> struct determinant_f;
00028
00029
00030
00031
00032 template<typename MatT>
00033 struct determinant_f<MatT,2>
00034 {
00035 typename MatT::value_type operator()(const MatT& M) const
00036 {
00037 return M(0,0)*M(1,1) - M(1,0)*M(0,1);
00038 }
00039
00040 };
00041
00042
00043
00044
00045 template<typename MatT>
00046 struct determinant_f<MatT,3>
00047 {
00048
00049
00050
00051
00052 typename MatT::value_type operator()(const MatT& M) const
00053 {
00054 return M(0,0)*(M(1,1)*M(2,2) - M(1,2)*M(2,1))
00055 + M(0,1)*(M(1,2)*M(2,0) - M(1,0)*M(2,2))
00056 + M(0,2)*(M(1,0)*M(2,1) - M(1,1)*M(2,0));
00057 }
00058
00059 };
00060
00061
00062
00063
00064 template<typename MatT>
00065 struct determinant_f<MatT,4>
00066 {
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 typename MatT::value_type operator()(const MatT& M) const
00089 {
00090
00091 typedef typename MatT::value_type value_type;
00092
00093
00094 value_type m_22_33_23_32 = M(2,2)*M(3,3) - M(2,3)*M(3,2);
00095 value_type m_23_30_20_33 = M(2,3)*M(3,0) - M(2,0)*M(3,3);
00096 value_type m_20_31_21_30 = M(2,0)*M(3,1) - M(2,1)*M(3,0);
00097 value_type m_21_32_22_31 = M(2,1)*M(3,2) - M(2,2)*M(3,1);
00098 value_type m_23_31_21_33 = M(2,3)*M(3,1) - M(2,1)*M(3,3);
00099 value_type m_20_32_22_30 = M(2,0)*M(3,2) - M(2,2)*M(3,0);
00100
00101 value_type d00 = M(0,0)*(
00102 M(1,1) * m_22_33_23_32
00103 + M(1,2) * m_23_31_21_33
00104 + M(1,3) * m_21_32_22_31);
00105
00106 value_type d01 = M(0,1)*(
00107 M(1,0) * m_22_33_23_32
00108 + M(1,2) * m_23_30_20_33
00109 + M(1,3) * m_20_32_22_30);
00110
00111 value_type d02 = M(0,2)*(
00112 M(1,0) * - m_23_31_21_33
00113 + M(1,1) * m_23_30_20_33
00114 + M(1,3) * m_20_31_21_30);
00115
00116 value_type d03 = M(0,3)*(
00117 M(1,0) * m_21_32_22_31
00118 + M(1,1) * - m_20_32_22_30
00119 + M(1,2) * m_20_31_21_30);
00120
00121 return d00 - d01 + d02 - d03;
00122 }
00123
00124 };
00125
00126
00127 template<typename MatT, int N>
00128 struct determinant_f
00129 {
00130 typename MatT::value_type operator()(const MatT& M) const
00131 {
00132
00133 typename MatT::temporary_type LU = lu(M);
00134
00135
00136 typename MatT::value_type det = LU(0,0);
00137 for(size_t i = 1; i < LU.rows(); ++ i)
00138 det *= LU(i,i);
00139 return det;
00140 }
00141
00142 };
00143
00144
00145 template<typename MatT> typename MatT::value_type
00146 determinant(const MatT& M, fixed_size_tag)
00147 {
00148
00149 cml::et::CheckedSquare(M, fixed_size_tag());
00150 return determinant_f<MatT,MatT::array_rows>()(M);
00151 }
00152
00153
00154 template<typename MatT> typename MatT::value_type
00155 determinant(const MatT& M, dynamic_size_tag)
00156 {
00157
00158 cml::et::CheckedSquare(M, dynamic_size_tag());
00159
00160
00161 switch(M.rows()) {
00162 case 2: return determinant_f<MatT,2>()(M);
00163 case 3: return determinant_f<MatT,3>()(M);
00164 case 4: return determinant_f<MatT,4>()(M);
00165 default: return determinant_f<MatT,0>()(M);
00166 }
00167 }
00168
00169 }
00170
00172 template<typename E, class AT, class BO, class L> inline E
00173 determinant(const matrix<E,AT,BO,L>& M)
00174 {
00175 typedef typename matrix<E,AT,BO,L>::size_tag size_tag;
00176 return detail::determinant(M,size_tag());
00177 }
00178
00180 template<typename XprT> inline typename XprT::value_type
00181 determinant(const et::MatrixXpr<XprT>& e)
00182 {
00183 typedef typename et::MatrixXpr<XprT>::size_tag size_tag;
00184 return detail::determinant(e,size_tag());
00185 }
00186
00187 }
00188
00189 #endif
00190
00191
00192