Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_BIG_BACKWARD_GAUSS_SEIDEL_H
00002 #define OPENTISSUE_CORE_MATH_BIG_BACKWARD_GAUSS_SEIDEL_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/big/big_types.h>
00013 #include <OpenTissue/core/math/math_is_number.h>
00014 #include <OpenTissue/core/math/math_value_traits.h>
00015
00016 #include <stdexcept>
00017
00018 namespace OpenTissue
00019 {
00020 namespace math
00021 {
00022 namespace big
00023 {
00024
00036 template<typename T>
00037 inline void backward_gauss_seidel(
00038 boost::numeric::ublas::compressed_matrix<T> const & A
00039 , boost::numeric::ublas::vector<T> & x
00040 , boost::numeric::ublas::vector<T> const & b
00041 )
00042 {
00043 typedef boost::numeric::ublas::compressed_matrix<T> matrix_type;
00044 typedef boost::numeric::ublas::vector<T> vector_type;
00045 typedef typename vector_type::size_type size_type;
00046 typedef typename vector_type::value_type value_type;
00047 typedef OpenTissue::math::ValueTraits<T> value_traits;
00048
00049 using std::fabs;
00050
00051 if(A.size1() <= 0 || A.size2() <= 0)
00052 throw std::invalid_argument("backward_gauss_seidel(): A was empty");
00053
00054 if(b.size() != A.size1())
00055 throw std::invalid_argument("backward_gauss_seidel(): The size of b must be the same as the number of rows in A");
00056
00057 if(x.size() != A.size2())
00058 throw std::invalid_argument("backward_gauss_seidel(): The size of x must be the same as the number of columns in A");
00059
00060 size_type const N = A.filled1() - 1;
00061 for (size_type i = 0; i < N; ++i)
00062 {
00063 size_type row = N - i - 1;
00064
00065 assert( ( row >= 0 && row< N ) || !"backward_gauss_seidel::do_apply(): row index were out of range");
00066
00067 size_type begin = A.index1_data()[row];
00068 size_type end = A.index1_data()[row + 1];
00069
00070 value_type sum = b(row);
00071 value_type diag = value_traits::zero();
00072
00073 for (size_type j = begin; j < end; ++ j)
00074 {
00075 size_type const & col = A.index2_data()[j];
00076 value_type const & A_ij = A.value_data()[j];
00077
00078 assert( ( col >= 0 && col< A.size2() ) || !"backward_gauss_seidel::do_apply(): column index were out of range");
00079 assert( is_number( A_ij ) || !"backward_gauss_seidel::do_apply(): A_ij value was not a number?");
00080
00081
00082
00083 if(row==col)
00084 diag = A_ij;
00085 else
00086 sum -= A_ij * x( col );
00087 }
00088
00089 assert( fabs(diag) > value_traits::zero() || !"backward_gauss_seidel::do_apply(): Diagonal were zero");
00090 assert( is_number( sum ) || !"backward_gauss_seidel::do_apply(): sum value was not a number?");
00091 assert( is_number( diag ) || !"backward_gauss_seidel::do_apply(): diag value was not a number?");
00092 x (row) = sum / diag;
00093 assert( is_number( x(row ) ) || !"backward_gauss_seidel::do_apply(): updated value was not a number?");
00094 }
00095
00096 }
00097
00111 template<typename T>
00112 inline void backward_gauss_seidel(
00113 boost::numeric::ublas::compressed_matrix<T> const & A
00114 , boost::numeric::ublas::vector<T> & x
00115 , boost::numeric::ublas::vector<T> const & b
00116 , size_t const & max_iterations
00117 , size_t & iterations
00118 )
00119 {
00120 if(max_iterations < 1)
00121 throw std::invalid_argument("backward_gauss_seidel(): max_iterations must be a positive number");
00122
00123 iterations = 0;
00124 while(iterations<max_iterations)
00125 {
00126 ++iterations;
00127 backward_gauss_seidel(A,x,b);
00128 }
00129 }
00130
00140 class BackwardGaussSeidelFunctor
00141 {
00142 public:
00143
00144 template<typename T>
00145 void operator()(
00146 boost::numeric::ublas::compressed_matrix<T> const & A
00147 , boost::numeric::ublas::vector<T> & x
00148 , boost::numeric::ublas::vector<T> const & b
00149 , size_t const & max_iterations
00150 , size_t & iterations
00151 )
00152 {
00153 backward_gauss_seidel(A,x,b,max_iterations,iterations);
00154 }
00155
00156 template<typename T>
00157 void operator()(
00158 boost::numeric::ublas::compressed_matrix<T> const & A
00159 , boost::numeric::ublas::vector<T> & x
00160 , boost::numeric::ublas::vector<T> const & b
00161 )
00162 {
00163 backward_gauss_seidel(A,x,b);
00164 }
00165
00166 };
00167
00168 }
00169 }
00170 }
00171
00172
00173 #endif