ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/host_based/direct_solve.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_HOST_BASED_DIRECT_SOLVE_HPP
00002 #define VIENNACL_LINALG_HOST_BASED_DIRECT_SOLVE_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #include "viennacl/vector.hpp"
00026 #include "viennacl/matrix.hpp"
00027 
00028 #include "viennacl/linalg/host_based/common.hpp"
00029 
00030 namespace viennacl
00031 {
00032   namespace linalg
00033   {
00034     namespace host_based
00035     {
00036 
00037       namespace detail
00038       {
00039         //
00040         // Upper solve:
00041         //
00042         template <typename MatrixType1, typename MatrixType2>
00043         void upper_inplace_solve_matrix(MatrixType1 & A, MatrixType2 & B, vcl_size_t A_size, vcl_size_t B_size, bool unit_diagonal)
00044         {
00045           typedef typename MatrixType2::value_type   value_type;
00046 
00047           for (vcl_size_t i = 0; i < A_size; ++i)
00048           {
00049             vcl_size_t current_row = A_size - i - 1;
00050 
00051             for (vcl_size_t j = current_row + 1; j < A_size; ++j)
00052             {
00053               value_type A_element = A(current_row, j);
00054               for (vcl_size_t k=0; k < B_size; ++k)
00055                 B(current_row, k) -= A_element * B(j, k);
00056             }
00057 
00058             if (!unit_diagonal)
00059             {
00060               value_type A_diag = A(current_row, current_row);
00061               for (vcl_size_t k=0; k < B_size; ++k)
00062                 B(current_row, k) /= A_diag;
00063             }
00064           }
00065         }
00066 
00067         template <typename MatrixType1, typename MatrixType2>
00068         void inplace_solve_matrix(MatrixType1 & A, MatrixType2 & B, vcl_size_t A_size, vcl_size_t B_size, viennacl::linalg::unit_upper_tag)
00069         {
00070           upper_inplace_solve_matrix(A, B, A_size, B_size, true);
00071         }
00072 
00073         template <typename MatrixType1, typename MatrixType2>
00074         void inplace_solve_matrix(MatrixType1 & A, MatrixType2 & B, vcl_size_t A_size, vcl_size_t B_size, viennacl::linalg::upper_tag)
00075         {
00076           upper_inplace_solve_matrix(A, B, A_size, B_size, false);
00077         }
00078 
00079         //
00080         // Lower solve:
00081         //
00082         template <typename MatrixType1, typename MatrixType2>
00083         void lower_inplace_solve_matrix(MatrixType1 & A, MatrixType2 & B, vcl_size_t A_size, vcl_size_t B_size, bool unit_diagonal)
00084         {
00085           typedef typename MatrixType2::value_type   value_type;
00086 
00087           for (vcl_size_t i = 0; i < A_size; ++i)
00088           {
00089             for (vcl_size_t j = 0; j < i; ++j)
00090             {
00091               value_type A_element = A(i, j);
00092               for (vcl_size_t k=0; k < B_size; ++k)
00093                 B(i, k) -= A_element * B(j, k);
00094             }
00095 
00096             if (!unit_diagonal)
00097             {
00098               value_type A_diag = A(i, i);
00099               for (vcl_size_t k=0; k < B_size; ++k)
00100                 B(i, k) /= A_diag;
00101             }
00102           }
00103         }
00104 
00105         template <typename MatrixType1, typename MatrixType2>
00106         void inplace_solve_matrix(MatrixType1 & A, MatrixType2 & B, vcl_size_t A_size, vcl_size_t B_size, viennacl::linalg::unit_lower_tag)
00107         {
00108           lower_inplace_solve_matrix(A, B, A_size, B_size, true);
00109         }
00110 
00111         template <typename MatrixType1, typename MatrixType2>
00112         void inplace_solve_matrix(MatrixType1 & A, MatrixType2 & B, vcl_size_t A_size, vcl_size_t B_size, viennacl::linalg::lower_tag)
00113         {
00114           lower_inplace_solve_matrix(A, B, A_size, B_size, false);
00115         }
00116 
00117       }
00118 
00119       //
00120       // Note: By convention, all size checks are performed in the calling frontend. No need to double-check here.
00121       //
00122 
00124 
00129       template <typename NumericT, typename F1, typename F2, typename SOLVERTAG>
00130       void inplace_solve(const matrix_base<NumericT, F1> & A, matrix_base<NumericT, F2> & B, SOLVERTAG)
00131       {
00132         typedef NumericT        value_type;
00133 
00134         value_type const * data_A = detail::extract_raw_pointer<value_type>(A);
00135         value_type       * data_B = detail::extract_raw_pointer<value_type>(B);
00136 
00137         vcl_size_t A_start1 = viennacl::traits::start1(A);
00138         vcl_size_t A_start2 = viennacl::traits::start2(A);
00139         vcl_size_t A_inc1   = viennacl::traits::stride1(A);
00140         vcl_size_t A_inc2   = viennacl::traits::stride2(A);
00141         vcl_size_t A_size2  = viennacl::traits::size2(A);
00142         vcl_size_t A_internal_size1  = viennacl::traits::internal_size1(A);
00143         vcl_size_t A_internal_size2  = viennacl::traits::internal_size2(A);
00144 
00145         vcl_size_t B_start1 = viennacl::traits::start1(B);
00146         vcl_size_t B_start2 = viennacl::traits::start2(B);
00147         vcl_size_t B_inc1   = viennacl::traits::stride1(B);
00148         vcl_size_t B_inc2   = viennacl::traits::stride2(B);
00149         vcl_size_t B_size2  = viennacl::traits::size2(B);
00150         vcl_size_t B_internal_size1  = viennacl::traits::internal_size1(B);
00151         vcl_size_t B_internal_size2  = viennacl::traits::internal_size2(B);
00152 
00153 
00154         detail::matrix_array_wrapper<value_type const, typename F1::orientation_category, false>   wrapper_A(data_A, A_start1, A_start2, A_inc1, A_inc2, A_internal_size1, A_internal_size2);
00155         detail::matrix_array_wrapper<value_type,       typename F2::orientation_category, false>   wrapper_B(data_B, B_start1, B_start2, B_inc1, B_inc2, B_internal_size1, B_internal_size2);
00156 
00157         detail::inplace_solve_matrix(wrapper_A, wrapper_B, A_size2, B_size2, SOLVERTAG());
00158       }
00159 
00165       template <typename NumericT, typename F1, typename F2, typename SOLVERTAG>
00166       void inplace_solve(const matrix_base<NumericT, F1> & A,
00167                          matrix_expression< const matrix_base<NumericT, F2>, const matrix_base<NumericT, F2>, op_trans> proxy_B,
00168                          SOLVERTAG)
00169       {
00170         typedef NumericT        value_type;
00171 
00172         value_type const * data_A = detail::extract_raw_pointer<value_type>(A);
00173         value_type       * data_B = const_cast<value_type *>(detail::extract_raw_pointer<value_type>(proxy_B.lhs()));
00174 
00175         vcl_size_t A_start1 = viennacl::traits::start1(A);
00176         vcl_size_t A_start2 = viennacl::traits::start2(A);
00177         vcl_size_t A_inc1   = viennacl::traits::stride1(A);
00178         vcl_size_t A_inc2   = viennacl::traits::stride2(A);
00179         vcl_size_t A_size2  = viennacl::traits::size2(A);
00180         vcl_size_t A_internal_size1  = viennacl::traits::internal_size1(A);
00181         vcl_size_t A_internal_size2  = viennacl::traits::internal_size2(A);
00182 
00183         vcl_size_t B_start1 = viennacl::traits::start1(proxy_B.lhs());
00184         vcl_size_t B_start2 = viennacl::traits::start2(proxy_B.lhs());
00185         vcl_size_t B_inc1   = viennacl::traits::stride1(proxy_B.lhs());
00186         vcl_size_t B_inc2   = viennacl::traits::stride2(proxy_B.lhs());
00187         vcl_size_t B_size1  = viennacl::traits::size1(proxy_B.lhs());
00188         vcl_size_t B_internal_size1  = viennacl::traits::internal_size1(proxy_B.lhs());
00189         vcl_size_t B_internal_size2  = viennacl::traits::internal_size2(proxy_B.lhs());
00190 
00191 
00192         detail::matrix_array_wrapper<value_type const, typename F1::orientation_category, false>   wrapper_A(data_A, A_start1, A_start2, A_inc1, A_inc2, A_internal_size1, A_internal_size2);
00193         detail::matrix_array_wrapper<value_type,       typename F2::orientation_category, true>   wrapper_B(data_B, B_start1, B_start2, B_inc1, B_inc2, B_internal_size1, B_internal_size2);
00194 
00195         detail::inplace_solve_matrix(wrapper_A, wrapper_B, A_size2, B_size1, SOLVERTAG());
00196       }
00197 
00198       //upper triangular solver for transposed lower triangular matrices
00204       template <typename NumericT, typename F1, typename F2, typename SOLVERTAG>
00205       void inplace_solve(const matrix_expression< const matrix_base<NumericT, F1>, const matrix_base<NumericT, F1>, op_trans> & proxy_A,
00206                          matrix_base<NumericT, F2> & B,
00207                          SOLVERTAG)
00208       {
00209         typedef NumericT        value_type;
00210 
00211         value_type const * data_A = detail::extract_raw_pointer<value_type>(proxy_A.lhs());
00212         value_type       * data_B = const_cast<value_type *>(detail::extract_raw_pointer<value_type>(B));
00213 
00214         vcl_size_t A_start1 = viennacl::traits::start1(proxy_A.lhs());
00215         vcl_size_t A_start2 = viennacl::traits::start2(proxy_A.lhs());
00216         vcl_size_t A_inc1   = viennacl::traits::stride1(proxy_A.lhs());
00217         vcl_size_t A_inc2   = viennacl::traits::stride2(proxy_A.lhs());
00218         vcl_size_t A_size2  = viennacl::traits::size2(proxy_A.lhs());
00219         vcl_size_t A_internal_size1  = viennacl::traits::internal_size1(proxy_A.lhs());
00220         vcl_size_t A_internal_size2  = viennacl::traits::internal_size2(proxy_A.lhs());
00221 
00222         vcl_size_t B_start1 = viennacl::traits::start1(B);
00223         vcl_size_t B_start2 = viennacl::traits::start2(B);
00224         vcl_size_t B_inc1   = viennacl::traits::stride1(B);
00225         vcl_size_t B_inc2   = viennacl::traits::stride2(B);
00226         vcl_size_t B_size2  = viennacl::traits::size2(B);
00227         vcl_size_t B_internal_size1  = viennacl::traits::internal_size1(B);
00228         vcl_size_t B_internal_size2  = viennacl::traits::internal_size2(B);
00229 
00230 
00231         detail::matrix_array_wrapper<value_type const, typename F1::orientation_category, true>    wrapper_A(data_A, A_start1, A_start2, A_inc1, A_inc2, A_internal_size1, A_internal_size2);
00232         detail::matrix_array_wrapper<value_type,       typename F2::orientation_category, false>   wrapper_B(data_B, B_start1, B_start2, B_inc1, B_inc2, B_internal_size1, B_internal_size2);
00233 
00234         detail::inplace_solve_matrix(wrapper_A, wrapper_B, A_size2, B_size2, SOLVERTAG());
00235       }
00236 
00242       template <typename NumericT, typename F1, typename F2, typename SOLVERTAG>
00243       void inplace_solve(const matrix_expression< const matrix_base<NumericT, F1>, const matrix_base<NumericT, F1>, op_trans> & proxy_A,
00244                                matrix_expression< const matrix_base<NumericT, F2>, const matrix_base<NumericT, F2>, op_trans>   proxy_B,
00245                          SOLVERTAG)
00246       {
00247         typedef NumericT        value_type;
00248 
00249         value_type const * data_A = detail::extract_raw_pointer<value_type>(proxy_A.lhs());
00250         value_type       * data_B = const_cast<value_type *>(detail::extract_raw_pointer<value_type>(proxy_B.lhs()));
00251 
00252         vcl_size_t A_start1 = viennacl::traits::start1(proxy_A.lhs());
00253         vcl_size_t A_start2 = viennacl::traits::start2(proxy_A.lhs());
00254         vcl_size_t A_inc1   = viennacl::traits::stride1(proxy_A.lhs());
00255         vcl_size_t A_inc2   = viennacl::traits::stride2(proxy_A.lhs());
00256         vcl_size_t A_size2  = viennacl::traits::size2(proxy_A.lhs());
00257         vcl_size_t A_internal_size1  = viennacl::traits::internal_size1(proxy_A.lhs());
00258         vcl_size_t A_internal_size2  = viennacl::traits::internal_size2(proxy_A.lhs());
00259 
00260         vcl_size_t B_start1 = viennacl::traits::start1(proxy_B.lhs());
00261         vcl_size_t B_start2 = viennacl::traits::start2(proxy_B.lhs());
00262         vcl_size_t B_inc1   = viennacl::traits::stride1(proxy_B.lhs());
00263         vcl_size_t B_inc2   = viennacl::traits::stride2(proxy_B.lhs());
00264         vcl_size_t B_size1  = viennacl::traits::size1(proxy_B.lhs());
00265         vcl_size_t B_internal_size1  = viennacl::traits::internal_size1(proxy_B.lhs());
00266         vcl_size_t B_internal_size2  = viennacl::traits::internal_size2(proxy_B.lhs());
00267 
00268 
00269         detail::matrix_array_wrapper<value_type const, typename F1::orientation_category, true>   wrapper_A(data_A, A_start1, A_start2, A_inc1, A_inc2, A_internal_size1, A_internal_size2);
00270         detail::matrix_array_wrapper<value_type,       typename F2::orientation_category, true>   wrapper_B(data_B, B_start1, B_start2, B_inc1, B_inc2, B_internal_size1, B_internal_size2);
00271 
00272         detail::inplace_solve_matrix(wrapper_A, wrapper_B, A_size2, B_size1, SOLVERTAG());
00273       }
00274 
00275       //
00276       //  Solve on vector
00277       //
00278 
00279       namespace detail
00280       {
00281         //
00282         // Upper solve:
00283         //
00284         template <typename MatrixType, typename VectorType>
00285         void upper_inplace_solve_vector(MatrixType & A, VectorType & b, vcl_size_t A_size, bool unit_diagonal)
00286         {
00287           typedef typename VectorType::value_type   value_type;
00288 
00289           for (vcl_size_t i = 0; i < A_size; ++i)
00290           {
00291             vcl_size_t current_row = A_size - i - 1;
00292 
00293             for (vcl_size_t j = current_row + 1; j < A_size; ++j)
00294             {
00295               value_type A_element = A(current_row, j);
00296               b(current_row) -= A_element * b(j);
00297             }
00298 
00299             if (!unit_diagonal)
00300               b(current_row) /= A(current_row, current_row);
00301           }
00302         }
00303 
00304         template <typename MatrixType, typename VectorType>
00305         void inplace_solve_vector(MatrixType & A, VectorType & b, vcl_size_t A_size, viennacl::linalg::unit_upper_tag)
00306         {
00307           upper_inplace_solve_vector(A, b, A_size, true);
00308         }
00309 
00310         template <typename MatrixType, typename VectorType>
00311         void inplace_solve_vector(MatrixType & A, VectorType & b, vcl_size_t A_size, viennacl::linalg::upper_tag)
00312         {
00313           upper_inplace_solve_vector(A, b, A_size, false);
00314         }
00315 
00316         //
00317         // Lower solve:
00318         //
00319         template <typename MatrixType, typename VectorType>
00320         void lower_inplace_solve_vector(MatrixType & A, VectorType & b, vcl_size_t A_size, bool unit_diagonal)
00321         {
00322           typedef typename VectorType::value_type   value_type;
00323 
00324           for (vcl_size_t i = 0; i < A_size; ++i)
00325           {
00326             for (vcl_size_t j = 0; j < i; ++j)
00327             {
00328               value_type A_element = A(i, j);
00329               b(i) -= A_element * b(j);
00330             }
00331 
00332             if (!unit_diagonal)
00333               b(i) /= A(i, i);
00334           }
00335         }
00336 
00337         template <typename MatrixType, typename VectorType>
00338         void inplace_solve_vector(MatrixType & A, VectorType & b, vcl_size_t A_size, viennacl::linalg::unit_lower_tag)
00339         {
00340           lower_inplace_solve_vector(A, b, A_size, true);
00341         }
00342 
00343         template <typename MatrixType, typename VectorType>
00344         void inplace_solve_vector(MatrixType & A, VectorType & b, vcl_size_t A_size, viennacl::linalg::lower_tag)
00345         {
00346           lower_inplace_solve_vector(A, b, A_size, false);
00347         }
00348 
00349       }
00350 
00351       template <typename NumericT, typename F, typename SOLVERTAG>
00352       void inplace_solve(const matrix_base<NumericT, F> & mat,
00353                                vector_base<NumericT> & vec,
00354                          SOLVERTAG)
00355       {
00356         typedef NumericT        value_type;
00357 
00358         value_type const * data_A = detail::extract_raw_pointer<value_type>(mat);
00359         value_type       * data_v = detail::extract_raw_pointer<value_type>(vec);
00360 
00361         vcl_size_t A_start1 = viennacl::traits::start1(mat);
00362         vcl_size_t A_start2 = viennacl::traits::start2(mat);
00363         vcl_size_t A_inc1   = viennacl::traits::stride1(mat);
00364         vcl_size_t A_inc2   = viennacl::traits::stride2(mat);
00365         vcl_size_t A_size2  = viennacl::traits::size2(mat);
00366         vcl_size_t A_internal_size1  = viennacl::traits::internal_size1(mat);
00367         vcl_size_t A_internal_size2  = viennacl::traits::internal_size2(mat);
00368 
00369         vcl_size_t start1 = viennacl::traits::start(vec);
00370         vcl_size_t inc1   = viennacl::traits::stride(vec);
00371 
00372         detail::matrix_array_wrapper<value_type const, typename F::orientation_category, false>   wrapper_A(data_A, A_start1, A_start2, A_inc1, A_inc2, A_internal_size1, A_internal_size2);
00373         detail::vector_array_wrapper<value_type> wrapper_v(data_v, start1, inc1);
00374 
00375         detail::inplace_solve_vector(wrapper_A, wrapper_v, A_size2, SOLVERTAG());
00376       }
00377 
00378 
00379 
00385       template <typename NumericT, typename F, typename SOLVERTAG>
00386       void inplace_solve(const matrix_expression< const matrix_base<NumericT, F>, const matrix_base<NumericT, F>, op_trans> & proxy,
00387                          vector_base<NumericT> & vec,
00388                          SOLVERTAG)
00389       {
00390         typedef NumericT        value_type;
00391 
00392         value_type const * data_A = detail::extract_raw_pointer<value_type>(proxy.lhs());
00393         value_type       * data_v = detail::extract_raw_pointer<value_type>(vec);
00394 
00395         vcl_size_t A_start1 = viennacl::traits::start1(proxy.lhs());
00396         vcl_size_t A_start2 = viennacl::traits::start2(proxy.lhs());
00397         vcl_size_t A_inc1   = viennacl::traits::stride1(proxy.lhs());
00398         vcl_size_t A_inc2   = viennacl::traits::stride2(proxy.lhs());
00399         vcl_size_t A_size2  = viennacl::traits::size2(proxy.lhs());
00400         vcl_size_t A_internal_size1  = viennacl::traits::internal_size1(proxy.lhs());
00401         vcl_size_t A_internal_size2  = viennacl::traits::internal_size2(proxy.lhs());
00402 
00403         vcl_size_t start1 = viennacl::traits::start(vec);
00404         vcl_size_t inc1   = viennacl::traits::stride(vec);
00405 
00406         detail::matrix_array_wrapper<value_type const, typename F::orientation_category, true>   wrapper_A(data_A, A_start1, A_start2, A_inc1, A_inc2, A_internal_size1, A_internal_size2);
00407         detail::vector_array_wrapper<value_type> wrapper_v(data_v, start1, inc1);
00408 
00409         detail::inplace_solve_vector(wrapper_A, wrapper_v, A_size2, SOLVERTAG());
00410       }
00411 
00412 
00413 
00414     }
00415   }
00416 }
00417 
00418 #endif