00001
00002
00003
00004
00005
00006
00007
00008
00013 #ifndef matrix_inverse_h
00014 #define matrix_inverse_h
00015
00016 #include <cml/matrix/lu.h>
00017
00018 namespace cml {
00019 namespace detail {
00020
00021
00022
00023
00024 template<typename MatT, int _tag> struct inverse_f;
00025
00026
00027
00028
00029
00030
00031
00032 template<typename MatT>
00033 struct inverse_f<MatT,2>
00034 {
00035 typename MatT::temporary_type operator()(const MatT& M) const
00036 {
00037 typedef typename MatT::temporary_type temporary_type;
00038 typedef typename temporary_type::value_type value_type;
00039
00040
00041 temporary_type Z;
00042 cml::et::detail::Resize(Z,2,2);
00043
00044
00045 value_type D = value_type(1) / (M(0,0)*M(1,1) - M(0,1)*M(1,0));
00046 Z(0,0) = M(1,1)*D; Z(0,1) = - M(0,1)*D;
00047 Z(1,0) = - M(1,0)*D; Z(1,1) = M(0,0)*D;
00048
00049 return Z;
00050 }
00051 };
00052
00053
00054
00055
00056 template<typename MatT>
00057 struct inverse_f<MatT,3>
00058 {
00059
00060
00061
00062
00063 typename MatT::temporary_type operator()(const MatT& M) const
00064 {
00065
00066 typedef typename MatT::value_type value_type;
00067
00068
00069 value_type m_00 = M(1,1)*M(2,2) - M(1,2)*M(2,1);
00070 value_type m_01 = M(1,2)*M(2,0) - M(1,0)*M(2,2);
00071 value_type m_02 = M(1,0)*M(2,1) - M(1,1)*M(2,0);
00072
00073 value_type m_10 = M(0,2)*M(2,1) - M(0,1)*M(2,2);
00074 value_type m_11 = M(0,0)*M(2,2) - M(0,2)*M(2,0);
00075 value_type m_12 = M(0,1)*M(2,0) - M(0,0)*M(2,1);
00076
00077 value_type m_20 = M(0,1)*M(1,2) - M(0,2)*M(1,1);
00078 value_type m_21 = M(0,2)*M(1,0) - M(0,0)*M(1,2);
00079 value_type m_22 = M(0,0)*M(1,1) - M(0,1)*M(1,0);
00080
00081
00082 value_type D =
00083 value_type(1) / (M(0,0)*m_00 + M(0,1)*m_01 + M(0,2)*m_02);
00084
00085
00086 typename MatT::temporary_type Z;
00087 cml::et::detail::Resize(Z,3,3);
00088
00089
00090 Z(0,0) = m_00*D; Z(0,1) = m_10*D; Z(0,2) = m_20*D;
00091 Z(1,0) = m_01*D; Z(1,1) = m_11*D; Z(1,2) = m_21*D;
00092 Z(2,0) = m_02*D; Z(2,1) = m_12*D; Z(2,2) = m_22*D;
00093
00094 return Z;
00095 }
00096 };
00097
00098
00099
00100
00101 template<typename MatT>
00102 struct inverse_f<MatT,4>
00103 {
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 typename MatT::temporary_type operator()(const MatT& M) const
00118 {
00119
00120 typedef typename MatT::value_type value_type;
00121
00122
00123 value_type m_22_33_23_32 = M(2,2)*M(3,3) - M(2,3)*M(3,2);
00124 value_type m_23_30_20_33 = M(2,3)*M(3,0) - M(2,0)*M(3,3);
00125 value_type m_20_31_21_30 = M(2,0)*M(3,1) - M(2,1)*M(3,0);
00126 value_type m_21_32_22_31 = M(2,1)*M(3,2) - M(2,2)*M(3,1);
00127 value_type m_23_31_21_33 = M(2,3)*M(3,1) - M(2,1)*M(3,3);
00128 value_type m_20_32_22_30 = M(2,0)*M(3,2) - M(2,2)*M(3,0);
00129
00130
00131 value_type d00
00132 = M(1,1)*m_22_33_23_32+M(1,2)*m_23_31_21_33+M(1,3)*m_21_32_22_31;
00133
00134 value_type d01
00135 = M(1,0)*m_22_33_23_32+M(1,2)*m_23_30_20_33+M(1,3)*m_20_32_22_30;
00136
00137 value_type d02
00138 = M(1,0)*-m_23_31_21_33+M(1,1)*m_23_30_20_33+M(1,3)*m_20_31_21_30;
00139
00140 value_type d03
00141 = M(1,0)*m_21_32_22_31+M(1,1)*-m_20_32_22_30+M(1,2)*m_20_31_21_30;
00142
00143
00144 value_type d10
00145 = M(0,1)*m_22_33_23_32+M(0,2)*m_23_31_21_33+M(0,3)*m_21_32_22_31;
00146
00147 value_type d11
00148 = M(0,0)*m_22_33_23_32+M(0,2)*m_23_30_20_33+M(0,3)*m_20_32_22_30;
00149
00150 value_type d12
00151 = M(0,0)*-m_23_31_21_33+M(0,1)*m_23_30_20_33+M(0,3)*m_20_31_21_30;
00152
00153 value_type d13
00154 = M(0,0)*m_21_32_22_31+M(0,1)*-m_20_32_22_30+M(0,2)*m_20_31_21_30;
00155
00156
00157 value_type m_02_13_03_12 = M(0,2)*M(1,3) - M(0,3)*M(1,2);
00158 value_type m_03_10_00_13 = M(0,3)*M(1,0) - M(0,0)*M(1,3);
00159 value_type m_00_11_01_10 = M(0,0)*M(1,1) - M(0,1)*M(1,0);
00160 value_type m_01_12_02_11 = M(0,1)*M(1,2) - M(0,2)*M(1,1);
00161 value_type m_03_11_01_13 = M(0,3)*M(1,1) - M(0,1)*M(1,3);
00162 value_type m_00_12_02_10 = M(0,0)*M(1,2) - M(0,2)*M(1,0);
00163
00164
00165
00166
00167 value_type d20
00168 = M(3,1)*m_02_13_03_12+M(3,2)*m_03_11_01_13+M(3,3)*m_01_12_02_11;
00169
00170 value_type d21
00171 = M(3,0)*m_02_13_03_12+M(3,2)*m_03_10_00_13+M(3,3)*m_00_12_02_10;
00172
00173 value_type d22
00174 = M(3,0)*-m_03_11_01_13+M(3,1)*m_03_10_00_13+M(3,3)*m_00_11_01_10;
00175
00176 value_type d23
00177 = M(3,0)*m_01_12_02_11+M(3,1)*-m_00_12_02_10+M(3,2)*m_00_11_01_10;
00178
00179
00180 value_type d30
00181 = M(2,1)*m_02_13_03_12+M(2,2)*m_03_11_01_13+M(2,3)*m_01_12_02_11;
00182
00183 value_type d31
00184 = M(2,0)*m_02_13_03_12+M(2,2)*m_03_10_00_13+M(2,3)*m_00_12_02_10;
00185
00186 value_type d32
00187 = M(2,0)*-m_03_11_01_13+M(2,1)*m_03_10_00_13+M(2,3)*m_00_11_01_10;
00188
00189 value_type d33
00190 = M(2,0)*m_01_12_02_11+M(2,1)*-m_00_12_02_10+M(2,2)*m_00_11_01_10;
00191
00192
00193
00194
00195 typename MatT::temporary_type Z;
00196 cml::et::detail::Resize(Z,4,4);
00197
00198 value_type D = value_type(1) /
00199 (M(0,0)*d00 - M(0,1)*d01 + M(0,2)*d02 - M(0,3)*d03);
00200 Z(0,0) = +d00*D; Z(0,1) = -d10*D; Z(0,2) = +d20*D; Z(0,3) = -d30*D;
00201 Z(1,0) = -d01*D; Z(1,1) = +d11*D; Z(1,2) = -d21*D; Z(1,3) = +d31*D;
00202 Z(2,0) = +d02*D; Z(2,1) = -d12*D; Z(2,2) = +d22*D; Z(2,3) = -d32*D;
00203 Z(3,0) = -d03*D; Z(3,1) = +d13*D; Z(3,2) = -d23*D; Z(3,3) = +d33*D;
00204
00205 return Z;
00206 }
00207 };
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 template<typename MatT, int _tag>
00221 struct inverse_f
00222 {
00223 typename MatT::temporary_type operator()(const MatT& M) const
00224 {
00225
00226 typedef typename MatT::value_type value_type;
00227
00228
00229 size_t N = M.rows();
00230
00231
00232 typename MatT::temporary_type Z;
00233 cml::et::detail::Resize(Z,N,N);
00234 Z = M;
00235
00236
00237 std::vector<size_t> row_index(N);
00238 std::vector<size_t> col_index(N);
00239 std::vector<size_t> pivoted(N,0);
00240
00241
00242 for (size_t i = 0; i < N; ++i) {
00243
00244
00245 size_t row = 0, col = 0;
00246 value_type max = value_type(0);
00247 for (size_t j = 0; j < N; ++j) {
00248 if (!pivoted[j]) {
00249 for (size_t k = 0; k < N; ++k) {
00250 if (!pivoted[k]) {
00251 value_type mag = std::fabs(Z(j,k));
00252 if (mag > max) {
00253 max = mag;
00254 row = j;
00255 col = k;
00256 }
00257 }
00258 }
00259 }
00260 }
00261
00262
00263
00264 row_index[i] = row;
00265 col_index[i] = col;
00266
00267
00268 if (row != col) {
00269
00270 for (size_t j = 0; j < Z.cols(); ++j) {
00271 std::swap(Z(row,j),Z(col,j));
00272 }
00273 }
00274
00275
00276 pivoted[col] = true;
00277 value_type pivot = Z(col,col);
00278 Z(col,col) = value_type(1);
00279
00280 value_type k = value_type(1)/pivot;
00281 for (size_t j = 0; j < Z.cols(); ++j) {
00282 Z(col,j) *= k;
00283 }
00284
00285
00286 for (size_t j = 0; j < N; ++j) {
00287 if (j != col) {
00288 value_type mult = -Z(j,col);
00289 Z(j,col) = value_type(0);
00290
00291 for (size_t k = 0; k < Z.cols(); ++k) {
00292 Z(j,k) += mult * Z(col,k);
00293 }
00294 }
00295 }
00296 }
00297
00298
00299 for (int i = N-1; i >= 0; --i) {
00300 if (row_index[i] != col_index[i]) {
00301
00302 for (size_t j = 0; j < Z.rows(); ++j) {
00303 std::swap(Z(j,row_index[i]),Z(j,col_index[i]));
00304 }
00305 }
00306 }
00307
00308
00309 return Z;
00310 }
00311 };
00312
00313
00314
00315
00316
00317
00318 #if 0
00319
00320
00321 template<typename MatT, int _tag>
00322 struct inverse_f
00323 {
00324 typename MatT::temporary_type operator()(const MatT& M) const
00325 {
00326
00327 typedef typename MatT::value_type value_type;
00328
00329
00330 size_t N = M.rows();
00331 typename MatT::temporary_type LU;
00332 cml::et::detail::Resize(LU,N,N);
00333 LU = lu(M);
00334
00335
00336 typename MatT::temporary_type Z;
00337 cml::et::detail::Resize(Z,N,N);
00338
00339 typename MatT::col_vector_type v, x;
00340 cml::et::detail::Resize(v,N);
00341 cml::et::detail::Resize(x,N);
00342 for(size_t i = 0; i < N; ++i)
00343 v[i] = value_type(0);
00344
00345
00346
00347 for(size_t i = 0; i < N; ++i) {
00348 v[i] = 1.;
00349 x = lu_solve(LU,v);
00350
00351
00352 for(size_t k = 0; k < N; ++ k) {
00353 Z(k,i) = x[k];
00354 }
00355 v[i] = 0.;
00356 }
00357
00358 return Z;
00359 }
00360
00361 };
00362
00363 #endif
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 template<typename MatT> typename MatT::temporary_type
00378 inverse(const MatT& M, fixed_size_tag)
00379 {
00380
00381 cml::et::CheckedSquare(M, fixed_size_tag());
00382
00383
00384
00385
00386
00387
00388 return inverse_f<MatT,MatT::array_rows>()(M);
00389
00390
00391
00392 }
00393
00394
00395 template<typename MatT> typename MatT::temporary_type
00396 inverse(const MatT& M, dynamic_size_tag)
00397 {
00398
00399 cml::et::CheckedSquare(M, dynamic_size_tag());
00400
00401
00402
00403
00404
00405
00406
00407 switch(M.rows()) {
00408 case 2: return inverse_f<MatT,2>()(M);
00409 case 3: return inverse_f<MatT,3>()(M);
00410 case 4: return inverse_f<MatT,4>()(M);
00411 default: return inverse_f<MatT,0>()(M);
00412 }
00413
00414
00415
00416 }
00417
00418 }
00419
00421 template<typename E, class AT, typename BO, typename L> inline
00422 typename matrix<E,AT,BO,L>::temporary_type
00423 inverse(const matrix<E,AT,BO,L>& M)
00424 {
00425 typedef typename matrix<E,AT,BO,L>::size_tag size_tag;
00426 return detail::inverse(M,size_tag());
00427 }
00428
00430 template<typename XprT> inline
00431 typename et::MatrixXpr<XprT>::temporary_type
00432 inverse(const et::MatrixXpr<XprT>& e)
00433 {
00434 typedef typename et::MatrixXpr<XprT>::size_tag size_tag;
00435 return detail::inverse(e,size_tag());
00436 }
00437
00438 }
00439
00440 #endif
00441
00442
00443