ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/qr.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_QR_HPP
00002 #define VIENNACL_LINALG_QR_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 <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, effective_block_size)),
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, effective_block_size)),
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, effective_block_size)),
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