00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_LOWER_TRISOLVE_INCLUDE
00013 #define MTL_LOWER_TRISOLVE_INCLUDE
00014
00015 #include <boost/numeric/mtl/utility/tag.hpp>
00016 #include <boost/numeric/mtl/utility/exception.hpp>
00017 #include <boost/numeric/mtl/utility/property_map.hpp>
00018 #include <boost/numeric/mtl/utility/range_generator.hpp>
00019 #include <boost/numeric/mtl/utility/category.hpp>
00020 #include <boost/numeric/mtl/concept/collection.hpp>
00021 #include <boost/numeric/mtl/operation/adjust_cursor.hpp>
00022
00023 #include <boost/numeric/linear_algebra/identity.hpp>
00024 #include <boost/numeric/linear_algebra/inverse.hpp>
00025
00026 namespace mtl { namespace matrix {
00027
00028
00029 namespace detail {
00030
00031 template <typename Value>
00032 Value inline lower_trisolve_diavalue(const Value& v, tag::regular_diagonal)
00033 {
00034 using math::reciprocal;
00035 return reciprocal(v);
00036 }
00037
00038 template <typename Value>
00039 Value inline lower_trisolve_diavalue(const Value& v, tag::inverse_diagonal)
00040 {
00041 return v;
00042 }
00043
00044 template <typename Matrix, typename Vector>
00045 Vector inline lower_trisolve(const Matrix& A, const Vector& v, tag::row_major, tag::unit_diagonal)
00046 {
00047 namespace traits = mtl::traits;
00048 using namespace tag; using traits::range_generator; using math::one; using mtl::detail::adjust_cursor;
00049
00050 typedef typename Collection<Matrix>::value_type value_type;
00051 typedef typename Collection<Matrix>::size_type size_type;
00052 typedef typename range_generator<row, Matrix>::type a_cur_type;
00053 typedef typename range_generator<nz, a_cur_type>::type a_icur_type;
00054 typename traits::col<Matrix>::type col_a(A);
00055 typename traits::const_value<Matrix>::type value_a(A);
00056
00057 Vector result(v);
00058
00059 a_cur_type ac= begin<row>(A), aend= end<row>(A);
00060 ++ac;
00061 for (size_type r= 1; ac != aend; ++r, ++ac) {
00062 a_icur_type aic= begin<nz>(ac), aiend= lower_bound<nz>(ac, r);
00063 typename Collection<Vector>::value_type rr= result[r];
00064
00065 for (; aic != aiend; ++aic) {
00066 MTL_DEBUG_THROW_IF(col_a(*aic) >= r, logic_error("Matrix entries must be sorted for this."));
00067 rr-= value_a(*aic) * result[col_a(*aic)];
00068 }
00069 result[r]= rr;
00070 }
00071 return result;
00072 }
00073
00074
00075 template <typename Matrix, typename Vector, typename DiaTag>
00076 Vector inline lower_trisolve(const Matrix& A, const Vector& v, tag::row_major,
00077 DiaTag)
00078 {
00079 namespace traits = mtl::traits;
00080 using namespace tag; using traits::range_generator; using math::one; using mtl::detail::adjust_cursor;
00081
00082 typedef typename Collection<Matrix>::value_type value_type;
00083 typedef typename range_generator<row, Matrix>::type a_cur_type;
00084 typedef typename range_generator<nz, a_cur_type>::type a_icur_type;
00085 typename traits::col<Matrix>::type col_a(A);
00086 typename traits::const_value<Matrix>::type value_a(A);
00087
00088 Vector result(v);
00089
00090 a_cur_type ac= begin<row>(A), aend= end<row>(A);
00091 for (typename Collection<Matrix>::size_type r= 0; ac != aend; ++r, ++ac) {
00092 a_icur_type aic= begin<nz>(ac), aiend= lower_bound<nz>(ac, r+1);
00093 MTL_THROW_IF(aic == aiend || col_a(*--aiend) != r, missing_diagonal());
00094
00095 value_type dia= value_a(*aiend);
00096 typename Collection<Vector>::value_type rr= result[r];
00097
00098 for (; aic != aiend; ++aic) {
00099 MTL_DEBUG_THROW_IF(col_a(*aic) >= r, logic_error("Matrix entries must be sorted for this."));
00100 rr-= value_a(*aic) * result[col_a(*aic)];
00101 }
00102 result[r]= rr * lower_trisolve_diavalue(dia, DiaTag());
00103 }
00104 return result;
00105 }
00106
00107
00108 template <typename Matrix, typename Vector>
00109 Vector inline lower_trisolve(const Matrix& A, const Vector& v, tag::col_major, tag::unit_diagonal)
00110 {
00111 using namespace tag; using mtl::traits::range_generator; using mtl::detail::adjust_cursor;
00112
00113 typedef typename range_generator<col, Matrix>::type a_cur_type;
00114 typedef typename range_generator<nz, a_cur_type>::type a_icur_type;
00115 typename mtl::traits::row<Matrix>::type row_a(A);
00116 typename mtl::traits::const_value<Matrix>::type value_a(A);
00117
00118 Vector result(v);
00119
00120 a_cur_type ac= begin<col>(A), aend= end<col>(A);
00121 for (typename Collection<Matrix>::size_type r= 0; ac != aend; ++r, ++ac) {
00122 a_icur_type aic= lower_bound<nz>(ac, r+1), aiend= end<nz>(ac);
00123 typename Collection<Vector>::value_type rr= result[r];
00124
00125 for (; aic != aiend; ++aic) {
00126 MTL_DEBUG_THROW_IF(row_a(*aic) <= r, logic_error("Matrix entries must be sorted for this."));
00127 result[row_a(*aic)]-= value_a(*aic) * rr;
00128 }
00129 }
00130 return result;
00131 }
00132
00133 template <typename Matrix, typename Vector, typename DiaTag>
00134 Vector inline lower_trisolve(const Matrix& A, const Vector& v, tag::col_major, DiaTag)
00135 {
00136 using namespace tag; using mtl::traits::range_generator; using mtl::detail::adjust_cursor;
00137
00138 typedef typename range_generator<col, Matrix>::type a_cur_type;
00139 typedef typename range_generator<nz, a_cur_type>::type a_icur_type;
00140 typename mtl::traits::row<Matrix>::type row_a(A);
00141 typename mtl::traits::const_value<Matrix>::type value_a(A);
00142
00143 Vector result(v);
00144
00145 a_cur_type ac= begin<col>(A), aend= end<col>(A);
00146 for (typename Collection<Matrix>::size_type r= 0; ac != aend; ++r, ++ac) {
00147 a_icur_type aic= lower_bound<nz>(ac, r), aiend= end<nz>(ac);
00148 MTL_DEBUG_THROW_IF(aic == aiend || row_a(*aic) != r, missing_diagonal());
00149 typename Collection<Vector>::value_type rr= result[r]*= lower_trisolve_diavalue(value_a(*aic), DiaTag());
00150
00151 for (++aic; aic != aiend; ++aic) {
00152 MTL_DEBUG_THROW_IF(row_a(*aic) <= r, logic_error("Matrix entries must be sorted for this."));
00153 result[row_a(*aic)]-= value_a(*aic) * rr;
00154 }
00155 }
00156 return result;
00157 }
00158
00159
00160 }
00161
00162
00164 template <typename Matrix, typename Vector>
00165 Vector inline lower_trisolve(const Matrix& A, const Vector& v)
00166 {
00167 return detail::lower_trisolve(A, v, typename OrientedCollection<Matrix>::orientation(), tag::regular_diagonal());
00168 }
00170 template <typename Matrix, typename Vector>
00171 Vector inline unit_lower_trisolve(const Matrix& A, const Vector& v)
00172 {
00173 return detail::lower_trisolve(A, v, typename OrientedCollection<Matrix>::orientation(), tag::unit_diagonal());
00174 }
00176 template <typename Matrix, typename Vector>
00177 Vector inline inverse_lower_trisolve(const Matrix& A, const Vector& v)
00178 {
00179 return detail::lower_trisolve(A, v, typename OrientedCollection<Matrix>::orientation(), tag::inverse_diagonal());
00180 }
00181
00182 template <typename Matrix, typename Vector, typename DiaTag>
00183 Vector inline lower_trisolve(const Matrix& A, const Vector& v, DiaTag)
00184 {
00185 return detail::lower_trisolve(A, v, typename OrientedCollection<Matrix>::orientation(), DiaTag());
00186 }
00187
00188
00189
00190 }}
00191
00192 #endif // MTL_LOWER_TRISOLVE_INCLUDE