00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef ITL_PC_DIAGONAL_INCLUDE
00013 #define ITL_PC_DIAGONAL_INCLUDE
00014
00015 #include <boost/numeric/linear_algebra/inverse.hpp>
00016
00017 #include <boost/numeric/mtl/vector/dense_vector.hpp>
00018 #include <boost/numeric/mtl/utility/exception.hpp>
00019 #include <boost/numeric/mtl/concept/collection.hpp>
00020
00021 #include <boost/numeric/itl/utility/solver_proxy.hpp>
00022
00023 namespace itl { namespace pc {
00024
00026 template <typename Matrix>
00027 class diagonal
00028 {
00029 public:
00030 typedef typename mtl::Collection<Matrix>::value_type value_type;
00031 typedef typename mtl::Collection<Matrix>::size_type size_type;
00032 typedef diagonal self;
00033
00035 explicit diagonal(const Matrix& A) : inv_diag(num_rows(A))
00036 {
00037 MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square());
00038 using math::reciprocal;
00039
00040 for (size_type i= 0; i < num_rows(A); ++i)
00041 inv_diag[i]= reciprocal(A[i][i]);
00042 }
00043
00045 template <typename Vector>
00046 Vector solve(const Vector& x) const
00047 {
00048 MTL_THROW_IF(size(x) != size(inv_diag), mtl::incompatible_size());
00049 Vector y(size(x));
00050
00051 for (size_type i= 0; i < size(inv_diag); ++i)
00052 y[i]= inv_diag[i] * x[i];
00053 return y;
00054 }
00055
00057 template <typename Vector>
00058 Vector adjoint_solve(const Vector& x) const
00059 {
00060 return solve(x);
00061 }
00062
00063 protected:
00064 mtl::dense_vector<value_type> inv_diag;
00065 };
00066
00067
00069 template <typename Matrix, typename Vector>
00070 Vector solve(const diagonal<Matrix>& P, const Vector& x)
00071 {
00072 return P.solve(x);
00073 }
00074
00076 template <typename Matrix, typename Vector>
00077 Vector adjoint_solve(const diagonal<Matrix>& P, const Vector& x)
00078 {
00079 return P.adjoint_solve(x);
00080 }
00081
00082
00083 }}
00084
00085 #endif // ITL_PC_DIAGONAL_INCLUDE