ViennaCL - The Vienna Computing Library
1.5.2
|
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