ViennaCL - The Vienna Computing Library
1.5.0
|
00001 #ifndef VIENNACL_LINALG_QR_HPP 00002 #define VIENNACL_LINALG_QR_HPP 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2013, 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 <utility> 00026 #include <iostream> 00027 #include <fstream> 00028 #include <string> 00029 #include <algorithm> 00030 #include <vector> 00031 #include <math.h> 00032 #include <cmath> 00033 #include "boost/numeric/ublas/vector.hpp" 00034 #include "boost/numeric/ublas/matrix.hpp" 00035 #include "boost/numeric/ublas/matrix_proxy.hpp" 00036 #include "boost/numeric/ublas/vector_proxy.hpp" 00037 #include "boost/numeric/ublas/io.hpp" 00038 #include "boost/numeric/ublas/matrix_expression.hpp" 00039 00040 #include "viennacl/matrix.hpp" 00041 #include "viennacl/matrix_proxy.hpp" 00042 #include "viennacl/linalg/prod.hpp" 00043 #include "viennacl/range.hpp" 00044 00045 namespace viennacl 00046 { 00047 namespace linalg 00048 { 00049 namespace detail 00050 { 00051 00052 template <typename MatrixType, typename VectorType> 00053 typename MatrixType::value_type setup_householder_vector_ublas(MatrixType const & A, VectorType & v, MatrixType & matrix_1x1, vcl_size_t j) 00054 { 00055 using boost::numeric::ublas::range; 00056 using boost::numeric::ublas::project; 00057 00058 typedef typename MatrixType::value_type ScalarType; 00059 00060 //compute norm of column below diagonal: 00061 matrix_1x1 = boost::numeric::ublas::prod( trans(project(A, range(j+1, A.size1()), range(j, j+1))), 00062 project(A, range(j+1, A.size1()), range(j, j+1)) 00063 ); 00064 ScalarType sigma = matrix_1x1(0,0); 00065 ScalarType beta = 0; 00066 ScalarType A_jj = A(j,j); 00067 00068 assert( sigma >= 0.0 && bool("sigma must be non-negative!")); 00069 00070 //get v from A: 00071 v(j,0) = 1.0; 00072 project(v, range(j+1, A.size1()), range(0,1)) = project(A, range(j+1, A.size1()), range(j,j+1)); 00073 00074 if (sigma == 0) 00075 return 0; 00076 else 00077 { 00078 ScalarType mu = std::sqrt(sigma + A_jj*A_jj); 00079 00080 ScalarType v1 = (A_jj <= 0) ? (A_jj - mu) : (-sigma / (A_jj + mu)); 00081 beta = static_cast<ScalarType>(2.0) * v1 * v1 / (sigma + v1 * v1); 00082 00083 //divide v by its diagonal element v[j] 00084 project(v, range(j+1, A.size1()), range(0,1)) /= v1; 00085 } 00086 00087 return beta; 00088 } 00089 00090 00091 template <typename MatrixType, typename VectorType> 00092 typename viennacl::result_of::cpu_value_type< typename MatrixType::value_type >::type 00093 setup_householder_vector_viennacl(MatrixType const & A, VectorType & v, MatrixType & matrix_1x1, vcl_size_t j) 00094 { 00095 using viennacl::range; 00096 using viennacl::project; 00097 00098 typedef typename viennacl::result_of::cpu_value_type< typename MatrixType::value_type >::type ScalarType; 00099 00100 //compute norm of column below diagonal: 00101 matrix_1x1 = viennacl::linalg::prod( trans(project(A, range(j+1, A.size1()), range(j, j+1))), 00102 project(A, range(j+1, A.size1()), range(j, j+1)) 00103 ); 00104 ScalarType sigma = matrix_1x1(0,0); 00105 ScalarType beta = 0; 00106 ScalarType A_jj = A(j,j); 00107 00108 assert( sigma >= 0.0 && bool("sigma must be non-negative!")); 00109 00110 //get v from A: 00111 v(j,0) = 1.0; 00112 project(v, range(j+1, A.size1()), range(0,1)) = project(A, range(j+1, A.size1()), range(j,j+1)); 00113 00114 if (sigma == 0) 00115 return 0; 00116 else 00117 { 00118 ScalarType mu = std::sqrt(sigma + A_jj*A_jj); 00119 00120 ScalarType v1 = (A_jj <= 0) ? (A_jj - mu) : (-sigma / (A_jj + mu)); 00121 00122 beta = 2.0 * v1 * v1 / (sigma + v1 * v1); 00123 00124 //divide v by its diagonal element v[j] 00125 project(v, range(j+1, A.size1()), range(0,1)) /= v1; 00126 } 00127 00128 return beta; 00129 } 00130 00131 00132 // Apply (I - beta v v^T) to the k-th column of A, where v is the reflector starting at j-th row/column 00133 template <typename MatrixType, typename VectorType, typename ScalarType> 00134 void householder_reflect(MatrixType & A, VectorType & v, ScalarType beta, vcl_size_t j, vcl_size_t k) 00135 { 00136 ScalarType v_in_col = A(j,k); 00137 for (vcl_size_t i=j+1; i<A.size1(); ++i) 00138 v_in_col += v[i] * A(i,k); 00139 00140 //assert(v[j] == 1.0); 00141 00142 for (vcl_size_t i=j; i<A.size1(); ++i) 00143 A(i,k) -= beta * v_in_col * v[i]; 00144 } 00145 00146 template <typename MatrixType, typename VectorType, typename ScalarType> 00147 void householder_reflect_ublas(MatrixType & A, VectorType & v, MatrixType & matrix_1x1, ScalarType beta, vcl_size_t j, vcl_size_t k) 00148 { 00149 using boost::numeric::ublas::range; 00150 using boost::numeric::ublas::project; 00151 00152 ScalarType v_in_col = A(j,k); 00153 matrix_1x1 = boost::numeric::ublas::prod(trans(project(v, range(j+1, A.size1()), range(0, 1))), 00154 project(A, range(j+1, A.size1()), range(k,k+1))); 00155 v_in_col += matrix_1x1(0,0); 00156 00157 project(A, range(j, A.size1()), range(k, k+1)) -= (beta * v_in_col) * project(v, range(j, A.size1()), range(0, 1)); 00158 } 00159 00160 template <typename MatrixType, typename VectorType, typename ScalarType> 00161 void householder_reflect_viennacl(MatrixType & A, VectorType & v, MatrixType & matrix_1x1, ScalarType beta, vcl_size_t j, vcl_size_t k) 00162 { 00163 using viennacl::range; 00164 using viennacl::project; 00165 00166 ScalarType v_in_col = A(j,k); 00167 00168 matrix_1x1 = viennacl::linalg::prod(trans(project(v, range(j+1, A.size1()), range(0, 1))), 00169 project(A, range(j+1, A.size1()), range(k,k+1))); 00170 v_in_col += matrix_1x1(0,0); 00171 00172 if ( beta * v_in_col != 0.0) 00173 { 00174 VectorType temp = project(v, range(j, A.size1()), range(0, 1)); 00175 project(v, range(j, A.size1()), range(0, 1)) *= (beta * v_in_col); 00176 project(A, range(j, A.size1()), range(k, k+1)) -= project(v, range(j, A.size1()), range(0, 1)); 00177 project(v, range(j, A.size1()), range(0, 1)) = temp; 00178 } 00179 } 00180 00181 00182 // Apply (I - beta v v^T) to A, where v is the reflector starting at j-th row/column 00183 template <typename MatrixType, typename VectorType, typename ScalarType> 00184 void householder_reflect(MatrixType & A, VectorType & v, ScalarType beta, vcl_size_t j) 00185 { 00186 vcl_size_t column_end = A.size2(); 00187 00188 for (vcl_size_t k=j; k<column_end; ++k) //over columns 00189 householder_reflect(A, v, beta, j, k); 00190 } 00191 00192 00193 template <typename MatrixType, typename VectorType> 00194 void write_householder_to_A(MatrixType & A, VectorType const & v, vcl_size_t j) 00195 { 00196 for (vcl_size_t i=j+1; i<A.size1(); ++i) 00197 A(i,j) = v[i]; 00198 } 00199 00200 template <typename MatrixType, typename VectorType> 00201 void write_householder_to_A_ublas(MatrixType & A, VectorType const & v, vcl_size_t j) 00202 { 00203 using boost::numeric::ublas::range; 00204 using boost::numeric::ublas::project; 00205 00206 //VectorType temp = project(v, range(j+1, A.size1())); 00207 project( A, range(j+1, A.size1()), range(j, j+1) ) = project(v, range(j+1, A.size1()), range(0, 1) );; 00208 } 00209 00210 template <typename MatrixType, typename VectorType> 00211 void write_householder_to_A_viennacl(MatrixType & A, VectorType const & v, vcl_size_t j) 00212 { 00213 using viennacl::range; 00214 using viennacl::project; 00215 00216 //VectorType temp = project(v, range(j+1, A.size1())); 00217 project( A, range(j+1, A.size1()), range(j, j+1) ) = project(v, range(j+1, A.size1()), range(0, 1) );; 00218 } 00219 00220 00221 00227 template<typename MatrixType> 00228 std::vector<typename MatrixType::value_type> inplace_qr_ublas(MatrixType & A, vcl_size_t block_size = 32) 00229 { 00230 typedef typename MatrixType::value_type ScalarType; 00231 typedef boost::numeric::ublas::matrix_range<MatrixType> MatrixRange; 00232 00233 using boost::numeric::ublas::range; 00234 using boost::numeric::ublas::project; 00235 00236 std::vector<ScalarType> betas(A.size2()); 00237 MatrixType v(A.size1(), 1); 00238 MatrixType matrix_1x1(1,1); 00239 00240 MatrixType Y(A.size1(), block_size); Y.clear(); Y.resize(A.size1(), block_size); 00241 MatrixType W(A.size1(), block_size); W.clear(); W.resize(A.size1(), block_size); 00242 00243 //run over A in a block-wise manner: 00244 for (vcl_size_t j = 0; j < std::min(A.size1(), A.size2()); j += block_size) 00245 { 00246 vcl_size_t effective_block_size = std::min(std::min(A.size1(), A.size2()), j+block_size) - j; 00247 00248 //determine Householder vectors: 00249 for (vcl_size_t k = 0; k < effective_block_size; ++k) 00250 { 00251 betas[j+k] = detail::setup_householder_vector_ublas(A, v, matrix_1x1, j+k); 00252 00253 for (vcl_size_t l = k; l < effective_block_size; ++l) 00254 detail::householder_reflect_ublas(A, v, matrix_1x1, betas[j+k], j+k, j+l); 00255 00256 detail::write_householder_to_A_ublas(A, v, j+k); 00257 } 00258 00259 // 00260 // Setup Y: 00261 // 00262 Y.clear(); Y.resize(A.size1(), block_size); 00263 for (vcl_size_t k = 0; k < effective_block_size; ++k) 00264 { 00265 //write Householder to Y: 00266 Y(j+k,k) = 1.0; 00267 project(Y, range(j+k+1, A.size1()), range(k, k+1)) = project(A, range(j+k+1, A.size1()), range(j+k, j+k+1)); 00268 } 00269 00270 // 00271 // Setup W: 00272 // 00273 00274 //first vector: 00275 W.clear(); W.resize(A.size1(), block_size); 00276 W(j, 0) = -betas[j]; 00277 project(W, range(j+1, A.size1()), range(0, 1)) = -betas[j] * project(A, range(j+1, A.size1()), range(j, j+1)); 00278 00279 00280 //k-th column of W is given by -beta * (Id + W*Y^T) v_k, where W and Y have k-1 columns 00281 for (vcl_size_t k = 1; k < effective_block_size; ++k) 00282 { 00283 MatrixRange Y_old = project(Y, range(j, A.size1()), range(0, k)); 00284 MatrixRange v_k = project(Y, range(j, A.size1()), range(k, k+1)); 00285 MatrixRange W_old = project(W, range(j, A.size1()), range(0, k)); 00286 MatrixRange z = project(W, range(j, A.size1()), range(k, k+1)); 00287 00288 MatrixType YT_prod_v = boost::numeric::ublas::prod(boost::numeric::ublas::trans(Y_old), v_k); 00289 z = - betas[j+k] * (v_k + prod(W_old, YT_prod_v)); 00290 } 00291 00292 // 00293 //apply (I+WY^T)^T = I + Y W^T to the remaining columns of A: 00294 // 00295 00296 if (A.size2() - j - effective_block_size > 0) 00297 { 00298 00299 MatrixRange A_part(A, range(j, A.size1()), range(j+effective_block_size, A.size2())); 00300 MatrixRange W_part(W, range(j, A.size1()), range(0, effective_block_size)); 00301 MatrixType temp = boost::numeric::ublas::prod(trans(W_part), A_part); 00302 00303 A_part += prod(project(Y, range(j, A.size1()), range(0, Y.size2())), 00304 temp); 00305 } 00306 } 00307 00308 return betas; 00309 } 00310 00311 00320 template<typename MatrixType> 00321 std::vector< typename viennacl::result_of::cpu_value_type< typename MatrixType::value_type >::type > 00322 inplace_qr_viennacl(MatrixType & A, vcl_size_t block_size = 16) 00323 { 00324 typedef typename viennacl::result_of::cpu_value_type< typename MatrixType::value_type >::type ScalarType; 00325 typedef viennacl::matrix_range<MatrixType> MatrixRange; 00326 00327 using viennacl::range; 00328 using viennacl::project; 00329 00330 std::vector<ScalarType> betas(A.size2()); 00331 MatrixType v(A.size1(), 1); 00332 MatrixType matrix_1x1(1,1); 00333 00334 MatrixType Y(A.size1(), block_size); Y.clear(); 00335 MatrixType W(A.size1(), block_size); W.clear(); 00336 00337 MatrixType YT_prod_v(block_size, 1); 00338 MatrixType z(A.size1(), 1); 00339 00340 //run over A in a block-wise manner: 00341 for (vcl_size_t j = 0; j < std::min(A.size1(), A.size2()); j += block_size) 00342 { 00343 vcl_size_t effective_block_size = std::min(std::min(A.size1(), A.size2()), j+block_size) - j; 00344 00345 //determine Householder vectors: 00346 for (vcl_size_t k = 0; k < effective_block_size; ++k) 00347 { 00348 betas[j+k] = detail::setup_householder_vector_viennacl(A, v, matrix_1x1, j+k); 00349 for (vcl_size_t l = k; l < effective_block_size; ++l) 00350 detail::householder_reflect_viennacl(A, v, matrix_1x1, betas[j+k], j+k, j+l); 00351 00352 detail::write_householder_to_A_viennacl(A, v, j+k); 00353 } 00354 00355 // 00356 // Setup Y: 00357 // 00358 Y.clear(); 00359 for (vcl_size_t k = 0; k < effective_block_size; ++k) 00360 { 00361 //write Householder to Y: 00362 Y(j+k,k) = 1.0; 00363 project(Y, range(j+k+1, A.size1()), range(k, k+1)) = project(A, range(j+k+1, A.size1()), range(j+k, j+k+1)); 00364 } 00365 00366 // 00367 // Setup W: 00368 // 00369 00370 //first vector: 00371 W.clear(); 00372 W(j, 0) = -betas[j]; 00373 //project(W, range(j+1, A.size1()), range(0, 1)) = -betas[j] * project(A, range(j+1, A.size1()), range(j, j+1)); 00374 project(W, range(j+1, A.size1()), range(0, 1)) = project(A, range(j+1, A.size1()), range(j, j+1)); 00375 project(W, range(j+1, A.size1()), range(0, 1)) *= -betas[j]; 00376 00377 00378 //k-th column of W is given by -beta * (Id + W*Y^T) v_k, where W and Y have k-1 columns 00379 for (vcl_size_t k = 1; k < effective_block_size; ++k) 00380 { 00381 MatrixRange Y_old = project(Y, range(j, A.size1()), range(0, k)); 00382 MatrixRange v_k = project(Y, range(j, A.size1()), range(k, k+1)); 00383 MatrixRange W_old = project(W, range(j, A.size1()), range(0, k)); 00384 00385 project(YT_prod_v, range(0, k), range(0,1)) = prod(trans(Y_old), v_k); 00386 project(z, range(j, A.size1()), range(0,1)) = prod(W_old, project(YT_prod_v, range(0, k), range(0,1))); 00387 project(W, range(j, A.size1()), range(k, k+1)) = project(z, range(j, A.size1()), range(0,1)); 00388 project(W, range(j, A.size1()), range(k, k+1)) += v_k; 00389 project(W, range(j, A.size1()), range(k, k+1)) *= - betas[j+k]; 00390 } 00391 00392 // 00393 //apply (I+WY^T)^T = I + Y W^T to the remaining columns of A: 00394 // 00395 00396 if (A.size2() > j + effective_block_size) 00397 { 00398 00399 MatrixRange A_part(A, range(j, A.size1()), range(j+effective_block_size, A.size2())); 00400 MatrixRange W_part(W, range(j, A.size1()), range(0, effective_block_size)); 00401 MatrixType temp = prod(trans(W_part), A_part); 00402 00403 A_part += prod(project(Y, range(j, A.size1()), range(0, Y.size2())), 00404 temp); 00405 } 00406 } 00407 00408 return betas; 00409 } 00410 00411 00412 00413 00414 00415 00416 //MatrixType is ViennaCL-matrix 00424 template<typename MatrixType> 00425 std::vector< typename viennacl::result_of::cpu_value_type< typename MatrixType::value_type >::type > 00426 inplace_qr_hybrid(MatrixType & A, vcl_size_t block_size = 16) 00427 { 00428 typedef typename viennacl::result_of::cpu_value_type< typename MatrixType::value_type >::type ScalarType; 00429 00430 typedef viennacl::matrix_range<MatrixType> VCLMatrixRange; 00431 typedef boost::numeric::ublas::matrix<ScalarType> UblasMatrixType; 00432 typedef boost::numeric::ublas::matrix_range<UblasMatrixType> UblasMatrixRange; 00433 00434 std::vector<ScalarType> betas(A.size2()); 00435 UblasMatrixType v(A.size1(), 1); 00436 UblasMatrixType matrix_1x1(1,1); 00437 00438 UblasMatrixType ublasW(A.size1(), block_size); ublasW.clear(); ublasW.resize(A.size1(), block_size); 00439 UblasMatrixType ublasY(A.size1(), block_size); ublasY.clear(); ublasY.resize(A.size1(), block_size); 00440 00441 UblasMatrixType ublasA(A.size1(), A.size1()); 00442 00443 MatrixType vclW(ublasW.size1(), ublasW.size2()); 00444 MatrixType vclY(ublasY.size1(), ublasY.size2()); 00445 00446 00447 //run over A in a block-wise manner: 00448 for (vcl_size_t j = 0; j < std::min(A.size1(), A.size2()); j += block_size) 00449 { 00450 vcl_size_t effective_block_size = std::min(std::min(A.size1(), A.size2()), j+block_size) - j; 00451 UblasMatrixRange ublasA_part = boost::numeric::ublas::project(ublasA, 00452 boost::numeric::ublas::range(0, A.size1()), 00453 boost::numeric::ublas::range(j, j + effective_block_size)); 00454 viennacl::copy(viennacl::project(A, 00455 viennacl::range(0, A.size1()), 00456 viennacl::range(j, j+effective_block_size)), 00457 ublasA_part 00458 ); 00459 00460 //determine Householder vectors: 00461 for (vcl_size_t k = 0; k < effective_block_size; ++k) 00462 { 00463 betas[j+k] = detail::setup_householder_vector_ublas(ublasA, v, matrix_1x1, j+k); 00464 00465 for (vcl_size_t l = k; l < effective_block_size; ++l) 00466 detail::householder_reflect_ublas(ublasA, v, matrix_1x1, betas[j+k], j+k, j+l); 00467 00468 detail::write_householder_to_A_ublas(ublasA, v, j+k); 00469 } 00470 00471 // 00472 // Setup Y: 00473 // 00474 ublasY.clear(); ublasY.resize(A.size1(), block_size); 00475 for (vcl_size_t k = 0; k < effective_block_size; ++k) 00476 { 00477 //write Householder to Y: 00478 ublasY(j+k,k) = 1.0; 00479 boost::numeric::ublas::project(ublasY, 00480 boost::numeric::ublas::range(j+k+1, A.size1()), 00481 boost::numeric::ublas::range(k, k+1)) 00482 = boost::numeric::ublas::project(ublasA, 00483 boost::numeric::ublas::range(j+k+1, A.size1()), 00484 boost::numeric::ublas::range(j+k, j+k+1)); 00485 } 00486 00487 // 00488 // Setup W: 00489 // 00490 00491 //first vector: 00492 ublasW.clear(); ublasW.resize(A.size1(), block_size); 00493 ublasW(j, 0) = -betas[j]; 00494 boost::numeric::ublas::project(ublasW, 00495 boost::numeric::ublas::range(j+1, A.size1()), 00496 boost::numeric::ublas::range(0, 1)) 00497 = -betas[j] * boost::numeric::ublas::project(ublasA, 00498 boost::numeric::ublas::range(j+1, A.size1()), 00499 boost::numeric::ublas::range(j, j+1)); 00500 00501 00502 //k-th column of W is given by -beta * (Id + W*Y^T) v_k, where W and Y have k-1 columns 00503 for (vcl_size_t k = 1; k < effective_block_size; ++k) 00504 { 00505 UblasMatrixRange Y_old = boost::numeric::ublas::project(ublasY, 00506 boost::numeric::ublas::range(j, A.size1()), 00507 boost::numeric::ublas::range(0, k)); 00508 UblasMatrixRange v_k = boost::numeric::ublas::project(ublasY, 00509 boost::numeric::ublas::range(j, A.size1()), 00510 boost::numeric::ublas::range(k, k+1)); 00511 UblasMatrixRange W_old = boost::numeric::ublas::project(ublasW, 00512 boost::numeric::ublas::range(j, A.size1()), 00513 boost::numeric::ublas::range(0, k)); 00514 UblasMatrixRange z = boost::numeric::ublas::project(ublasW, 00515 boost::numeric::ublas::range(j, A.size1()), 00516 boost::numeric::ublas::range(k, k+1)); 00517 00518 UblasMatrixType YT_prod_v = boost::numeric::ublas::prod(boost::numeric::ublas::trans(Y_old), v_k); 00519 z = - betas[j+k] * (v_k + prod(W_old, YT_prod_v)); 00520 } 00521 00522 00523 00524 // 00525 //apply (I+WY^T)^T = I + Y W^T to the remaining columns of A: 00526 // 00527 00528 VCLMatrixRange A_part = viennacl::project(A, 00529 viennacl::range(0, A.size1()), 00530 viennacl::range(j, j+effective_block_size)); 00531 00532 viennacl::copy(boost::numeric::ublas::project(ublasA, 00533 boost::numeric::ublas::range(0, A.size1()), 00534 boost::numeric::ublas::range(j, j+effective_block_size)), 00535 A_part); 00536 00537 viennacl::copy(ublasW, vclW); 00538 viennacl::copy(ublasY, vclY); 00539 00540 if (A.size2() > j + effective_block_size) 00541 { 00542 00543 VCLMatrixRange A_part(A, viennacl::range(j, A.size1()), viennacl::range(j+effective_block_size, A.size2())); 00544 VCLMatrixRange W_part(vclW, viennacl::range(j, A.size1()), viennacl::range(0, effective_block_size)); 00545 MatrixType temp = viennacl::linalg::prod(trans(W_part), A_part); 00546 00547 A_part += viennacl::linalg::prod(viennacl::project(vclY, viennacl::range(j, A.size1()), viennacl::range(0, vclY.size2())), 00548 temp); 00549 } 00550 } 00551 00552 return betas; 00553 } 00554 00555 00556 00557 } //namespace detail 00558 00559 00560 00561 00562 //takes an inplace QR matrix A and generates Q and R explicitly 00563 template <typename MatrixType, typename VectorType> 00564 void recoverQ(MatrixType const & A, VectorType const & betas, MatrixType & Q, MatrixType & R) 00565 { 00566 typedef typename MatrixType::value_type ScalarType; 00567 00568 std::vector<ScalarType> v(A.size1()); 00569 00570 Q.clear(); 00571 R.clear(); 00572 00573 // 00574 // Recover R from upper-triangular part of A: 00575 // 00576 vcl_size_t i_max = std::min(R.size1(), R.size2()); 00577 for (vcl_size_t i=0; i<i_max; ++i) 00578 for (vcl_size_t j=i; j<R.size2(); ++j) 00579 R(i,j) = A(i,j); 00580 00581 // 00582 // Recover Q by applying all the Householder reflectors to the identity matrix: 00583 // 00584 for (vcl_size_t i=0; i<Q.size1(); ++i) 00585 Q(i,i) = 1.0; 00586 00587 vcl_size_t j_max = std::min(A.size1(), A.size2()); 00588 for (vcl_size_t j=0; j<j_max; ++j) 00589 { 00590 vcl_size_t col_index = j_max - j - 1; 00591 v[col_index] = 1.0; 00592 for (vcl_size_t i=col_index+1; i<A.size1(); ++i) 00593 v[i] = A(i, col_index); 00594 00595 if (betas[col_index] != 0) 00596 detail::householder_reflect(Q, v, betas[col_index], col_index); 00597 } 00598 } 00599 00600 00607 template <typename MatrixType, typename VectorType1, typename VectorType2> 00608 void inplace_qr_apply_trans_Q(MatrixType const & A, VectorType1 const & betas, VectorType2 & b) 00609 { 00610 typedef typename viennacl::result_of::cpu_value_type<typename MatrixType::value_type>::type ScalarType; 00611 00612 // 00613 // Apply Q^T = (I - beta_m v_m v_m^T) \times ... \times (I - beta_0 v_0 v_0^T) by applying all the Householder reflectors to b: 00614 // 00615 for (vcl_size_t col_index=0; col_index<std::min(A.size1(), A.size2()); ++col_index) 00616 { 00617 ScalarType v_in_b = b[col_index]; 00618 for (vcl_size_t i=col_index+1; i<A.size1(); ++i) 00619 v_in_b += A(i, col_index) * b[i]; 00620 00621 b[col_index] -= betas[col_index] * v_in_b; 00622 for (vcl_size_t i=col_index+1; i<A.size1(); ++i) 00623 b[i] -= betas[col_index] * A(i, col_index) * v_in_b; 00624 } 00625 } 00626 00627 template <typename T, typename F, unsigned int ALIGNMENT, typename VectorType1, unsigned int A2> 00628 void inplace_qr_apply_trans_Q(viennacl::matrix<T, F, ALIGNMENT> const & A, VectorType1 const & betas, viennacl::vector<T, A2> & b) 00629 { 00630 boost::numeric::ublas::matrix<T> ublas_A(A.size1(), A.size2()); 00631 viennacl::copy(A, ublas_A); 00632 00633 std::vector<T> stl_b(b.size()); 00634 viennacl::copy(b, stl_b); 00635 00636 inplace_qr_apply_trans_Q(ublas_A, betas, stl_b); 00637 00638 viennacl::copy(stl_b, b); 00639 } 00640 00646 template<typename T, typename F, unsigned int ALIGNMENT> 00647 std::vector<T> inplace_qr(viennacl::matrix<T, F, ALIGNMENT> & A, vcl_size_t block_size = 16) 00648 { 00649 return detail::inplace_qr_hybrid(A, block_size); 00650 } 00651 00657 template<typename MatrixType> 00658 std::vector<typename MatrixType::value_type> inplace_qr(MatrixType & A, vcl_size_t block_size = 16) 00659 { 00660 return detail::inplace_qr_ublas(A, block_size); 00661 } 00662 00663 00664 00665 } //linalg 00666 } //viennacl 00667 00668 00669 #endif