ViennaCL - The Vienna Computing Library  1.5.2
viennacl/linalg/qr-method-common.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_QR_METHOD_COMMON_HPP
00002 #define VIENNACL_LINALG_QR_METHOD_COMMON_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 
00021 #include <cmath>
00022 
00023 #include "viennacl/ocl/device.hpp"
00024 #include "viennacl/ocl/handle.hpp"
00025 #include "viennacl/ocl/kernel.hpp"
00026 #include "viennacl/linalg/opencl/kernels/svd.hpp"
00027 #include "viennacl/meta/result_of.hpp"
00028 #include "viennacl/vector.hpp"
00029 #include "viennacl/matrix.hpp"
00030 
00031 #include <boost/numeric/ublas/vector.hpp>
00032 #include <boost/numeric/ublas/io.hpp>
00033 
00038 namespace viennacl
00039 {
00040   namespace linalg
00041   {
00042     const std::string SVD_BIDIAG_PACK_KERNEL = "bidiag_pack";
00043     const std::string SVD_HOUSEHOLDER_UPDATE_A_LEFT_KERNEL = "house_update_A_left";
00044     const std::string SVD_HOUSEHOLDER_UPDATE_A_RIGHT_KERNEL = "house_update_A_right";
00045     const std::string SVD_HOUSEHOLDER_UPDATE_QL_KERNEL = "house_update_QL";
00046     const std::string SVD_HOUSEHOLDER_UPDATE_QR_KERNEL = "house_update_QR";
00047     const std::string SVD_COPY_COL_KERNEL = "copy_col";
00048     const std::string SVD_COPY_ROW_KERNEL = "copy_row";
00049     const std::string SVD_MATRIX_TRANSPOSE_KERNEL = "transpose_inplace";
00050     const std::string SVD_INVERSE_SIGNS_KERNEL = "inverse_signs";
00051     const std::string SVD_GIVENS_PREV_KERNEL = "givens_prev";
00052     const std::string SVD_GIVENS_NEXT_KERNEL = "givens_next";
00053     const std::string SVD_FINAL_ITER_UPDATE_KERNEL = "final_iter_update";
00054     const std::string SVD_UPDATE_QR_COLUMN_KERNEL = "update_qr_column";
00055 
00056     namespace detail
00057     {
00058       //static const float EPS = 0.00001f;
00059       //static const vcl_size_t ITER_MAX = 50;
00060 
00061       static const double EPS = 1e-10;
00062       static const vcl_size_t ITER_MAX = 50;
00063 
00064       template <typename SCALARTYPE>
00065       SCALARTYPE pythag(SCALARTYPE a, SCALARTYPE b)
00066       {
00067         return std::sqrt(a*a + b*b);
00068       }
00069 
00070       template <typename SCALARTYPE>
00071       SCALARTYPE sign(SCALARTYPE val)
00072       {
00073           return (val >= 0) ? SCALARTYPE(1) : SCALARTYPE(-1);
00074       }
00075 
00076       // DEPRECATED: Replace with viennacl::linalg::norm_2
00077       template <typename VectorType>
00078       typename VectorType::value_type norm_lcl(VectorType const & x, vcl_size_t size)
00079       {
00080         typename VectorType::value_type x_norm = 0.0;
00081         for(vcl_size_t i = 0; i < size; i++)
00082           x_norm += std::pow(x[i], 2);
00083         return std::sqrt(x_norm);
00084       }
00085 
00086       template <typename VectorType>
00087       void normalize(VectorType & x, vcl_size_t size)
00088       {
00089         typename VectorType::value_type x_norm = norm_lcl(x, size);
00090         for(vcl_size_t i = 0; i < size; i++)
00091             x[i] /= x_norm;
00092       }
00093 
00094 
00095 
00096       template <typename VectorType>
00097       void householder_vector(VectorType & v, vcl_size_t start)
00098       {
00099         typedef typename VectorType::value_type    ScalarType;
00100         ScalarType x_norm = norm_lcl(v, v.size());
00101         ScalarType alpha = -sign(v[start]) * x_norm;
00102         v[start] += alpha;
00103         normalize(v, v.size());
00104       }
00105 
00106       template <typename MatrixType>
00107       void transpose(MatrixType & A)
00108       {
00109         typedef typename MatrixType::value_type                                   ScalarType;
00110         typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type    CPU_ScalarType;
00111 
00112         viennacl::ocl::kernel & kernel = viennacl::ocl::get_kernel(viennacl::linalg::opencl::kernels::svd<CPU_ScalarType>::program_name(), SVD_MATRIX_TRANSPOSE_KERNEL);
00113 
00114         viennacl::ocl::enqueue(kernel(A,
00115                                       static_cast<cl_uint>(A.internal_size1()),
00116                                       static_cast<cl_uint>(A.internal_size2())
00117                                      )
00118                               );
00119       }
00120 
00121 
00122 
00123       template <typename T>
00124       void cdiv(T xr, T xi, T yr, T yi, T& cdivr, T& cdivi)
00125       {
00126           // Complex scalar division.
00127           T r;
00128           T d;
00129           if (std::fabs(yr) > std::fabs(yi))
00130           {
00131               r = yi / yr;
00132               d = yr + r * yi;
00133               cdivr = (xr + r * xi) / d;
00134               cdivi = (xi - r * xr) / d;
00135           }
00136           else
00137           {
00138               r = yr / yi;
00139               d = yi + r * yr;
00140               cdivr = (r * xr + xi) / d;
00141               cdivi = (r * xi - xr) / d;
00142           }
00143       }
00144 
00145 
00146       template <typename SCALARTYPE, unsigned int ALIGNMENT>
00147       void copy_vec(viennacl::matrix<SCALARTYPE, row_major, ALIGNMENT>& A,
00148                     viennacl::vector<SCALARTYPE, ALIGNMENT>& V,
00149                     vcl_size_t row_start,
00150                     vcl_size_t col_start,
00151                     bool copy_col
00152       )
00153       {
00154 
00155         std::string kernel_name = copy_col ? SVD_COPY_COL_KERNEL : SVD_COPY_ROW_KERNEL;
00156         viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(A).context());
00157         viennacl::ocl::kernel& kernel = ctx.get_kernel(viennacl::linalg::opencl::kernels::svd<SCALARTYPE>::program_name(), kernel_name);
00158 
00159         viennacl::ocl::enqueue(kernel(
00160                                       A,
00161                                       V,
00162                                       static_cast<cl_uint>(row_start),
00163                                       static_cast<cl_uint>(col_start),
00164                                       copy_col ? static_cast<cl_uint>(A.size1())
00165                                                : static_cast<cl_uint>(A.size2()),
00166                                       static_cast<cl_uint>(A.internal_size2())
00167                               ));
00168 
00169       }
00170 
00171 
00172       template<typename SCALARTYPE, unsigned int ALIGNMENT>
00173       void prepare_householder_vector(
00174                                     viennacl::matrix<SCALARTYPE, row_major, ALIGNMENT>& A,
00175                                     viennacl::vector<SCALARTYPE, ALIGNMENT>& D,
00176                                     vcl_size_t size,
00177                                     vcl_size_t row_start,
00178                                     vcl_size_t col_start,
00179                                     vcl_size_t start,
00180                                     bool is_column
00181                                     )
00182       {
00183         boost::numeric::ublas::vector<SCALARTYPE> tmp = boost::numeric::ublas::scalar_vector<SCALARTYPE>(size, 0);
00184 
00185         copy_vec(A, D, row_start, col_start, is_column);
00186         fast_copy(D.begin(), D.begin() + vcl_ptrdiff_t(size - start), tmp.begin() + start);
00187 
00188         //std::cout << "1: " << tmp << "\n";
00189 
00190         detail::householder_vector(tmp, start);
00191         fast_copy(tmp, D);
00192 
00193         //std::cout << "2: "  << D << "\n";
00194       }
00195 
00196       template <typename SCALARTYPE, unsigned int ALIGNMENT, typename VectorType>
00197       void bidiag_pack(viennacl::matrix<SCALARTYPE, row_major, ALIGNMENT>& A,
00198                        VectorType & dh,
00199                        VectorType & sh
00200                       )
00201       {
00202         viennacl::vector<SCALARTYPE, ALIGNMENT> D(dh.size());
00203         viennacl::vector<SCALARTYPE, ALIGNMENT> S(sh.size());
00204 
00205         viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(A).context());
00206         viennacl::ocl::kernel& kernel = ctx.get_kernel(viennacl::linalg::opencl::kernels::svd<SCALARTYPE>::program_name(), SVD_BIDIAG_PACK_KERNEL);
00207 
00208         viennacl::ocl::enqueue(kernel(
00209                                       A,
00210                                       D,
00211                                       S,
00212                                       static_cast<cl_uint>(A.size1()),
00213                                       static_cast<cl_uint>(A.size2()),
00214                                       static_cast<cl_uint>(A.internal_size2())
00215                                     ));
00216 
00217         fast_copy(D, dh);
00218         fast_copy(S, sh);
00219       }
00220 
00221     }
00222   }
00223 }
00224 
00225 #endif