00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_MATRIX_INV_INCLUDE
00013 #define MTL_MATRIX_INV_INCLUDE
00014
00015 #include <boost/numeric/mtl/mtl_fwd.hpp>
00016 #include <boost/numeric/mtl/concept/collection.hpp>
00017 #include <boost/numeric/mtl/matrix/identity.hpp>
00018 #include <boost/numeric/mtl/operation/upper_trisolve.hpp>
00019 #include <boost/numeric/mtl/operation/lu.hpp>
00020 #include <boost/numeric/mtl/utility/exception.hpp>
00021 #include <boost/numeric/mtl/utility/irange.hpp>
00022 #include <boost/numeric/mtl/vector/dense_vector.hpp>
00023 #include <boost/numeric/mtl/vector/unit_vector.hpp>
00024
00025 namespace mtl { namespace matrix {
00026
00027 namespace traits {
00028
00030
00031 template <typename Matrix>
00032 struct inv
00033 {
00034 typedef typename Collection<Matrix>::value_type value_type;
00035 typedef ::mtl::matrix::dense2D<value_type> type;
00036 };
00037
00038 }
00039
00041 template <typename Matrix>
00042 typename traits::inv<Matrix>::type
00043 inv_upper(Matrix const& A)
00044 {
00045 typedef typename Collection<Matrix>::value_type value_type;
00046 typedef typename Collection<Matrix>::size_type size_type;
00047
00048 const size_type N= num_rows(A);
00049 MTL_THROW_IF(num_cols(A) != N, matrix_not_square());
00050
00051 typename traits::inv<Matrix>::type Inv(N, N);
00052 Inv= math::zero(value_type());
00053
00054 for (size_type k= 0; k < N; ++k) {
00055 irange r(k+1);
00056 Inv[r][k]= upper_trisolve(A[r][r], vector::unit_vector<value_type>(k, k+1));
00057 }
00058 return Inv;
00059 }
00060
00062 template <typename Matrix>
00063 typename traits::inv<Matrix>::type
00064 inline inv_lower(Matrix const& A)
00065 {
00066 Matrix T(trans(A));
00067 return typename traits::inv<Matrix>::type(trans(inv_upper(T)));
00068 }
00069
00070
00072
00074 template <typename Matrix>
00075 typename traits::inv<Matrix>::type
00076 inline inv(Matrix const& A)
00077 {
00078 typedef typename Collection<Matrix>::size_type size_type;
00079 typedef typename Collection<Matrix>::value_type value_type;
00080 typedef typename traits::inv<Matrix>::type result_type;
00081
00082 MTL_THROW_IF(num_cols(A) != num_cols(A), matrix_not_square());
00083
00084 result_type PLU(A);
00085 mtl::dense_vector<size_type> Pv(num_rows(A));
00086
00087 lu(PLU, Pv);
00088 result_type PU(upper(PLU)), PL(strict_lower(PLU) + identity<value_type>(num_rows(A), num_cols(A)));
00089
00090 return result_type(inv_upper(PU) * inv_lower(PL) * permutation(Pv));
00091 }
00092
00093
00094 }}
00095
00096 #endif // MTL_MATRIX_INV_INCLUDE