00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef MTL_MATRIX_QR_INCLUDE
00015 #define MTL_MATRIX_QR_INCLUDE
00016
00017 #include <cmath>
00018 #include <boost/numeric/linear_algebra/identity.hpp>
00019 #include <boost/numeric/linear_algebra/inverse.hpp>
00020 #include <boost/numeric/mtl/utility/exception.hpp>
00021 #include <boost/numeric/mtl/utility/irange.hpp>
00022 #include <boost/numeric/mtl/concept/collection.hpp>
00023 #include <boost/numeric/mtl/concept/magnitude.hpp>
00024 #include <boost/numeric/mtl/operation/householder.hpp>
00025 #include <boost/numeric/mtl/operation/rank_one_update.hpp>
00026 #include <boost/numeric/mtl/operation/trans.hpp>
00027
00028
00029 namespace mtl { namespace matrix {
00030
00031
00032
00033 template <typename Matrix>
00034 Matrix inline qr(const Matrix& A)
00035 {
00036 typedef typename Collection<Matrix>::value_type value_type;
00037 typedef typename Collection<Matrix>::size_type size_type;
00038 size_type ncols = num_cols(A), nrows = num_rows(A), mini;
00039 value_type zero= math::zero(A[0][0]);
00040 Matrix B(A);
00041
00042 if ( nrows < ncols ) throw mtl::logic_error("underdetermined system, use trans(A) instead of A");
00043 mini= nrows;
00044
00045 for (size_type i = 0; i < mini; i++) {
00046 irange r(i, imax);
00047 dense_vector<value_type> v(nrows-i), w(nrows-i);
00048
00049 for (size_type j = 0; j < size(w); j++)
00050 w[j]= B[j+i][i];
00051 value_type beta= householder(w).second;
00052 v= householder(w).first;
00053
00054 if ( beta != zero ){
00055
00056 for(size_type k = 0; k < ncols-i; k++){
00057 w[k]= zero;
00058 for(size_type j = 0; j < nrows-i; j++){
00059 w[k] += beta * v[j] * B[j+i][k+i];
00060 }
00061 }
00062
00063 for(size_type row = i; row < nrows; row++){
00064 for(size_type col = i; col < ncols; col++){
00065 B[row][col] -= v[row-i] * w[col-i];
00066 }
00067 }
00068
00069
00070 for (size_type k = i+1; k < nrows; k++)
00071 B[k][i]= v[k-i];
00072 }
00073 }
00074 return B;
00075 }
00076
00077
00078
00079
00080
00081 template <typename Matrix>
00082 std::pair<typename mtl::dense2D<typename Collection<Matrix>::value_type>,
00083 typename mtl::dense2D<typename Collection<Matrix>::value_type> >
00084 inline qr_factors(const Matrix& A)
00085 {
00086 using std::abs;
00087 typedef typename Collection<Matrix>::value_type value_type;
00088 typedef typename Magnitude<value_type>::type magnitude_type;
00089 typedef typename Collection<Matrix>::size_type size_type;
00090 size_type ncols = num_cols(A), nrows = num_rows(A);
00091 value_type zero= math::zero(A[0][0]), one= math::one(A[0][0]);
00092
00093
00094 Matrix Q(nrows, ncols), Qk(ncols, ncols), HEL(nrows, ncols), R(ncols, ncols), B(nrows, ncols);
00095 Q= one; R= zero; HEL= zero;
00096
00097 B= qr(A);
00098
00099
00100
00101
00102 for(size_type i = 0; i < nrows-1; i++){
00103 dense_vector<value_type> z(nrows-i);
00104
00105 for(size_type k = i+1; k < nrows-1; k++){
00106 z[k-i]= B[k][i];
00107 }
00108 z[0]= one;
00109 Qk= one;
00110 #if 0
00111 Qk= zero;
00112 for(size_type k = 0; k < ncols; k++){
00113 Qk[k][k]= one;
00114 }
00115 #endif
00116 magnitude_type factor= magnitude_type(2) / abs(dot(z, z));
00117
00118 for(size_type row = i; row < nrows; row++){
00119 for(size_type col = i; col < ncols; col++){
00120 Qk[row][col]-= factor * z[row-i] * z[col-i];
00121 }
00122 }
00123
00124 HEL = Q * Qk;
00125 Q = HEL;
00126 }
00127
00128
00129 for(size_type row = 0; row < ncols; row++){
00130 for(size_type col = row; col < ncols; col++){
00131 R[row][col]= B[row][col];
00132 }
00133 }
00134 return std::make_pair(Q,R);
00135 }
00136
00137 }}
00138
00139
00140 #endif // MTL_MATRIX_QR_INCLUDE
00141