00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef MTL_MATRIX_LU_INCLUDE
00015 #define MTL_MATRIX_LU_INCLUDE
00016
00017 #include <cmath>
00018 #include <boost/numeric/linear_algebra/identity.hpp>
00019 #include <boost/numeric/mtl/utility/exception.hpp>
00020 #include <boost/numeric/mtl/utility/irange.hpp>
00021 #include <boost/numeric/mtl/concept/collection.hpp>
00022 #include <boost/numeric/mtl/matrix/upper.hpp>
00023 #include <boost/numeric/mtl/matrix/lower.hpp>
00024 #include <boost/numeric/mtl/matrix/permutation.hpp>
00025 #include <boost/numeric/mtl/operation/adjoint.hpp>
00026 #include <boost/numeric/mtl/operation/lower_trisolve.hpp>
00027 #include <boost/numeric/mtl/operation/upper_trisolve.hpp>
00028 #include <boost/numeric/mtl/operation/max_pos.hpp>
00029 #include <boost/numeric/mtl/operation/swap_row.hpp>
00030
00031
00032 namespace mtl { namespace matrix {
00033
00035 template <typename Matrix>
00036 void inline lu(Matrix& LU)
00037 {
00038 MTL_THROW_IF(num_rows(LU) != num_cols(LU), matrix_not_square());
00039
00040 for (std::size_t k= 0; k < num_rows(LU); k++) {
00041 irange r(k+1, imax), kr(k, k+1);
00042 LU[r][kr]/= LU[k][k];
00043 LU[r][r]-= LU[r][kr] * LU[kr][r];
00044 }
00045 }
00046
00048 template <typename Matrix, typename PermuationVector>
00049 void inline lu(Matrix& A, PermuationVector& P)
00050 {
00051 using math::zero;
00052 typedef typename Collection<Matrix>::size_type size_type;
00053 size_type ncols = num_cols(A), nrows = num_rows(A);
00054
00055 MTL_THROW_IF(ncols != nrows , matrix_not_square());
00056 P.change_dim(nrows);
00057
00058 for (size_type i= 0; i < nrows; i++)
00059 P[i]= i;
00060
00061 for (size_type i= 0; i < nrows; i++) {
00062
00063 irange r(i+1, imax), ir(i, i+1);
00064 size_type rmax= max_abs_pos(A[irange(i, imax)][ir]).first + i;
00065 swap_row(A, i, rmax);
00066 swap_row(P, i, rmax);
00067
00068 if(A[i][i] == zero(A[i][i])) throw matrix_singular();
00069
00070
00071 A[r][ir]/= A[i][i];
00072 A[r][r]-= A[r][ir] * A[ir][r];
00073 }
00074 }
00075
00076
00078 template <typename Matrix>
00079 Matrix inline lu_f(const Matrix& A)
00080 {
00081 Matrix LU(A);
00082 lu(LU);
00083 return LU;
00084 }
00085
00087 template <typename Matrix, typename Vector>
00088 Vector inline lu_solve_straight(const Matrix& A, const Vector& b)
00089 {
00090 Matrix LU(A);
00091 lu(LU);
00092 return upper_trisolve(upper(LU), unit_lower_trisolve(strict_lower(LU), b));
00093 }
00094
00096 template <typename Matrix, typename PermVector, typename Vector>
00097 Vector inline lu_apply(const Matrix& LU, const PermVector& P, const Vector& b)
00098 {
00099 return upper_trisolve(upper(LU), unit_lower_trisolve(strict_lower(LU), Vector(matrix::permutation(P) * b)));
00100 }
00101
00102
00104 template <typename Matrix, typename Vector>
00105 Vector inline lu_solve(const Matrix& A, const Vector& b)
00106 {
00107 dense_vector<std::size_t> P(num_rows(A));
00108 Matrix LU(A);
00109
00110 lu(LU, P);
00111 return lu_apply(LU, P, b);
00112 }
00113
00114
00116
00117 template <typename Matrix, typename PermVector, typename Vector>
00118 Vector inline lu_adjoint_apply(const Matrix& LU, const PermVector& P, const Vector& b)
00119 {
00120 return Vector(trans(matrix::permutation(P)) * unit_upper_trisolve(adjoint(LU), lower_trisolve(adjoint(LU), b)));
00121 }
00122
00123
00125 template <typename Matrix, typename Vector>
00126 Vector inline lu_adjoint_solve(const Matrix& A, const Vector& b)
00127 {
00128 dense_vector<std::size_t> P(num_rows(A));
00129 Matrix LU(A);
00130
00131 lu(LU, P);
00132 return lu_adjoint_apply(LU, P, b);
00133 }
00134
00135
00136
00137 }}
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 #if 0
00157
00158 namespace mtl { namespace matrix {
00159
00160 template <typename Matrix>
00161 void inline lu(Matrix& LU)
00162 {
00163 MTL_THROW_IF(num_rows(LU) != num_cols(LU), matrix_not_square());
00164
00165 typedef typename Collection<Matrix>::value_type value_type;
00166 typedef typename Collection<Matrix>::size_type size_type;
00167
00168 size_type n= num_rows(LU);
00169 for (size_type k= 0; k < num_rows(LU); k++) {
00170 value_type pivot= LU[k][k];
00171 for (size_type j= k+1; j < n; j++) {
00172 value_type alpha= LU[j][k]/= pivot;
00173 for (size_type i= k+1; i < n; i++)
00174 LU[j][i]-= alpha * LU[k][i];
00175 }
00176 }
00177 }
00178
00179
00180
00181 }}
00182
00183 #endif
00184
00185 #endif // MTL_MATRIX_LU_INCLUDE