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