00001 #ifndef TOON_INCLUDE_DETERMINANT_H
00002 #define TOON_INCLUDE_DETERMINANT_H
00003 #include <TooN/TooN.h>
00004 #include <cstdlib>
00005 #include <utility>
00006 #ifdef TOON_DETERMINANT_LAPACK
00007 #include <TooN/LU.h>
00008 #endif
00009
00010 namespace TooN
00011 {
00012 namespace Internal
00013 {
00020 template<int R, int C> struct Square
00021 {
00022 };
00023
00024
00028 template<int R> struct Square<R, R>
00029 {
00030 static const int Size = R;
00031 };
00032
00037 template<int R> struct Square<R, Dynamic>
00038 {
00039 static const int Size = R;
00040 };
00045 template<int C> struct Square<Dynamic, C>
00046 {
00047 static const int Size = C;
00048 };
00053 template<> struct Square<Dynamic, Dynamic>
00054 {
00055 static const int Size = Dynamic;
00056 };
00057 };
00058
00059
00065 template<int R, int C, typename Precision, typename Base>
00066 Precision determinant_gaussian_elimination(const Matrix<R, C, Precision, Base>& A_)
00067 {
00068 Matrix<Internal::Square<R,C>::Size, Internal::Square<R,C>::Size,Precision> A = A_;
00069 TooN::SizeMismatch<R, C>::test(A.num_rows(), A.num_cols());
00070 using std::swap;
00071 using std::abs;
00072
00073 int size=A.num_rows();
00074
00075
00076
00077
00078
00079 Precision determinant=1;
00080
00081 for (int i=0; i<size; ++i) {
00082
00083
00084 int argmax = i;
00085 Precision maxval = abs(A[i][i]);
00086
00087 for (int ii=i+1; ii<size; ++ii) {
00088 double v = abs(A[ii][i]);
00089 if (v > maxval) {
00090 maxval = v;
00091 argmax = ii;
00092 }
00093 }
00094 Precision pivot = A[argmax][i];
00095
00096
00097
00098
00099
00100 if (argmax != i) {
00101 determinant*=-1;
00102 for (int j=i; j<size; ++j)
00103 swap(A[i][j], A[argmax][j]);
00104 }
00105
00106 determinant *= A[i][i];
00107
00108 if(determinant == 0)
00109 return 0;
00110
00111 for (int u=i+1; u<size; ++u) {
00112
00113
00114 double factor = A[u][i]/pivot;
00115
00116 for (int j=i+1; j<size; ++j)
00117 A[u][j] = A[u][j] - factor * A[i][j];
00118 }
00119 }
00120
00121 return determinant;
00122 }
00123
00124 #ifdef TOON_DETERMINANT_LAPACK
00125
00130 template<int R, int C, class P, class B>
00131 P determinant_LU(const Matrix<R, C, P, B>& A)
00132 {
00133 TooN::SizeMismatch<R, C>::test(A.num_rows(), A.num_cols());
00134 LU<Internal::Square<R,C>::Size, P> lu(A);
00135 return lu.determinant();
00136 }
00137 #endif
00138
00148 template<int R, int C, class P, class B>
00149 P determinant(const Matrix<R, C, P, B>& A)
00150 {
00151 TooN::SizeMismatch<R, C>::test(A.num_rows(), A.num_cols());
00152 if(A.num_rows() == 2)
00153 return A[0][0]*A[1][1] - A[1][0]*A[0][1];
00154 #if defined TOON_DETERMINANT_LAPACK && TOON_DETERMINANT_LAPACK != -1
00155 else if(A.num_rows() >= TOON_DETERMINANT_LAPACK)
00156 return determinant_LU(A);
00157 #endif
00158 else
00159 return determinant_gaussian_elimination(A);
00160 }
00161 }
00162
00163 #endif