ViennaCL - The Vienna Computing Library  1.5.2
viennacl/linalg/matrix_operations.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_MATRIX_OPERATIONS_HPP_
00002 #define VIENNACL_LINALG_MATRIX_OPERATIONS_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/forwards.h"
00026 #include "viennacl/scalar.hpp"
00027 #include "viennacl/vector.hpp"
00028 #include "viennacl/vector_proxy.hpp"
00029 #include "viennacl/tools/tools.hpp"
00030 #include "viennacl/meta/enable_if.hpp"
00031 #include "viennacl/meta/predicate.hpp"
00032 #include "viennacl/meta/result_of.hpp"
00033 #include "viennacl/traits/size.hpp"
00034 #include "viennacl/traits/start.hpp"
00035 #include "viennacl/traits/handle.hpp"
00036 #include "viennacl/traits/stride.hpp"
00037 #include "viennacl/vector.hpp"
00038 #include "viennacl/linalg/host_based/matrix_operations.hpp"
00039 
00040 #ifdef VIENNACL_WITH_OPENCL
00041   #include "viennacl/linalg/opencl/matrix_operations.hpp"
00042 #endif
00043 
00044 #ifdef VIENNACL_WITH_CUDA
00045   #include "viennacl/linalg/cuda/matrix_operations.hpp"
00046 #endif
00047 
00048 namespace viennacl
00049 {
00050   namespace linalg
00051   {
00052 
00053     template <typename NumericT, typename F,
00054               typename ScalarType1>
00055     void am(matrix_base<NumericT, F> & mat1,
00056             matrix_base<NumericT, F> const & mat2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha)
00057     {
00058       switch (viennacl::traits::handle(mat1).get_active_handle_id())
00059       {
00060         case viennacl::MAIN_MEMORY:
00061           viennacl::linalg::host_based::am(mat1, mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha);
00062           break;
00063 #ifdef VIENNACL_WITH_OPENCL
00064         case viennacl::OPENCL_MEMORY:
00065           viennacl::linalg::opencl::am(mat1, mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha);
00066           break;
00067 #endif
00068 #ifdef VIENNACL_WITH_CUDA
00069         case viennacl::CUDA_MEMORY:
00070           viennacl::linalg::cuda::am(mat1, mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha);
00071           break;
00072 #endif
00073         case viennacl::MEMORY_NOT_INITIALIZED:
00074           throw memory_exception("not initialised!");
00075         default:
00076           throw memory_exception("not implemented");
00077       }
00078     }
00079 
00080 
00081     template <typename NumericT, typename F,
00082               typename ScalarType1, typename ScalarType2>
00083     void ambm(matrix_base<NumericT, F> & mat1,
00084               matrix_base<NumericT, F> const & mat2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha,
00085               matrix_base<NumericT, F> const & mat3, ScalarType2 const & beta,  vcl_size_t len_beta,  bool reciprocal_beta,  bool flip_sign_beta)
00086     {
00087       switch (viennacl::traits::handle(mat1).get_active_handle_id())
00088       {
00089         case viennacl::MAIN_MEMORY:
00090           viennacl::linalg::host_based::ambm(mat1,
00091                                              mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00092                                              mat3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00093           break;
00094 #ifdef VIENNACL_WITH_OPENCL
00095         case viennacl::OPENCL_MEMORY:
00096           viennacl::linalg::opencl::ambm(mat1,
00097                                          mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00098                                          mat3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00099           break;
00100 #endif
00101 #ifdef VIENNACL_WITH_CUDA
00102         case viennacl::CUDA_MEMORY:
00103           viennacl::linalg::cuda::ambm(mat1,
00104                                        mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00105                                        mat3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00106           break;
00107 #endif
00108         case viennacl::MEMORY_NOT_INITIALIZED:
00109           throw memory_exception("not initialised!");
00110         default:
00111           throw memory_exception("not implemented");
00112       }
00113     }
00114 
00115 
00116     template <typename NumericT, typename F,
00117               typename ScalarType1, typename ScalarType2>
00118     void ambm_m(matrix_base<NumericT, F> & mat1,
00119                 matrix_base<NumericT, F> const & mat2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha,
00120                 matrix_base<NumericT, F> const & mat3, ScalarType2 const & beta,  vcl_size_t len_beta,  bool reciprocal_beta,  bool flip_sign_beta)
00121     {
00122       switch (viennacl::traits::handle(mat1).get_active_handle_id())
00123       {
00124         case viennacl::MAIN_MEMORY:
00125           viennacl::linalg::host_based::ambm_m(mat1,
00126                                                mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00127                                                mat3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00128           break;
00129 #ifdef VIENNACL_WITH_OPENCL
00130         case viennacl::OPENCL_MEMORY:
00131           viennacl::linalg::opencl::ambm_m(mat1,
00132                                            mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00133                                            mat3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00134           break;
00135 #endif
00136 #ifdef VIENNACL_WITH_CUDA
00137         case viennacl::CUDA_MEMORY:
00138           viennacl::linalg::cuda::ambm_m(mat1,
00139                                          mat2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00140                                          mat3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00141           break;
00142 #endif
00143         case viennacl::MEMORY_NOT_INITIALIZED:
00144           throw memory_exception("not initialised!");
00145         default:
00146           throw memory_exception("not implemented");
00147       }
00148     }
00149 
00150 
00151     template <typename NumericT, typename F>
00152     void matrix_assign(matrix_base<NumericT, F> & mat, NumericT s, bool clear = false)
00153     {
00154       switch (viennacl::traits::handle(mat).get_active_handle_id())
00155       {
00156         case viennacl::MAIN_MEMORY:
00157           viennacl::linalg::host_based::matrix_assign(mat, s, clear);
00158           break;
00159 #ifdef VIENNACL_WITH_OPENCL
00160         case viennacl::OPENCL_MEMORY:
00161           viennacl::linalg::opencl::matrix_assign(mat, s, clear);
00162           break;
00163 #endif
00164 #ifdef VIENNACL_WITH_CUDA
00165         case viennacl::CUDA_MEMORY:
00166           viennacl::linalg::cuda::matrix_assign(mat, s, clear);
00167           break;
00168 #endif
00169         case viennacl::MEMORY_NOT_INITIALIZED:
00170           throw memory_exception("not initialised!");
00171         default:
00172           throw memory_exception("not implemented");
00173       }
00174     }
00175 
00176 
00177     template <typename NumericT, typename F>
00178     void matrix_diagonal_assign(matrix_base<NumericT, F> & mat, NumericT s)
00179     {
00180       switch (viennacl::traits::handle(mat).get_active_handle_id())
00181       {
00182         case viennacl::MAIN_MEMORY:
00183           viennacl::linalg::host_based::matrix_diagonal_assign(mat, s);
00184           break;
00185 #ifdef VIENNACL_WITH_OPENCL
00186         case viennacl::OPENCL_MEMORY:
00187           viennacl::linalg::opencl::matrix_diagonal_assign(mat, s);
00188           break;
00189 #endif
00190 #ifdef VIENNACL_WITH_CUDA
00191         case viennacl::CUDA_MEMORY:
00192           viennacl::linalg::cuda::matrix_diagonal_assign(mat, s);
00193           break;
00194 #endif
00195         case viennacl::MEMORY_NOT_INITIALIZED:
00196           throw memory_exception("not initialised!");
00197         default:
00198           throw memory_exception("not implemented");
00199       }
00200     }
00201 
00202 
00204     template <typename NumericT, typename F>
00205     void matrix_diag_from_vector(const vector_base<NumericT> & v, int k, matrix_base<NumericT, F> & A)
00206     {
00207       switch (viennacl::traits::handle(v).get_active_handle_id())
00208       {
00209         case viennacl::MAIN_MEMORY:
00210           viennacl::linalg::host_based::matrix_diag_from_vector(v, k, A);
00211           break;
00212 #ifdef VIENNACL_WITH_OPENCL
00213         case viennacl::OPENCL_MEMORY:
00214           viennacl::linalg::opencl::matrix_diag_from_vector(v, k, A);
00215           break;
00216 #endif
00217 #ifdef VIENNACL_WITH_CUDA
00218         case viennacl::CUDA_MEMORY:
00219           viennacl::linalg::cuda::matrix_diag_from_vector(v, k, A);
00220           break;
00221 #endif
00222         case viennacl::MEMORY_NOT_INITIALIZED:
00223           throw memory_exception("not initialised!");
00224         default:
00225           throw memory_exception("not implemented");
00226       }
00227     }
00228 
00230     template <typename NumericT, typename F>
00231     void matrix_diag_to_vector(const matrix_base<NumericT, F> & A, int k, vector_base<NumericT> & v)
00232     {
00233       switch (viennacl::traits::handle(A).get_active_handle_id())
00234       {
00235         case viennacl::MAIN_MEMORY:
00236           viennacl::linalg::host_based::matrix_diag_to_vector(A, k, v);
00237           break;
00238 #ifdef VIENNACL_WITH_OPENCL
00239         case viennacl::OPENCL_MEMORY:
00240           viennacl::linalg::opencl::matrix_diag_to_vector(A, k, v);
00241           break;
00242 #endif
00243 #ifdef VIENNACL_WITH_CUDA
00244         case viennacl::CUDA_MEMORY:
00245           viennacl::linalg::cuda::matrix_diag_to_vector(A, k, v);
00246           break;
00247 #endif
00248         case viennacl::MEMORY_NOT_INITIALIZED:
00249           throw memory_exception("not initialised!");
00250         default:
00251           throw memory_exception("not implemented");
00252       }
00253     }
00254 
00255     template <typename NumericT, typename F>
00256     void matrix_row(const matrix_base<NumericT, F> & A, unsigned int i, vector_base<NumericT> & v)
00257     {
00258       switch (viennacl::traits::handle(A).get_active_handle_id())
00259       {
00260         case viennacl::MAIN_MEMORY:
00261           viennacl::linalg::host_based::matrix_row(A, i, v);
00262           break;
00263 #ifdef VIENNACL_WITH_OPENCL
00264         case viennacl::OPENCL_MEMORY:
00265           viennacl::linalg::opencl::matrix_row(A, i, v);
00266           break;
00267 #endif
00268 #ifdef VIENNACL_WITH_CUDA
00269         case viennacl::CUDA_MEMORY:
00270           viennacl::linalg::cuda::matrix_row(A, i, v);
00271           break;
00272 #endif
00273         case viennacl::MEMORY_NOT_INITIALIZED:
00274           throw memory_exception("not initialised!");
00275         default:
00276           throw memory_exception("not implemented");
00277       }
00278     }
00279 
00280     template <typename NumericT, typename F>
00281     void matrix_column(const matrix_base<NumericT, F> & A, unsigned int j, vector_base<NumericT> & v)
00282     {
00283       switch (viennacl::traits::handle(A).get_active_handle_id())
00284       {
00285         case viennacl::MAIN_MEMORY:
00286           viennacl::linalg::host_based::matrix_column(A, j, v);
00287           break;
00288 #ifdef VIENNACL_WITH_OPENCL
00289         case viennacl::OPENCL_MEMORY:
00290           viennacl::linalg::opencl::matrix_column(A, j, v);
00291           break;
00292 #endif
00293 #ifdef VIENNACL_WITH_CUDA
00294         case viennacl::CUDA_MEMORY:
00295           viennacl::linalg::cuda::matrix_column(A, j, v);
00296           break;
00297 #endif
00298         case viennacl::MEMORY_NOT_INITIALIZED:
00299           throw memory_exception("not initialised!");
00300         default:
00301           throw memory_exception("not implemented");
00302       }
00303     }
00304 
00310     template <typename T, typename F>
00311     void norm_frobenius_impl(matrix_base<T, F> const & A,
00312                              scalar<T> & result)
00313     {
00314       typedef typename matrix_base<T, F>::handle_type  HandleType;
00315       viennacl::vector_base<T> temp(const_cast<HandleType &>(A.handle()), A.internal_size(), 0, 1);
00316       norm_2_impl(temp, result);
00317     }
00318 
00324     template <typename T, typename F>
00325     void norm_frobenius_cpu(matrix_base<T, F> const & A,
00326                              T & result)
00327     {
00328       typedef typename matrix_base<T, F>::handle_type  HandleType;
00329       viennacl::vector_base<T> temp(const_cast<HandleType &>(A.handle()), A.internal_size(), 0, 1);
00330       norm_2_cpu(temp, result);
00331     }
00332 
00333     //
00335     //
00336 
00337 
00338 
00339     // A * x
00340 
00349     template <typename NumericT, typename F>
00350     void prod_impl(const matrix_base<NumericT, F> & mat,
00351                    const vector_base<NumericT> & vec,
00352                          vector_base<NumericT> & result)
00353     {
00354       assert( (viennacl::traits::size1(mat) == viennacl::traits::size(result)) && bool("Size check failed at v1 = prod(A, v2): size1(A) != size(v1)"));
00355       assert( (viennacl::traits::size2(mat) == viennacl::traits::size(vec))    && bool("Size check failed at v1 = prod(A, v2): size2(A) != size(v2)"));
00356 
00357       switch (viennacl::traits::handle(mat).get_active_handle_id())
00358       {
00359         case viennacl::MAIN_MEMORY:
00360           viennacl::linalg::host_based::prod_impl(mat, vec, result);
00361           break;
00362 #ifdef VIENNACL_WITH_OPENCL
00363         case viennacl::OPENCL_MEMORY:
00364           viennacl::linalg::opencl::prod_impl(mat, vec, result);
00365           break;
00366 #endif
00367 #ifdef VIENNACL_WITH_CUDA
00368         case viennacl::CUDA_MEMORY:
00369           viennacl::linalg::cuda::prod_impl(mat, vec, result);
00370           break;
00371 #endif
00372         case viennacl::MEMORY_NOT_INITIALIZED:
00373           throw memory_exception("not initialised!");
00374         default:
00375           throw memory_exception("not implemented");
00376       }
00377     }
00378 
00379 
00380     // trans(A) * x
00381 
00390     template <typename NumericT, typename F>
00391     void prod_impl(const matrix_expression< const matrix_base<NumericT, F>, const matrix_base<NumericT, F>, op_trans> & mat_trans,
00392                    const vector_base<NumericT> & vec,
00393                          vector_base<NumericT> & result)
00394     {
00395       assert( (viennacl::traits::size1(mat_trans.lhs()) == viennacl::traits::size(vec))    && bool("Size check failed at v1 = trans(A) * v2: size1(A) != size(v2)"));
00396       assert( (viennacl::traits::size2(mat_trans.lhs()) == viennacl::traits::size(result)) && bool("Size check failed at v1 = trans(A) * v2: size2(A) != size(v1)"));
00397 
00398       switch (viennacl::traits::handle(mat_trans.lhs()).get_active_handle_id())
00399       {
00400         case viennacl::MAIN_MEMORY:
00401           viennacl::linalg::host_based::prod_impl(mat_trans, vec, result);
00402           break;
00403 #ifdef VIENNACL_WITH_OPENCL
00404         case viennacl::OPENCL_MEMORY:
00405           viennacl::linalg::opencl::prod_impl(mat_trans, vec, result);
00406           break;
00407 #endif
00408 #ifdef VIENNACL_WITH_CUDA
00409         case viennacl::CUDA_MEMORY:
00410           viennacl::linalg::cuda::prod_impl(mat_trans, vec, result);
00411           break;
00412 #endif
00413         case viennacl::MEMORY_NOT_INITIALIZED:
00414           throw memory_exception("not initialised!");
00415         default:
00416           throw memory_exception("not implemented");
00417       }
00418     }
00419 
00420 
00421     //
00423     //
00424 
00430     template <typename NumericT, typename F1, typename F2, typename F3, typename ScalarType >
00431     void prod_impl(const matrix_base<NumericT, F1> & A,
00432                    const matrix_base<NumericT, F2> & B,
00433                          matrix_base<NumericT, F3> & C,
00434                    ScalarType alpha,
00435                    ScalarType beta)
00436     {
00437       assert( (viennacl::traits::size1(A) == viennacl::traits::size1(C)) && bool("Size check failed at C = prod(A, B): size1(A) != size1(C)"));
00438       assert( (viennacl::traits::size2(A) == viennacl::traits::size1(B)) && bool("Size check failed at C = prod(A, B): size2(A) != size1(B)"));
00439       assert( (viennacl::traits::size2(B) == viennacl::traits::size2(C)) && bool("Size check failed at C = prod(A, B): size2(B) != size2(C)"));
00440 
00441 
00442       switch (viennacl::traits::handle(A).get_active_handle_id())
00443       {
00444         case viennacl::MAIN_MEMORY:
00445           viennacl::linalg::host_based::prod_impl(A, B, C, alpha, beta);
00446           break;
00447 #ifdef VIENNACL_WITH_OPENCL
00448         case viennacl::OPENCL_MEMORY:
00449           viennacl::linalg::opencl::prod_impl(A, B, C, alpha, beta);
00450           break;
00451 #endif
00452 #ifdef VIENNACL_WITH_CUDA
00453         case viennacl::CUDA_MEMORY:
00454           viennacl::linalg::cuda::prod_impl(A, B, C, alpha, beta);
00455           break;
00456 #endif
00457         case viennacl::MEMORY_NOT_INITIALIZED:
00458           throw memory_exception("not initialised!");
00459         default:
00460           throw memory_exception("not implemented");
00461       }
00462     }
00463 
00464 
00465 
00471     template <typename NumericT, typename F1, typename F2, typename F3, typename ScalarType >
00472     void prod_impl(const viennacl::matrix_expression< const matrix_base<NumericT, F1>,
00473                                                       const matrix_base<NumericT, F1>,
00474                                                       op_trans> & A,
00475                    const matrix_base<NumericT, F2> & B,
00476                          matrix_base<NumericT, F3> & C,
00477                    ScalarType alpha,
00478                    ScalarType beta)
00479     {
00480       assert(viennacl::traits::size2(A.lhs()) == viennacl::traits::size1(C) && bool("Size check failed at C = prod(trans(A), B): size2(A) != size1(C)"));
00481       assert(viennacl::traits::size1(A.lhs()) == viennacl::traits::size1(B) && bool("Size check failed at C = prod(trans(A), B): size1(A) != size1(B)"));
00482       assert(viennacl::traits::size2(B)       == viennacl::traits::size2(C) && bool("Size check failed at C = prod(trans(A), B): size2(B) != size2(C)"));
00483 
00484       switch (viennacl::traits::handle(A.lhs()).get_active_handle_id())
00485       {
00486         case viennacl::MAIN_MEMORY:
00487           viennacl::linalg::host_based::prod_impl(A, B, C, alpha, beta);
00488           break;
00489 #ifdef VIENNACL_WITH_OPENCL
00490         case viennacl::OPENCL_MEMORY:
00491           viennacl::linalg::opencl::prod_impl(A, B, C, alpha, beta);
00492           break;
00493 #endif
00494 #ifdef VIENNACL_WITH_CUDA
00495         case viennacl::CUDA_MEMORY:
00496           viennacl::linalg::cuda::prod_impl(A, B, C, alpha, beta);
00497           break;
00498 #endif
00499         case viennacl::MEMORY_NOT_INITIALIZED:
00500           throw memory_exception("not initialised!");
00501         default:
00502           throw memory_exception("not implemented");
00503       }
00504     }
00505 
00506 
00507 
00508 
00514     template <typename NumericT, typename F1, typename F2, typename F3, typename ScalarType >
00515     void prod_impl(const matrix_base<NumericT, F1> & A,
00516                    const viennacl::matrix_expression< const matrix_base<NumericT, F2>, const matrix_base<NumericT, F2>, op_trans> & B,
00517                          matrix_base<NumericT, F3> & C,
00518                    ScalarType alpha,
00519                    ScalarType beta)
00520     {
00521       assert(viennacl::traits::size1(A)       == viennacl::traits::size1(C)       && bool("Size check failed at C = prod(A, trans(B)): size1(A) != size1(C)"));
00522       assert(viennacl::traits::size2(A)       == viennacl::traits::size2(B.lhs()) && bool("Size check failed at C = prod(A, trans(B)): size2(A) != size2(B)"));
00523       assert(viennacl::traits::size1(B.lhs()) == viennacl::traits::size2(C)       && bool("Size check failed at C = prod(A, trans(B)): size1(B) != size2(C)"));
00524 
00525       switch (viennacl::traits::handle(A).get_active_handle_id())
00526       {
00527         case viennacl::MAIN_MEMORY:
00528           viennacl::linalg::host_based::prod_impl(A, B, C, alpha, beta);
00529           break;
00530 #ifdef VIENNACL_WITH_OPENCL
00531         case viennacl::OPENCL_MEMORY:
00532           viennacl::linalg::opencl::prod_impl(A, B, C, alpha, beta);
00533           break;
00534 #endif
00535 #ifdef VIENNACL_WITH_CUDA
00536         case viennacl::CUDA_MEMORY:
00537           viennacl::linalg::cuda::prod_impl(A, B, C, alpha, beta);
00538           break;
00539 #endif
00540         case viennacl::MEMORY_NOT_INITIALIZED:
00541           throw memory_exception("not initialised!");
00542         default:
00543           throw memory_exception("not implemented");
00544       }
00545     }
00546 
00547 
00548 
00554     template <typename NumericT, typename F1, typename F2, typename F3, typename ScalarType >
00555     void prod_impl(const viennacl::matrix_expression< const matrix_base<NumericT, F1>, const matrix_base<NumericT, F1>, op_trans> & A,
00556                    const viennacl::matrix_expression< const matrix_base<NumericT, F2>, const matrix_base<NumericT, F2>, op_trans> & B,
00557                    matrix_base<NumericT, F3> & C,
00558                    ScalarType alpha,
00559                    ScalarType beta)
00560     {
00561       assert(viennacl::traits::size2(A.lhs()) == viennacl::traits::size1(C)       && bool("Size check failed at C = prod(trans(A), trans(B)): size2(A) != size1(C)"));
00562       assert(viennacl::traits::size1(A.lhs()) == viennacl::traits::size2(B.lhs()) && bool("Size check failed at C = prod(trans(A), trans(B)): size1(A) != size2(B)"));
00563       assert(viennacl::traits::size1(B.lhs()) == viennacl::traits::size2(C)       && bool("Size check failed at C = prod(trans(A), trans(B)): size1(B) != size2(C)"));
00564 
00565       switch (viennacl::traits::handle(A.lhs()).get_active_handle_id())
00566       {
00567         case viennacl::MAIN_MEMORY:
00568           viennacl::linalg::host_based::prod_impl(A, B, C, alpha, beta);
00569           break;
00570 #ifdef VIENNACL_WITH_OPENCL
00571         case viennacl::OPENCL_MEMORY:
00572           viennacl::linalg::opencl::prod_impl(A, B, C, alpha, beta);
00573           break;
00574 #endif
00575 #ifdef VIENNACL_WITH_CUDA
00576         case viennacl::CUDA_MEMORY:
00577           viennacl::linalg::cuda::prod_impl(A, B, C, alpha, beta);
00578           break;
00579 #endif
00580         case viennacl::MEMORY_NOT_INITIALIZED:
00581           throw memory_exception("not initialised!");
00582         default:
00583           throw memory_exception("not implemented");
00584       }
00585     }
00586 
00587 
00589 
00590 
00591 
00597     template <typename T, typename F, typename OP>
00598     void element_op(matrix_base<T, F> & A,
00599                     matrix_expression<const matrix_base<T, F>, const matrix_base<T, F>, OP> const & proxy)
00600     {
00601       assert( (viennacl::traits::size1(A) == viennacl::traits::size1(proxy)) && bool("Size check failed at A = element_op(B): size1(A) != size1(B)"));
00602       assert( (viennacl::traits::size2(A) == viennacl::traits::size2(proxy)) && bool("Size check failed at A = element_op(B): size2(A) != size2(B)"));
00603 
00604       switch (viennacl::traits::handle(A).get_active_handle_id())
00605       {
00606         case viennacl::MAIN_MEMORY:
00607           viennacl::linalg::host_based::element_op(A, proxy);
00608           break;
00609 #ifdef VIENNACL_WITH_OPENCL
00610         case viennacl::OPENCL_MEMORY:
00611           viennacl::linalg::opencl::element_op(A, proxy);
00612           break;
00613 #endif
00614 #ifdef VIENNACL_WITH_CUDA
00615         case viennacl::CUDA_MEMORY:
00616           viennacl::linalg::cuda::element_op(A, proxy);
00617           break;
00618 #endif
00619         case viennacl::MEMORY_NOT_INITIALIZED:
00620           throw memory_exception("not initialised!");
00621         default:
00622           throw memory_exception("not implemented");
00623       }
00624     }
00625 
00626 
00627 #define VIENNACL_MAKE_BINARY_OP(OPNAME)\
00628     template <typename T, typename F>\
00629     viennacl::matrix_expression<const matrix_base<T, F>, const matrix_base<T, F>, op_element_binary<op_##OPNAME> >\
00630     element_##OPNAME(matrix_base<T, F> const & A, matrix_base<T, F> const & B)\
00631     {\
00632       return viennacl::matrix_expression<const matrix_base<T, F>, const matrix_base<T, F>, op_element_binary<op_##OPNAME> >(A, B);\
00633     }\
00634 \
00635     template <typename M1, typename M2, typename OP, typename T, typename F>\
00636     viennacl::matrix_expression<const matrix_expression<const M1, const M2, OP>,\
00637                                 const matrix_base<T, F>,\
00638                                 op_element_binary<op_##OPNAME> >\
00639     element_##OPNAME(matrix_expression<const M1, const M2, OP> const & proxy, matrix_base<T, F> const & B)\
00640     {\
00641       return viennacl::matrix_expression<const matrix_expression<const M1, const M2, OP>,\
00642                                          const matrix_base<T, F>,\
00643                                          op_element_binary<op_##OPNAME> >(proxy, B);\
00644     }\
00645 \
00646     template <typename T, typename F, typename M2, typename M3, typename OP>\
00647     viennacl::matrix_expression<const matrix_base<T, F>,\
00648                                 const matrix_expression<const M2, const M3, OP>,\
00649                                 op_element_binary<op_##OPNAME> >\
00650     element_##OPNAME(matrix_base<T, F> const & A, matrix_expression<const M2, const M3, OP> const & proxy)\
00651     {\
00652       return viennacl::matrix_expression<const matrix_base<T, F>,\
00653                                          const matrix_expression<const M2, const M3, OP>,\
00654                                          op_element_binary<op_##OPNAME> >(A, proxy);\
00655     }\
00656 \
00657     template <typename M1, typename M2, typename OP1,\
00658               typename M3, typename M4, typename OP2>\
00659     viennacl::matrix_expression<const matrix_expression<const M1, const M2, OP1>,\
00660                                 const matrix_expression<const M3, const M4, OP2>,\
00661                                 op_element_binary<op_##OPNAME> >\
00662     element_##OPNAME(matrix_expression<const M1, const M2, OP1> const & proxy1,\
00663                  matrix_expression<const M3, const M4, OP2> const & proxy2)\
00664     {\
00665       return viennacl::matrix_expression<const matrix_expression<const M1, const M2, OP1>,\
00666                                          const matrix_expression<const M3, const M4, OP2>,\
00667                                          op_element_binary<op_##OPNAME> >(proxy1, proxy2);\
00668     }
00669 
00670     VIENNACL_MAKE_BINARY_OP(prod)
00671     VIENNACL_MAKE_BINARY_OP(div)
00672     VIENNACL_MAKE_BINARY_OP(pow)
00673 
00674 #undef VIENNACL_GENERATE_BINARY_OP_OVERLOADS
00675 
00676 
00677 
00678 #define VIENNACL_MAKE_UNARY_ELEMENT_OP(funcname) \
00679     template <typename T, typename F> \
00680     viennacl::matrix_expression<const matrix_base<T, F>, const matrix_base<T, F>, op_element_unary<op_##funcname> > \
00681     element_##funcname(matrix_base<T, F> const & A) \
00682     { \
00683       return viennacl::matrix_expression<const matrix_base<T, F>, const matrix_base<T, F>, op_element_unary<op_##funcname> >(A, A); \
00684     } \
00685     template <typename LHS, typename RHS, typename OP> \
00686     viennacl::matrix_expression<const matrix_expression<const LHS, const RHS, OP>, \
00687                                 const matrix_expression<const LHS, const RHS, OP>, \
00688                                 op_element_unary<op_##funcname> > \
00689     element_##funcname(matrix_expression<const LHS, const RHS, OP> const & proxy) \
00690     { \
00691       return viennacl::matrix_expression<const matrix_expression<const LHS, const RHS, OP>, \
00692                                          const matrix_expression<const LHS, const RHS, OP>, \
00693                                          op_element_unary<op_##funcname> >(proxy, proxy); \
00694     } \
00695 
00696     VIENNACL_MAKE_UNARY_ELEMENT_OP(abs)
00697     VIENNACL_MAKE_UNARY_ELEMENT_OP(acos)
00698     VIENNACL_MAKE_UNARY_ELEMENT_OP(asin)
00699     VIENNACL_MAKE_UNARY_ELEMENT_OP(atan)
00700     VIENNACL_MAKE_UNARY_ELEMENT_OP(ceil)
00701     VIENNACL_MAKE_UNARY_ELEMENT_OP(cos)
00702     VIENNACL_MAKE_UNARY_ELEMENT_OP(cosh)
00703     VIENNACL_MAKE_UNARY_ELEMENT_OP(exp)
00704     VIENNACL_MAKE_UNARY_ELEMENT_OP(fabs)
00705     VIENNACL_MAKE_UNARY_ELEMENT_OP(floor)
00706     VIENNACL_MAKE_UNARY_ELEMENT_OP(log)
00707     VIENNACL_MAKE_UNARY_ELEMENT_OP(log10)
00708     VIENNACL_MAKE_UNARY_ELEMENT_OP(sin)
00709     VIENNACL_MAKE_UNARY_ELEMENT_OP(sinh)
00710     VIENNACL_MAKE_UNARY_ELEMENT_OP(sqrt)
00711     VIENNACL_MAKE_UNARY_ELEMENT_OP(tan)
00712     VIENNACL_MAKE_UNARY_ELEMENT_OP(tanh)
00713 
00714 #undef VIENNACL_MAKE_UNARY_ELEMENT_OP
00715 
00716 
00717     //
00719     //
00720 
00721 
00727     template <typename NumericT>
00728     viennacl::matrix_expression<const vector_base<NumericT>, const vector_base<NumericT>, op_prod>
00729     outer_prod(const vector_base<NumericT> & vec1, const vector_base<NumericT> & vec2)
00730     {
00731       return viennacl::matrix_expression< const vector_base<NumericT>, const vector_base<NumericT>, op_prod>(vec1, vec2);
00732     }
00733 
00734 
00747     template <typename NumericT, typename F, typename S1>
00748     void scaled_rank_1_update(matrix_base<NumericT, F> & mat1,
00749                               S1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha,
00750                               const vector_base<NumericT> & vec1,
00751                               const vector_base<NumericT> & vec2)
00752     {
00753       switch (viennacl::traits::handle(mat1).get_active_handle_id())
00754       {
00755         case viennacl::MAIN_MEMORY:
00756           viennacl::linalg::host_based::scaled_rank_1_update(mat1,
00757                                                              alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00758                                                              vec1, vec2);
00759           break;
00760 #ifdef VIENNACL_WITH_OPENCL
00761         case viennacl::OPENCL_MEMORY:
00762           viennacl::linalg::opencl::scaled_rank_1_update(mat1,
00763                                                          alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00764                                                          vec1, vec2);
00765           break;
00766 #endif
00767 #ifdef VIENNACL_WITH_CUDA
00768         case viennacl::CUDA_MEMORY:
00769           viennacl::linalg::cuda::scaled_rank_1_update(mat1,
00770                                                        alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00771                                                        vec1, vec2);
00772           break;
00773 #endif
00774         case viennacl::MEMORY_NOT_INITIALIZED:
00775           throw memory_exception("not initialised!");
00776         default:
00777           throw memory_exception("not implemented");
00778       }
00779     }
00780 
00781   } //namespace linalg
00782 
00783 
00784 
00785 
00786   //
00788   //
00789 
00790 
00791   //v += A * x
00797   template <typename NumericT, typename F>
00798   vector<NumericT>
00799   operator+=(vector_base<NumericT> & v1,
00800              const viennacl::vector_expression< const matrix_base<NumericT, F>, const vector_base<NumericT>, viennacl::op_prod> & proxy)
00801   {
00802     assert(viennacl::traits::size1(proxy.lhs()) == v1.size() && bool("Size check failed for v1 += A * v2: size1(A) != size(v1)"));
00803 
00804     vector<NumericT> result(viennacl::traits::size1(proxy.lhs()));
00805     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00806     v1 += result;
00807     return v1;
00808   }
00809 
00815   template <typename NumericT, typename F>
00816   vector<NumericT>
00817   operator-=(vector_base<NumericT> & v1,
00818              const viennacl::vector_expression< const matrix_base<NumericT, F>, const vector_base<NumericT>, viennacl::op_prod> & proxy)
00819   {
00820     assert(viennacl::traits::size1(proxy.lhs()) == v1.size() && bool("Size check failed for v1 -= A * v2: size1(A) != size(v1)"));
00821 
00822     vector<NumericT> result(viennacl::traits::size1(proxy.lhs()));
00823     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00824     v1 -= result;
00825     return v1;
00826   }
00827 
00828 
00829 
00830 
00831 
00832   //free functions:
00838   template <typename NumericT, typename F>
00839   viennacl::vector<NumericT>
00840   operator+(const vector_base<NumericT> & v1,
00841             const vector_expression< const matrix_base<NumericT, F>, const vector_base<NumericT>, op_prod> & proxy)
00842   {
00843     assert(viennacl::traits::size1(proxy.lhs()) == viennacl::traits::size(v1) && bool("Size check failed for v1 + A * v2: size1(A) != size(v1)"));
00844 
00845     vector<NumericT> result(viennacl::traits::size(v1));
00846     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00847     result += v1;
00848     return result;
00849   }
00850 
00856   template <typename NumericT, typename F>
00857   viennacl::vector<NumericT>
00858   operator-(const vector_base<NumericT> & v1,
00859             const vector_expression< const matrix_base<NumericT, F>, const vector_base<NumericT>, op_prod> & proxy)
00860   {
00861     assert(viennacl::traits::size1(proxy.lhs()) == viennacl::traits::size(v1) && bool("Size check failed for v1 - A * v2: size1(A) != size(v1)"));
00862 
00863     vector<NumericT> result(viennacl::traits::size(v1));
00864     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00865     result = v1 - result;
00866     return result;
00867   }
00868 
00869 
00871 
00872 
00873   //v += A^T * x
00879   template <typename NumericT, typename F>
00880   vector<NumericT>
00881   operator+=(vector_base<NumericT> & v1,
00882              const vector_expression< const matrix_expression<const matrix_base<NumericT, F>, const matrix_base<NumericT, F>, op_trans>,
00883                                                               const vector_base<NumericT>,
00884                                                               op_prod> & proxy)
00885   {
00886     assert(viennacl::traits::size2(proxy.lhs()) == v1.size() && bool("Size check failed in v1 += trans(A) * v2: size2(A) != size(v1)"));
00887 
00888     vector<NumericT> result(viennacl::traits::size2(proxy.lhs()));
00889     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00890     v1 += result;
00891     return v1;
00892   }
00893 
00894   //v -= A^T * x
00900   template <typename NumericT, typename F>
00901   vector<NumericT>
00902   operator-=(vector_base<NumericT> & v1,
00903              const vector_expression< const matrix_expression<const matrix_base<NumericT, F>, const matrix_base<NumericT, F>, op_trans>,
00904                                                               const vector_base<NumericT>,
00905                                                               op_prod> & proxy)
00906   {
00907     assert(viennacl::traits::size2(proxy.lhs()) == v1.size() && bool("Size check failed in v1 += trans(A) * v2: size2(A) != size(v1)"));
00908 
00909     vector<NumericT> result(viennacl::traits::size2(proxy.lhs()));
00910     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00911     v1 -= result;
00912     return v1;
00913   }
00914 
00915 
00916   //free functions:
00922   template <typename NumericT, typename F>
00923   vector<NumericT>
00924   operator+(const vector_base<NumericT> & v1,
00925             const vector_expression< const matrix_expression<const matrix_base<NumericT, F>, const matrix_base<NumericT, F>, op_trans>,
00926                                      const vector_base<NumericT>,
00927                                      op_prod> & proxy)
00928   {
00929     assert(viennacl::traits::size2(proxy.lhs()) == viennacl::traits::size(v1) && bool("Size check failed in v1 + trans(A) * v2: size2(A) != size(v1)"));
00930 
00931     vector<NumericT> result(viennacl::traits::size(v1));
00932     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00933     result += v1;
00934     return result;
00935   }
00936 
00942   template <typename NumericT, typename F>
00943   vector<NumericT>
00944   operator-(const vector_base<NumericT> & v1,
00945             const vector_expression< const matrix_expression<const matrix_base<NumericT, F>, const matrix_base<NumericT, F>, op_trans>,
00946                                      const vector_base<NumericT>,
00947                                      op_prod> & proxy)
00948   {
00949     assert(viennacl::traits::size2(proxy.lhs()) == viennacl::traits::size(v1) && bool("Size check failed in v1 - trans(A) * v2: size2(A) != size(v1)"));
00950 
00951     vector<NumericT> result(viennacl::traits::size(v1));
00952     viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result);
00953     result = v1 - result;
00954     return result;
00955   }
00956 
00957 
00958 } //namespace viennacl
00959 
00960 
00961 #endif