ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/vector_operations.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_VECTOR_OPERATIONS_HPP_
00002 #define VIENNACL_LINALG_VECTOR_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/tools/tools.hpp"
00028 #include "viennacl/meta/predicate.hpp"
00029 #include "viennacl/meta/enable_if.hpp"
00030 #include "viennacl/traits/size.hpp"
00031 #include "viennacl/traits/start.hpp"
00032 #include "viennacl/traits/handle.hpp"
00033 #include "viennacl/traits/stride.hpp"
00034 #include "viennacl/linalg/host_based/vector_operations.hpp"
00035 
00036 #ifdef VIENNACL_WITH_OPENCL
00037   #include "viennacl/linalg/opencl/vector_operations.hpp"
00038 #endif
00039 
00040 #ifdef VIENNACL_WITH_CUDA
00041   #include "viennacl/linalg/cuda/vector_operations.hpp"
00042 #endif
00043 
00044 namespace viennacl
00045 {
00046   namespace linalg
00047   {
00048     template <typename T, typename ScalarType1>
00049     void av(vector_base<T> & vec1,
00050             vector_base<T> const & vec2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha)
00051     {
00052       assert(viennacl::traits::size(vec1) == viennacl::traits::size(vec2) && bool("Incompatible vector sizes in v1 = v2 @ alpha: size(v1) != size(v2)"));
00053 
00054       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00055       {
00056         case viennacl::MAIN_MEMORY:
00057           viennacl::linalg::host_based::av(vec1, vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha);
00058           break;
00059 #ifdef VIENNACL_WITH_OPENCL
00060         case viennacl::OPENCL_MEMORY:
00061           viennacl::linalg::opencl::av(vec1, vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha);
00062           break;
00063 #endif
00064 #ifdef VIENNACL_WITH_CUDA
00065         case viennacl::CUDA_MEMORY:
00066           viennacl::linalg::cuda::av(vec1, vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha);
00067           break;
00068 #endif
00069         case viennacl::MEMORY_NOT_INITIALIZED:
00070           throw memory_exception("not initialised!");
00071         default:
00072           throw memory_exception("not implemented");
00073       }
00074     }
00075 
00076 
00077     template <typename T, typename ScalarType1, typename ScalarType2>
00078     void avbv(vector_base<T> & vec1,
00079               vector_base<T> const & vec2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha,
00080               vector_base<T> const & vec3, ScalarType2 const & beta,  vcl_size_t len_beta,  bool reciprocal_beta,  bool flip_sign_beta)
00081     {
00082       assert(viennacl::traits::size(vec1) == viennacl::traits::size(vec2) && bool("Incompatible vector sizes in v1 = v2 @ alpha + v3 @ beta: size(v1) != size(v2)"));
00083       assert(viennacl::traits::size(vec2) == viennacl::traits::size(vec3) && bool("Incompatible vector sizes in v1 = v2 @ alpha + v3 @ beta: size(v2) != size(v3)"));
00084 
00085       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00086       {
00087         case viennacl::MAIN_MEMORY:
00088           viennacl::linalg::host_based::avbv(vec1,
00089                                                   vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00090                                                   vec3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00091           break;
00092 #ifdef VIENNACL_WITH_OPENCL
00093         case viennacl::OPENCL_MEMORY:
00094           viennacl::linalg::opencl::avbv(vec1,
00095                                          vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00096                                          vec3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00097           break;
00098 #endif
00099 #ifdef VIENNACL_WITH_CUDA
00100         case viennacl::CUDA_MEMORY:
00101           viennacl::linalg::cuda::avbv(vec1,
00102                                        vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00103                                        vec3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00104           break;
00105 #endif
00106         case viennacl::MEMORY_NOT_INITIALIZED:
00107           throw memory_exception("not initialised!");
00108         default:
00109           throw memory_exception("not implemented");
00110       }
00111     }
00112 
00113 
00114     template <typename T, typename ScalarType1, typename ScalarType2>
00115     void avbv_v(vector_base<T> & vec1,
00116                 vector_base<T> const & vec2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha,
00117                 vector_base<T> const & vec3, ScalarType2 const & beta,  vcl_size_t len_beta,  bool reciprocal_beta,  bool flip_sign_beta)
00118     {
00119       assert(viennacl::traits::size(vec1) == viennacl::traits::size(vec2) && bool("Incompatible vector sizes in v1 += v2 @ alpha + v3 @ beta: size(v1) != size(v2)"));
00120       assert(viennacl::traits::size(vec2) == viennacl::traits::size(vec3) && bool("Incompatible vector sizes in v1 += v2 @ alpha + v3 @ beta: size(v2) != size(v3)"));
00121 
00122       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00123       {
00124         case viennacl::MAIN_MEMORY:
00125           viennacl::linalg::host_based::avbv_v(vec1,
00126                                                     vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00127                                                     vec3,  beta, len_beta,  reciprocal_beta,  flip_sign_beta);
00128           break;
00129 #ifdef VIENNACL_WITH_OPENCL
00130         case viennacl::OPENCL_MEMORY:
00131           viennacl::linalg::opencl::avbv_v(vec1,
00132                                            vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00133                                            vec3,  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::avbv_v(vec1,
00139                                          vec2, alpha, len_alpha, reciprocal_alpha, flip_sign_alpha,
00140                                          vec3,  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 
00157     template <typename T>
00158     void vector_assign(vector_base<T> & vec1, const T & alpha, bool up_to_internal_size = false)
00159     {
00160       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00161       {
00162         case viennacl::MAIN_MEMORY:
00163           viennacl::linalg::host_based::vector_assign(vec1, alpha, up_to_internal_size);
00164           break;
00165 #ifdef VIENNACL_WITH_OPENCL
00166         case viennacl::OPENCL_MEMORY:
00167           viennacl::linalg::opencl::vector_assign(vec1, alpha, up_to_internal_size);
00168           break;
00169 #endif
00170 #ifdef VIENNACL_WITH_CUDA
00171         case viennacl::CUDA_MEMORY:
00172           viennacl::linalg::cuda::vector_assign(vec1, alpha, up_to_internal_size);
00173           break;
00174 #endif
00175         case viennacl::MEMORY_NOT_INITIALIZED:
00176           throw memory_exception("not initialised!");
00177         default:
00178           throw memory_exception("not implemented");
00179       }
00180     }
00181 
00182 
00188     template <typename T>
00189     void vector_swap(vector_base<T> & vec1, vector_base<T> & vec2)
00190     {
00191       assert(viennacl::traits::size(vec1) == viennacl::traits::size(vec2) && bool("Incompatible vector sizes in vector_swap()"));
00192 
00193       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00194       {
00195         case viennacl::MAIN_MEMORY:
00196           viennacl::linalg::host_based::vector_swap(vec1, vec2);
00197           break;
00198 #ifdef VIENNACL_WITH_OPENCL
00199         case viennacl::OPENCL_MEMORY:
00200           viennacl::linalg::opencl::vector_swap(vec1, vec2);
00201           break;
00202 #endif
00203 #ifdef VIENNACL_WITH_CUDA
00204         case viennacl::CUDA_MEMORY:
00205           viennacl::linalg::cuda::vector_swap(vec1, vec2);
00206           break;
00207 #endif
00208         case viennacl::MEMORY_NOT_INITIALIZED:
00209           throw memory_exception("not initialised!");
00210         default:
00211           throw memory_exception("not implemented");
00212       }
00213     }
00214 
00215 
00217 
00218 
00219 
00225     template <typename T, typename OP>
00226     void element_op(vector_base<T> & vec1,
00227                     vector_expression<const vector_base<T>, const vector_base<T>, OP> const & proxy)
00228     {
00229       assert(viennacl::traits::size(vec1) == viennacl::traits::size(proxy) && bool("Incompatible vector sizes in element_op()"));
00230 
00231       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00232       {
00233         case viennacl::MAIN_MEMORY:
00234           viennacl::linalg::host_based::element_op(vec1, proxy);
00235           break;
00236 #ifdef VIENNACL_WITH_OPENCL
00237         case viennacl::OPENCL_MEMORY:
00238           viennacl::linalg::opencl::element_op(vec1, proxy);
00239           break;
00240 #endif
00241 #ifdef VIENNACL_WITH_CUDA
00242         case viennacl::CUDA_MEMORY:
00243           viennacl::linalg::cuda::element_op(vec1, proxy);
00244           break;
00245 #endif
00246         case viennacl::MEMORY_NOT_INITIALIZED:
00247           throw memory_exception("not initialised!");
00248         default:
00249           throw memory_exception("not implemented");
00250       }
00251     }
00252 
00255 // Helper macro for generating binary element-wise operations such as element_prod(), element_div(), element_pow() without unnecessary code duplication */
00256 #define VIENNACL_GENERATE_BINARY_ELEMENTOPERATION_OVERLOADS(OPNAME) \
00257     template <typename T> \
00258     viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<op_##OPNAME> > \
00259     element_##OPNAME(vector_base<T> const & v1, vector_base<T> const & v2) \
00260     { \
00261       return viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<op_##OPNAME> >(v1, v2); \
00262     } \
00263 \
00264     template <typename V1, typename V2, typename OP, typename T> \
00265     viennacl::vector_expression<const vector_expression<const V1, const V2, OP>, const vector_base<T>, op_element_binary<op_##OPNAME> > \
00266     element_##OPNAME(vector_expression<const V1, const V2, OP> const & proxy, vector_base<T> const & v2) \
00267     { \
00268       return viennacl::vector_expression<const vector_expression<const V1, const V2, OP>, const vector_base<T>, op_element_binary<op_##OPNAME> >(proxy, v2); \
00269     } \
00270 \
00271     template <typename T, typename V2, typename V3, typename OP> \
00272     viennacl::vector_expression<const vector_base<T>, const vector_expression<const V2, const V3, OP>, op_element_binary<op_##OPNAME> > \
00273     element_##OPNAME(vector_base<T> const & v1, vector_expression<const V2, const V3, OP> const & proxy) \
00274     { \
00275       return viennacl::vector_expression<const vector_base<T>, const vector_expression<const V2, const V3, OP>, op_element_binary<op_##OPNAME> >(v1, proxy); \
00276     } \
00277 \
00278     template <typename V1, typename V2, typename OP1, \
00279               typename V3, typename V4, typename OP2> \
00280     viennacl::vector_expression<const vector_expression<const V1, const V2, OP1>, \
00281                                 const vector_expression<const V3, const V4, OP2>, \
00282                                 op_element_binary<op_##OPNAME> > \
00283     element_##OPNAME(vector_expression<const V1, const V2, OP1> const & proxy1, \
00284                      vector_expression<const V3, const V4, OP2> const & proxy2) \
00285     {\
00286       return viennacl::vector_expression<const vector_expression<const V1, const V2, OP1>, \
00287                                          const vector_expression<const V3, const V4, OP2>, \
00288                                          op_element_binary<op_##OPNAME> >(proxy1, proxy2); \
00289     }
00290 
00291     VIENNACL_GENERATE_BINARY_ELEMENTOPERATION_OVERLOADS(prod)  //for element_prod()
00292     VIENNACL_GENERATE_BINARY_ELEMENTOPERATION_OVERLOADS(div)   //for element_div()
00293     VIENNACL_GENERATE_BINARY_ELEMENTOPERATION_OVERLOADS(pow)   //for element_pow()
00294 
00295 #undef VIENNACL_GENERATE_BINARY_ELEMENTOPERATION_OVERLOADS
00296 
00297 // Helper macro for generating unary element-wise operations such as element_exp(), element_sin(), etc. without unnecessary code duplication */
00298 #define VIENNACL_MAKE_UNARY_ELEMENT_OP(funcname) \
00299     template <typename T> \
00300     viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<op_##funcname> > \
00301     element_##funcname(vector_base<T> const & v) \
00302     { \
00303       return viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<op_##funcname> >(v, v); \
00304     } \
00305     template <typename LHS, typename RHS, typename OP> \
00306     viennacl::vector_expression<const vector_expression<const LHS, const RHS, OP>, \
00307                                 const vector_expression<const LHS, const RHS, OP>, \
00308                                 op_element_unary<op_##funcname> > \
00309     element_##funcname(vector_expression<const LHS, const RHS, OP> const & proxy) \
00310     { \
00311       return viennacl::vector_expression<const vector_expression<const LHS, const RHS, OP>, \
00312                                          const vector_expression<const LHS, const RHS, OP>, \
00313                                          op_element_unary<op_##funcname> >(proxy, proxy); \
00314     } \
00315 
00316     VIENNACL_MAKE_UNARY_ELEMENT_OP(abs)
00317     VIENNACL_MAKE_UNARY_ELEMENT_OP(acos)
00318     VIENNACL_MAKE_UNARY_ELEMENT_OP(asin)
00319     VIENNACL_MAKE_UNARY_ELEMENT_OP(atan)
00320     VIENNACL_MAKE_UNARY_ELEMENT_OP(ceil)
00321     VIENNACL_MAKE_UNARY_ELEMENT_OP(cos)
00322     VIENNACL_MAKE_UNARY_ELEMENT_OP(cosh)
00323     VIENNACL_MAKE_UNARY_ELEMENT_OP(exp)
00324     VIENNACL_MAKE_UNARY_ELEMENT_OP(fabs)
00325     VIENNACL_MAKE_UNARY_ELEMENT_OP(floor)
00326     VIENNACL_MAKE_UNARY_ELEMENT_OP(log)
00327     VIENNACL_MAKE_UNARY_ELEMENT_OP(log10)
00328     VIENNACL_MAKE_UNARY_ELEMENT_OP(sin)
00329     VIENNACL_MAKE_UNARY_ELEMENT_OP(sinh)
00330     VIENNACL_MAKE_UNARY_ELEMENT_OP(sqrt)
00331     VIENNACL_MAKE_UNARY_ELEMENT_OP(tan)
00332     VIENNACL_MAKE_UNARY_ELEMENT_OP(tanh)
00333 
00334 #undef VIENNACL_MAKE_UNARY_ELEMENT_OP
00335 
00338 
00339 
00340 
00341     //implementation of inner product:
00342     //namespace {
00343 
00350     template <typename T>
00351     void inner_prod_impl(vector_base<T> const & vec1,
00352                          vector_base<T> const & vec2,
00353                          scalar<T> & result)
00354     {
00355       assert( vec1.size() == vec2.size() && bool("Size mismatch") );
00356 
00357       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00358       {
00359         case viennacl::MAIN_MEMORY:
00360           viennacl::linalg::host_based::inner_prod_impl(vec1, vec2, result);
00361           break;
00362 #ifdef VIENNACL_WITH_OPENCL
00363         case viennacl::OPENCL_MEMORY:
00364           viennacl::linalg::opencl::inner_prod_impl(vec1, vec2, result);
00365           break;
00366 #endif
00367 #ifdef VIENNACL_WITH_CUDA
00368         case viennacl::CUDA_MEMORY:
00369           viennacl::linalg::cuda::inner_prod_impl(vec1, vec2, 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     // vector expression on lhs
00380     template <typename LHS, typename RHS, typename OP, typename T>
00381     void inner_prod_impl(viennacl::vector_expression<LHS, RHS, OP> const & vec1,
00382                          vector_base<T> const & vec2,
00383                          scalar<T> & result)
00384     {
00385       viennacl::vector<T> temp = vec1;
00386       inner_prod_impl(temp, vec2, result);
00387     }
00388 
00389 
00390     // vector expression on rhs
00391     template <typename T, typename LHS, typename RHS, typename OP>
00392     void inner_prod_impl(vector_base<T> const & vec1,
00393                          viennacl::vector_expression<LHS, RHS, OP> const & vec2,
00394                          scalar<T> & result)
00395     {
00396       viennacl::vector<T> temp = vec2;
00397       inner_prod_impl(vec1, temp, result);
00398     }
00399 
00400 
00401     // vector expression on lhs and rhs
00402     template <typename LHS1, typename RHS1, typename OP1,
00403               typename LHS2, typename RHS2, typename OP2, typename T>
00404     void inner_prod_impl(viennacl::vector_expression<LHS1, RHS1, OP1> const & vec1,
00405                          viennacl::vector_expression<LHS2, RHS2, OP2> const & vec2,
00406                          scalar<T> & result)
00407     {
00408       viennacl::vector<T> temp1 = vec1;
00409       viennacl::vector<T> temp2 = vec2;
00410       inner_prod_impl(temp1, temp2, result);
00411     }
00412 
00413 
00414 
00415 
00422     template <typename T>
00423     void inner_prod_cpu(vector_base<T> const & vec1,
00424                         vector_base<T> const & vec2,
00425                         T & result)
00426     {
00427       assert( vec1.size() == vec2.size() && bool("Size mismatch") );
00428 
00429       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00430       {
00431         case viennacl::MAIN_MEMORY:
00432           viennacl::linalg::host_based::inner_prod_impl(vec1, vec2, result);
00433           break;
00434 #ifdef VIENNACL_WITH_OPENCL
00435         case viennacl::OPENCL_MEMORY:
00436           viennacl::linalg::opencl::inner_prod_cpu(vec1, vec2, result);
00437           break;
00438 #endif
00439 #ifdef VIENNACL_WITH_CUDA
00440         case viennacl::CUDA_MEMORY:
00441           viennacl::linalg::cuda::inner_prod_cpu(vec1, vec2, result);
00442           break;
00443 #endif
00444         case viennacl::MEMORY_NOT_INITIALIZED:
00445           throw memory_exception("not initialised!");
00446         default:
00447           throw memory_exception("not implemented");
00448       }
00449     }
00450 
00451     // vector expression on lhs
00452     template <typename LHS, typename RHS, typename OP, typename T>
00453     void inner_prod_cpu(viennacl::vector_expression<LHS, RHS, OP> const & vec1,
00454                         vector_base<T> const & vec2,
00455                         T & result)
00456     {
00457       viennacl::vector<T> temp = vec1;
00458       inner_prod_cpu(temp, vec2, result);
00459     }
00460 
00461 
00462     // vector expression on rhs
00463     template <typename T, typename LHS, typename RHS, typename OP>
00464     void inner_prod_cpu(vector_base<T> const & vec1,
00465                         viennacl::vector_expression<LHS, RHS, OP> const & vec2,
00466                         T & result)
00467     {
00468       viennacl::vector<T> temp = vec2;
00469       inner_prod_cpu(vec1, temp, result);
00470     }
00471 
00472 
00473     // vector expression on lhs and rhs
00474     template <typename LHS1, typename RHS1, typename OP1,
00475               typename LHS2, typename RHS2, typename OP2, typename S3>
00476     void inner_prod_cpu(viennacl::vector_expression<LHS1, RHS1, OP1> const & vec1,
00477                         viennacl::vector_expression<LHS2, RHS2, OP2> const & vec2,
00478                         S3 & result)
00479     {
00480       viennacl::vector<S3> temp1 = vec1;
00481       viennacl::vector<S3> temp2 = vec2;
00482       inner_prod_cpu(temp1, temp2, result);
00483     }
00484 
00485 
00486 
00493     template <typename T>
00494     void inner_prod_impl(vector_base<T> const & x,
00495                          vector_tuple<T> const & y_tuple,
00496                          vector_base<T> & result)
00497     {
00498       assert( x.size() == y_tuple.const_at(0).size() && bool("Size mismatch") );
00499       assert( result.size() == y_tuple.const_size() && bool("Number of elements does not match result size") );
00500 
00501       switch (viennacl::traits::handle(x).get_active_handle_id())
00502       {
00503         case viennacl::MAIN_MEMORY:
00504           viennacl::linalg::host_based::inner_prod_impl(x, y_tuple, result);
00505           break;
00506 #ifdef VIENNACL_WITH_OPENCL
00507         case viennacl::OPENCL_MEMORY:
00508           viennacl::linalg::opencl::inner_prod_impl(x, y_tuple, result);
00509           break;
00510 #endif
00511 #ifdef VIENNACL_WITH_CUDA
00512         case viennacl::CUDA_MEMORY:
00513           viennacl::linalg::cuda::inner_prod_impl(x, y_tuple, result);
00514           break;
00515 #endif
00516         case viennacl::MEMORY_NOT_INITIALIZED:
00517           throw memory_exception("not initialised!");
00518         default:
00519           throw memory_exception("not implemented");
00520       }
00521     }
00522 
00523 
00529     template <typename T>
00530     void norm_1_impl(vector_base<T> const & vec,
00531                      scalar<T> & result)
00532     {
00533       switch (viennacl::traits::handle(vec).get_active_handle_id())
00534       {
00535         case viennacl::MAIN_MEMORY:
00536           viennacl::linalg::host_based::norm_1_impl(vec, result);
00537           break;
00538 #ifdef VIENNACL_WITH_OPENCL
00539         case viennacl::OPENCL_MEMORY:
00540           viennacl::linalg::opencl::norm_1_impl(vec, result);
00541           break;
00542 #endif
00543 #ifdef VIENNACL_WITH_CUDA
00544         case viennacl::CUDA_MEMORY:
00545           viennacl::linalg::cuda::norm_1_impl(vec, result);
00546           break;
00547 #endif
00548         case viennacl::MEMORY_NOT_INITIALIZED:
00549           throw memory_exception("not initialised!");
00550         default:
00551           throw memory_exception("not implemented");
00552       }
00553     }
00554 
00555 
00561     template <typename LHS, typename RHS, typename OP, typename S2>
00562     void norm_1_impl(viennacl::vector_expression<LHS, RHS, OP> const & vec,
00563                      S2 & result)
00564     {
00565       viennacl::vector<typename viennacl::result_of::cpu_value_type<S2>::type> temp = vec;
00566       norm_1_impl(temp, result);
00567     }
00568 
00569 
00570 
00576     template <typename T>
00577     void norm_1_cpu(vector_base<T> const & vec,
00578                     T & result)
00579     {
00580       switch (viennacl::traits::handle(vec).get_active_handle_id())
00581       {
00582         case viennacl::MAIN_MEMORY:
00583           viennacl::linalg::host_based::norm_1_impl(vec, result);
00584           break;
00585 #ifdef VIENNACL_WITH_OPENCL
00586         case viennacl::OPENCL_MEMORY:
00587           viennacl::linalg::opencl::norm_1_cpu(vec, result);
00588           break;
00589 #endif
00590 #ifdef VIENNACL_WITH_CUDA
00591         case viennacl::CUDA_MEMORY:
00592           viennacl::linalg::cuda::norm_1_cpu(vec, result);
00593           break;
00594 #endif
00595         case viennacl::MEMORY_NOT_INITIALIZED:
00596           throw memory_exception("not initialised!");
00597         default:
00598           throw memory_exception("not implemented");
00599       }
00600     }
00601 
00607     template <typename LHS, typename RHS, typename OP, typename S2>
00608     void norm_1_cpu(viennacl::vector_expression<LHS, RHS, OP> const & vec,
00609                     S2 & result)
00610     {
00611       viennacl::vector<typename viennacl::result_of::cpu_value_type<LHS>::type> temp = vec;
00612       norm_1_cpu(temp, result);
00613     }
00614 
00615 
00616 
00617 
00623     template <typename T>
00624     void norm_2_impl(vector_base<T> const & vec,
00625                      scalar<T> & result)
00626     {
00627       switch (viennacl::traits::handle(vec).get_active_handle_id())
00628       {
00629         case viennacl::MAIN_MEMORY:
00630           viennacl::linalg::host_based::norm_2_impl(vec, result);
00631           break;
00632 #ifdef VIENNACL_WITH_OPENCL
00633         case viennacl::OPENCL_MEMORY:
00634           viennacl::linalg::opencl::norm_2_impl(vec, result);
00635           break;
00636 #endif
00637 #ifdef VIENNACL_WITH_CUDA
00638         case viennacl::CUDA_MEMORY:
00639           viennacl::linalg::cuda::norm_2_impl(vec, result);
00640           break;
00641 #endif
00642         case viennacl::MEMORY_NOT_INITIALIZED:
00643           throw memory_exception("not initialised!");
00644         default:
00645           throw memory_exception("not implemented");
00646       }
00647     }
00648 
00654     template <typename LHS, typename RHS, typename OP, typename T>
00655     void norm_2_impl(viennacl::vector_expression<LHS, RHS, OP> const & vec,
00656                      scalar<T> & result)
00657     {
00658       viennacl::vector<T> temp = vec;
00659       norm_2_impl(temp, result);
00660     }
00661 
00662 
00668     template <typename T>
00669     void norm_2_cpu(vector_base<T> const & vec,
00670                     T & result)
00671     {
00672       switch (viennacl::traits::handle(vec).get_active_handle_id())
00673       {
00674         case viennacl::MAIN_MEMORY:
00675           viennacl::linalg::host_based::norm_2_impl(vec, result);
00676           break;
00677 #ifdef VIENNACL_WITH_OPENCL
00678         case viennacl::OPENCL_MEMORY:
00679           viennacl::linalg::opencl::norm_2_cpu(vec, result);
00680           break;
00681 #endif
00682 #ifdef VIENNACL_WITH_CUDA
00683         case viennacl::CUDA_MEMORY:
00684           viennacl::linalg::cuda::norm_2_cpu(vec, result);
00685           break;
00686 #endif
00687         case viennacl::MEMORY_NOT_INITIALIZED:
00688           throw memory_exception("not initialised!");
00689         default:
00690           throw memory_exception("not implemented");
00691       }
00692     }
00693 
00699     template <typename LHS, typename RHS, typename OP, typename S2>
00700     void norm_2_cpu(viennacl::vector_expression<LHS, RHS, OP> const & vec,
00701                     S2 & result)
00702     {
00703       viennacl::vector<typename viennacl::result_of::cpu_value_type<LHS>::type> temp = vec;
00704       norm_2_cpu(temp, result);
00705     }
00706 
00707 
00708 
00709 
00715     template <typename T>
00716     void norm_inf_impl(vector_base<T> const & vec,
00717                        scalar<T> & result)
00718     {
00719       switch (viennacl::traits::handle(vec).get_active_handle_id())
00720       {
00721         case viennacl::MAIN_MEMORY:
00722           viennacl::linalg::host_based::norm_inf_impl(vec, result);
00723           break;
00724 #ifdef VIENNACL_WITH_OPENCL
00725         case viennacl::OPENCL_MEMORY:
00726           viennacl::linalg::opencl::norm_inf_impl(vec, result);
00727           break;
00728 #endif
00729 #ifdef VIENNACL_WITH_CUDA
00730         case viennacl::CUDA_MEMORY:
00731           viennacl::linalg::cuda::norm_inf_impl(vec, result);
00732           break;
00733 #endif
00734         case viennacl::MEMORY_NOT_INITIALIZED:
00735           throw memory_exception("not initialised!");
00736         default:
00737           throw memory_exception("not implemented");
00738       }
00739     }
00740 
00746     template <typename LHS, typename RHS, typename OP, typename T>
00747     void norm_inf_impl(viennacl::vector_expression<LHS, RHS, OP> const & vec,
00748                        scalar<T> & result)
00749     {
00750       viennacl::vector<T> temp = vec;
00751       norm_inf_impl(temp, result);
00752     }
00753 
00754 
00760     template <typename T>
00761     void norm_inf_cpu(vector_base<T> const & vec,
00762                       T & result)
00763     {
00764       switch (viennacl::traits::handle(vec).get_active_handle_id())
00765       {
00766         case viennacl::MAIN_MEMORY:
00767           viennacl::linalg::host_based::norm_inf_impl(vec, result);
00768           break;
00769 #ifdef VIENNACL_WITH_OPENCL
00770         case viennacl::OPENCL_MEMORY:
00771           viennacl::linalg::opencl::norm_inf_cpu(vec, result);
00772           break;
00773 #endif
00774 #ifdef VIENNACL_WITH_CUDA
00775         case viennacl::CUDA_MEMORY:
00776           viennacl::linalg::cuda::norm_inf_cpu(vec, result);
00777           break;
00778 #endif
00779         case viennacl::MEMORY_NOT_INITIALIZED:
00780           throw memory_exception("not initialised!");
00781         default:
00782           throw memory_exception("not implemented");
00783       }
00784     }
00785 
00791     template <typename LHS, typename RHS, typename OP, typename S2>
00792     void norm_inf_cpu(viennacl::vector_expression<LHS, RHS, OP> const & vec,
00793                       S2 & result)
00794     {
00795       viennacl::vector<typename viennacl::result_of::cpu_value_type<LHS>::type> temp = vec;
00796       norm_inf_cpu(temp, result);
00797     }
00798 
00799 
00800     //This function should return a CPU scalar, otherwise statements like
00801     // vcl_rhs[index_norm_inf(vcl_rhs)]
00802     // are ambiguous
00808     template <typename T>
00809     vcl_size_t index_norm_inf(vector_base<T> const & vec)
00810     {
00811       switch (viennacl::traits::handle(vec).get_active_handle_id())
00812       {
00813         case viennacl::MAIN_MEMORY:
00814           return viennacl::linalg::host_based::index_norm_inf(vec);
00815 #ifdef VIENNACL_WITH_OPENCL
00816         case viennacl::OPENCL_MEMORY:
00817           return viennacl::linalg::opencl::index_norm_inf(vec);
00818 #endif
00819 #ifdef VIENNACL_WITH_CUDA
00820         case viennacl::CUDA_MEMORY:
00821           return viennacl::linalg::cuda::index_norm_inf(vec);
00822 #endif
00823         case viennacl::MEMORY_NOT_INITIALIZED:
00824           throw memory_exception("not initialised!");
00825         default:
00826           throw memory_exception("not implemented");
00827       }
00828     }
00829 
00834     template <typename LHS, typename RHS, typename OP>
00835     vcl_size_t index_norm_inf(viennacl::vector_expression<LHS, RHS, OP> const & vec)
00836     {
00837       viennacl::vector<typename viennacl::result_of::cpu_value_type<LHS>::type> temp = vec;
00838       return index_norm_inf(temp);
00839     }
00840 
00841 
00851     template <typename T>
00852     void plane_rotation(vector_base<T> & vec1,
00853                         vector_base<T> & vec2,
00854                         T alpha, T beta)
00855     {
00856       switch (viennacl::traits::handle(vec1).get_active_handle_id())
00857       {
00858         case viennacl::MAIN_MEMORY:
00859           viennacl::linalg::host_based::plane_rotation(vec1, vec2, alpha, beta);
00860           break;
00861 #ifdef VIENNACL_WITH_OPENCL
00862         case viennacl::OPENCL_MEMORY:
00863           viennacl::linalg::opencl::plane_rotation(vec1, vec2, alpha, beta);
00864           break;
00865 #endif
00866 #ifdef VIENNACL_WITH_CUDA
00867         case viennacl::CUDA_MEMORY:
00868           viennacl::linalg::cuda::plane_rotation(vec1, vec2, alpha, beta);
00869           break;
00870 #endif
00871         case viennacl::MEMORY_NOT_INITIALIZED:
00872           throw memory_exception("not initialised!");
00873         default:
00874           throw memory_exception("not implemented");
00875       }
00876     }
00877 
00878   } //namespace linalg
00879 } //namespace viennacl
00880 
00881 
00882 #endif