ViennaCL - The Vienna Computing Library
1.5.0
|
00001 #ifndef VIENNACL_VECTOR_HPP_ 00002 #define VIENNACL_VECTOR_HPP_ 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2013, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 Portions of this software are copyright by UChicago Argonne, LLC. 00009 00010 ----------------- 00011 ViennaCL - The Vienna Computing Library 00012 ----------------- 00013 00014 Project Head: Karl Rupp rupp@iue.tuwien.ac.at 00015 00016 (A list of authors and contributors can be found in the PDF manual) 00017 00018 License: MIT (X11), see file LICENSE in the base directory 00019 ============================================================================= */ 00020 00027 #include "viennacl/forwards.h" 00028 #include "viennacl/backend/memory.hpp" 00029 #include "viennacl/scalar.hpp" 00030 #include "viennacl/tools/tools.hpp" 00031 #include "viennacl/tools/entry_proxy.hpp" 00032 #include "viennacl/linalg/detail/op_executor.hpp" 00033 #include "viennacl/linalg/vector_operations.hpp" 00034 #include "viennacl/meta/result_of.hpp" 00035 //#include "viennacl/rand/utils.hpp" 00036 #include "viennacl/context.hpp" 00037 #include "viennacl/traits/handle.hpp" 00038 00039 namespace viennacl 00040 { 00041 00046 template<typename SCALARTYPE> 00047 class implicit_vector_base 00048 { 00049 protected: 00050 typedef vcl_size_t size_type; 00051 implicit_vector_base(size_type s, vcl_size_t i, std::pair<SCALARTYPE, bool> v, viennacl::context ctx) : size_(s), index_(std::make_pair(true,i)), value_(v), ctx_(ctx){ } 00052 implicit_vector_base(size_type s, std::pair<SCALARTYPE, bool> v, viennacl::context ctx) : size_(s), index_(std::make_pair(false,0)), value_(v), ctx_(ctx){ } 00053 00054 public: 00055 typedef SCALARTYPE const & const_reference; 00056 typedef SCALARTYPE cpu_value_type; 00057 00058 viennacl::context context() const { return ctx_; } 00059 00060 size_type size() const { return size_; } 00061 00062 cpu_value_type value() const { return value_.first; } 00063 00064 bool is_value_static() const { return value_.second; } 00065 00066 vcl_size_t index() const { return index_.second; } 00067 00068 bool has_index() const { return index_.first; } 00069 00070 cpu_value_type operator()(size_type i) const { 00071 if(index_.first) 00072 return (i==index_.second)?value_.first:0; 00073 return value_.first; 00074 } 00075 00076 cpu_value_type operator[](size_type i) const { 00077 if(index_.first) 00078 return (i==index_.second)?value_.first:0; 00079 return 00080 value_.first; 00081 } 00082 00083 protected: 00084 size_type size_; 00085 std::pair<bool, vcl_size_t> index_; 00086 std::pair<SCALARTYPE, bool> value_; 00087 viennacl::context ctx_; 00088 }; 00089 00091 template <typename SCALARTYPE> 00092 class unit_vector : public implicit_vector_base<SCALARTYPE> 00093 { 00094 typedef implicit_vector_base<SCALARTYPE> base_type; 00095 public: 00096 typedef typename base_type::size_type size_type; 00097 unit_vector(size_type s, size_type ind, viennacl::context ctx = viennacl::context()) : base_type(s, ind, std::make_pair(SCALARTYPE(1),true), ctx) 00098 { 00099 assert( (ind < s) && bool("Provided index out of range!") ); 00100 } 00101 }; 00102 00103 00105 template <typename SCALARTYPE> 00106 class zero_vector : public implicit_vector_base<SCALARTYPE> 00107 { 00108 typedef implicit_vector_base<SCALARTYPE> base_type; 00109 public: 00110 typedef typename base_type::size_type size_type; 00111 typedef SCALARTYPE const_reference; 00112 zero_vector(size_type s, viennacl::context ctx = viennacl::context()) : base_type(s, std::make_pair(SCALARTYPE(0),true), ctx) {} 00113 }; 00114 00116 template <typename SCALARTYPE> 00117 class one_vector : public implicit_vector_base<SCALARTYPE> 00118 { 00119 typedef implicit_vector_base<SCALARTYPE> base_type; 00120 public: 00121 typedef typename base_type::size_type size_type; 00122 typedef SCALARTYPE const_reference; 00123 one_vector(size_type s, viennacl::context ctx = viennacl::context()) : base_type(s, std::make_pair(SCALARTYPE(1),true), ctx) {} 00124 }; 00125 00126 00128 template <typename SCALARTYPE> 00129 class scalar_vector : public implicit_vector_base<SCALARTYPE> 00130 { 00131 typedef implicit_vector_base<SCALARTYPE> base_type; 00132 public: 00133 typedef typename base_type::size_type size_type; 00134 typedef SCALARTYPE const & const_reference; 00135 00136 scalar_vector(size_type s, SCALARTYPE val, viennacl::context ctx = viennacl::context()) : base_type(s, std::make_pair(val,false), ctx) {} 00137 }; 00138 00139 00140 //#ifdef VIENNACL_WITH_OPENCL 00141 // template<class SCALARTYPE, class DISTRIBUTION> 00142 // rand::random_vector_t<SCALARTYPE, DISTRIBUTION> random_vector(unsigned int size, DISTRIBUTION const & distribution){ 00143 // return rand::random_vector_t<SCALARTYPE,DISTRIBUTION>(size,distribution); 00144 // } 00145 //#endif 00146 00147 00148 // 00149 // Vector expression 00150 // 00151 00164 template <typename LHS, typename RHS, typename OP> 00165 class vector_expression 00166 { 00167 typedef typename viennacl::result_of::reference_if_nonscalar<LHS>::type lhs_reference_type; 00168 typedef typename viennacl::result_of::reference_if_nonscalar<RHS>::type rhs_reference_type; 00169 00170 public: 00171 enum { alignment = 1 }; 00172 00175 typedef vcl_size_t size_type; 00176 00177 vector_expression(LHS & l, RHS & r) : lhs_(l), rhs_(r) {} 00178 00181 lhs_reference_type lhs() const { return lhs_; } 00184 rhs_reference_type rhs() const { return rhs_; } 00185 00187 size_type size() const { return viennacl::traits::size(*this); } 00188 00189 private: 00191 lhs_reference_type lhs_; 00193 rhs_reference_type rhs_; 00194 }; 00195 00214 template<class SCALARTYPE, unsigned int ALIGNMENT> 00215 class const_vector_iterator 00216 { 00217 typedef const_vector_iterator<SCALARTYPE, ALIGNMENT> self_type; 00218 public: 00219 typedef scalar<SCALARTYPE> value_type; 00220 typedef vcl_ptrdiff_t difference_type; 00221 typedef viennacl::backend::mem_handle handle_type; 00222 00223 //const_vector_iterator() {} 00224 00231 const_vector_iterator(vector_base<SCALARTYPE> const & vec, 00232 vcl_size_t index, 00233 vcl_size_t start = 0, 00234 vcl_ptrdiff_t stride = 1) : elements_(vec.handle()), index_(index), start_(start), stride_(stride) {} 00235 00242 const_vector_iterator(handle_type const & elements, 00243 vcl_size_t index, 00244 vcl_size_t start = 0, 00245 vcl_ptrdiff_t stride = 1) : elements_(elements), index_(index), start_(start), stride_(stride) {} 00246 00248 value_type operator*(void) const 00249 { 00250 value_type result; 00251 result = const_entry_proxy<SCALARTYPE>(start_ + index_ * stride_, elements_); 00252 return result; 00253 } 00254 self_type operator++(void) { index_ += stride_; return *this; } 00255 self_type operator++(int) { self_type tmp = *this; ++(*this); return tmp; } 00256 00257 bool operator==(self_type const & other) const { return index_ == other.index_; } 00258 bool operator!=(self_type const & other) const { return index_ != other.index_; } 00259 00260 // self_type & operator=(self_type const & other) 00261 // { 00262 // index_ = other._index; 00263 // elements_ = other._elements; 00264 // return *this; 00265 // } 00266 00267 difference_type operator-(self_type const & other) const 00268 { 00269 assert( (other.start_ == start_) && (other.stride_ == stride_) && bool("Iterators are not from the same vector (proxy)!")); 00270 return static_cast<difference_type>(index_) - static_cast<difference_type>(other.index_); 00271 } 00272 self_type operator+(difference_type diff) const { return self_type(elements_, index_ + diff * stride_, start_, stride_); } 00273 00274 //vcl_size_t index() const { return index_; } 00276 vcl_size_t offset() const { return start_ + index_ * stride_; } 00277 00279 vcl_size_t stride() const { return stride_; } 00280 handle_type const & handle() const { return elements_; } 00281 00282 protected: 00284 handle_type const & elements_; 00285 vcl_size_t index_; //offset from the beginning of elements_ 00286 vcl_size_t start_; 00287 vcl_ptrdiff_t stride_; 00288 }; 00289 00290 00310 template<class SCALARTYPE, unsigned int ALIGNMENT> 00311 class vector_iterator : public const_vector_iterator<SCALARTYPE, ALIGNMENT> 00312 { 00313 typedef const_vector_iterator<SCALARTYPE, ALIGNMENT> base_type; 00314 typedef vector_iterator<SCALARTYPE, ALIGNMENT> self_type; 00315 public: 00316 typedef typename base_type::handle_type handle_type; 00317 typedef typename base_type::difference_type difference_type; 00318 00319 vector_iterator() : base_type(), elements_(NULL) {} 00320 vector_iterator(handle_type & elements, 00321 vcl_size_t index, 00322 vcl_size_t start = 0, 00323 vcl_ptrdiff_t stride = 1) : base_type(elements, index, start, stride), elements_(elements) {} 00330 vector_iterator(vector_base<SCALARTYPE> & vec, 00331 vcl_size_t index, 00332 vcl_size_t start = 0, 00333 vcl_ptrdiff_t stride = 1) : base_type(vec, index, start, stride), elements_(vec.handle()) {} 00334 //vector_iterator(base_type const & b) : base_type(b) {} 00335 00336 typename base_type::value_type operator*(void) 00337 { 00338 typename base_type::value_type result; 00339 result = entry_proxy<SCALARTYPE>(base_type::start_ + base_type::index_ * base_type::stride_, elements_); 00340 return result; 00341 } 00342 00343 difference_type operator-(self_type const & other) const { difference_type result = base_type::index_; return (result - static_cast<difference_type>(other.index_)); } 00344 self_type operator+(difference_type diff) const { return self_type(elements_, base_type::index_ + diff * base_type::stride_, base_type::start_, base_type::stride_); } 00345 00346 handle_type & handle() { return elements_; } 00347 handle_type const & handle() const { return base_type::elements_; } 00348 00349 //operator base_type() const 00350 //{ 00351 // return base_type(base_type::elements_, base_type::index_, base_type::start_, base_type::stride_); 00352 //} 00353 private: 00354 handle_type & elements_; 00355 }; 00356 00357 00362 template<class SCALARTYPE, typename SizeType /* see forwards.h for default type */, typename DistanceType /* see forwards.h for default type */> 00363 class vector_base 00364 { 00365 typedef vector_base<SCALARTYPE> self_type; 00366 00367 public: 00368 typedef scalar<SCALARTYPE> value_type; 00369 typedef SCALARTYPE cpu_value_type; 00370 typedef viennacl::backend::mem_handle handle_type; 00371 typedef SizeType size_type; 00372 typedef DistanceType difference_type; 00373 typedef const_vector_iterator<SCALARTYPE, 1> const_iterator; 00374 typedef vector_iterator<SCALARTYPE, 1> iterator; 00375 00376 static const size_type alignment = 128; 00377 00380 explicit vector_base() : size_(0), start_(0), stride_(1), internal_size_(0) { /* Note: One must not call ::init() here because a vector might have been created globally before the backend has become available */ } 00381 00391 explicit vector_base(viennacl::backend::mem_handle & h, 00392 size_type vec_size, size_type vec_start, difference_type vec_stride) 00393 : size_(vec_size), start_(vec_start), stride_(vec_stride), internal_size_(vec_size), elements_(h) {} 00394 00396 explicit vector_base(size_type vec_size, viennacl::context ctx = viennacl::context()) 00397 : size_(vec_size), start_(0), stride_(1), internal_size_(viennacl::tools::align_to_multiple<size_type>(size_, alignment)) 00398 { 00399 if (size_ > 0) 00400 { 00401 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), ctx); 00402 clear(); 00403 } 00404 } 00405 00406 // CUDA or host memory: 00407 explicit vector_base(SCALARTYPE * ptr_to_mem, viennacl::memory_types mem_type, size_type vec_size, vcl_size_t start = 0, difference_type stride = 1) 00408 : size_(vec_size), start_(start), stride_(stride), internal_size_(vec_size) 00409 { 00410 if (mem_type == viennacl::CUDA_MEMORY) 00411 { 00412 #ifdef VIENNACL_WITH_CUDA 00413 elements_.switch_active_handle_id(viennacl::CUDA_MEMORY); 00414 elements_.cuda_handle().reset(reinterpret_cast<char*>(ptr_to_mem)); 00415 elements_.cuda_handle().inc(); //prevents that the user-provided memory is deleted once the vector object is destroyed. 00416 #else 00417 throw cuda_not_available_exception(); 00418 #endif 00419 } 00420 else if (mem_type == viennacl::MAIN_MEMORY) 00421 { 00422 elements_.switch_active_handle_id(viennacl::MAIN_MEMORY); 00423 elements_.ram_handle().reset(reinterpret_cast<char*>(ptr_to_mem)); 00424 elements_.ram_handle().inc(); //prevents that the user-provided memory is deleted once the vector object is destroyed. 00425 } 00426 00427 elements_.raw_size(sizeof(SCALARTYPE) * vec_size); 00428 00429 } 00430 00431 #ifdef VIENNACL_WITH_OPENCL 00432 00440 explicit vector_base(cl_mem existing_mem, size_type vec_size, size_type start = 0, difference_type stride = 1, viennacl::context ctx = viennacl::context()) 00441 : size_(vec_size), start_(start), stride_(stride), internal_size_(vec_size) 00442 { 00443 elements_.switch_active_handle_id(viennacl::OPENCL_MEMORY); 00444 elements_.opencl_handle() = existing_mem; 00445 elements_.opencl_handle().inc(); //prevents that the user-provided memory is deleted once the vector object is destroyed. 00446 elements_.opencl_handle().context(ctx.opencl_context()); 00447 elements_.raw_size(sizeof(SCALARTYPE) * vec_size); 00448 } 00449 #endif 00450 00452 /*template<class DISTRIBUTION> 00453 vector(rand::random_vector_t<SCALARTYPE, DISTRIBUTION> v) : size_(v.size) 00454 { 00455 if(size_ > 0) 00456 { 00457 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00458 rand::buffer_dumper<SCALARTYPE, DISTRIBUTION>::dump(elements_,v.distribution,0,size_); 00459 } 00460 } */ 00461 00462 template <typename LHS, typename RHS, typename OP> 00463 explicit vector_base(vector_expression<const LHS, const RHS, OP> const & proxy) 00464 : size_(viennacl::traits::size(proxy)), start_(0), stride_(1), internal_size_(viennacl::tools::align_to_multiple<size_type>(size_, alignment)) 00465 { 00466 if (size_ > 0) 00467 { 00468 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), viennacl::traits::context(proxy)); 00469 clear(); 00470 } 00471 self_type::operator=(proxy); 00472 } 00473 00474 00475 // 00476 // operator= 00477 // 00478 00479 00482 self_type & operator=(const self_type & vec) 00483 { 00484 assert( ( (vec.size() == size()) || (size() == 0) ) 00485 && bool("Incompatible vector sizes!")); 00486 00487 if (vec.size() > 0) 00488 { 00489 if (size_ == 0) 00490 { 00491 size_ = vec.size(); 00492 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00493 elements_.switch_active_handle_id(vec.handle().get_active_handle_id()); 00494 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), viennacl::traits::context(vec)); 00495 pad(); 00496 } 00497 00498 viennacl::linalg::av(*this, 00499 vec, cpu_value_type(1.0), 1, false, false); 00500 } 00501 00502 return *this; 00503 } 00504 00505 00510 template <typename LHS, typename RHS, typename OP> 00511 self_type & operator=(const vector_expression<const LHS, const RHS, OP> & proxy) 00512 { 00513 assert( ( (viennacl::traits::size(proxy) == size()) || (size() == 0) ) 00514 && bool("Incompatible vector sizes!")); 00515 00516 // initialize the necessary buffer 00517 if (size() == 0) 00518 { 00519 size_ = viennacl::traits::size(proxy); 00520 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00521 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), viennacl::traits::context(proxy)); 00522 pad(); 00523 } 00524 00525 linalg::detail::op_executor<self_type, op_assign, vector_expression<const LHS, const RHS, OP> >::apply(*this, proxy); 00526 00527 return *this; 00528 } 00529 00530 // assign vector range or vector slice 00531 template <typename T> 00532 self_type & 00533 operator = (const vector_base<T> & v1) 00534 { 00535 assert( ( (v1.size() == size()) || (size() == 0) ) 00536 && bool("Incompatible vector sizes!")); 00537 00538 if (size() == 0) 00539 { 00540 size_ = v1.size(); 00541 if (size_ > 0) 00542 { 00543 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00544 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), viennacl::traits::context(v1)); 00545 pad(); 00546 } 00547 } 00548 00549 viennacl::linalg::av(*this, 00550 v1, SCALARTYPE(1.0), 1, false, false); 00551 00552 return *this; 00553 } 00554 00556 self_type & operator = (unit_vector<SCALARTYPE> const & v) 00557 { 00558 assert( ( (v.size() == size()) || (size() == 0) ) 00559 && bool("Incompatible vector sizes!")); 00560 00561 if (size() == 0) 00562 { 00563 size_ = v.size(); 00564 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00565 if (size_ > 0) 00566 { 00567 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), v.context()); 00568 clear(); 00569 } 00570 } 00571 else 00572 viennacl::linalg::vector_assign(*this, SCALARTYPE(0)); 00573 00574 if (size_ > 0) 00575 this->operator()(v.index()) = SCALARTYPE(1); 00576 00577 return *this; 00578 } 00579 00581 self_type & operator = (zero_vector<SCALARTYPE> const & v) 00582 { 00583 assert( ( (v.size() == size()) || (size() == 0) ) 00584 && bool("Incompatible vector sizes!")); 00585 00586 if (size() == 0) 00587 { 00588 size_ = v.size(); 00589 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00590 if (size_ > 0) 00591 { 00592 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), v.context()); 00593 clear(); 00594 } 00595 } 00596 else 00597 viennacl::linalg::vector_assign(*this, SCALARTYPE(0)); 00598 00599 return *this; 00600 } 00601 00603 self_type & operator = (scalar_vector<SCALARTYPE> const & v) 00604 { 00605 assert( ( (v.size() == size()) || (size() == 0) ) 00606 && bool("Incompatible vector sizes!")); 00607 00608 if (size() == 0) 00609 { 00610 size_ = v.size(); 00611 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00612 if (size_ > 0) 00613 { 00614 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), v.context()); 00615 pad(); 00616 } 00617 } 00618 00619 if (size_ > 0) 00620 viennacl::linalg::vector_assign(*this, v[0]); 00621 00622 return *this; 00623 } 00624 00625 00626 00628 00629 //Note: The following operator overloads are defined in matrix_operations.hpp, compressed_matrix_operations.hpp and coordinate_matrix_operations.hpp 00630 //This is certainly not the nicest approach and will most likely by changed in the future, but it works :-) 00631 00632 //matrix<> 00637 template <typename F> 00638 self_type & operator=(const viennacl::vector_expression< const matrix_base<SCALARTYPE, F>, const vector_base<SCALARTYPE>, viennacl::op_prod> & proxy) 00639 { 00640 assert(viennacl::traits::size1(proxy.lhs()) == size() && bool("Size check failed for v1 = A * v2: size1(A) != size(v1)")); 00641 00642 // check for the special case x = A * x 00643 if (viennacl::traits::handle(proxy.rhs()) == viennacl::traits::handle(*this)) 00644 { 00645 viennacl::vector<SCALARTYPE> result(viennacl::traits::size1(proxy.lhs())); 00646 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result); 00647 *this = result; 00648 } 00649 else 00650 { 00651 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), *this); 00652 } 00653 return *this; 00654 } 00655 00656 00657 //transposed_matrix_proxy: 00662 template <typename F> 00663 self_type & operator=(const vector_expression< const matrix_expression< const matrix_base<SCALARTYPE, F>, const matrix_base<SCALARTYPE, F>, op_trans >, 00664 const vector_base<SCALARTYPE>, 00665 op_prod> & proxy) 00666 { 00667 assert(viennacl::traits::size1(proxy.lhs()) == size() && bool("Size check failed in v1 = trans(A) * v2: size2(A) != size(v1)")); 00668 00669 // check for the special case x = trans(A) * x 00670 if (viennacl::traits::handle(proxy.rhs()) == viennacl::traits::handle(*this)) 00671 { 00672 viennacl::vector<SCALARTYPE> result(viennacl::traits::size1(proxy.lhs())); 00673 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result); 00674 *this = result; 00675 } 00676 else 00677 { 00678 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), *this); 00679 } 00680 return *this; 00681 } 00682 00684 00685 00686 //read-write access to an element of the vector 00689 entry_proxy<SCALARTYPE> operator()(size_type index) 00690 { 00691 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00692 assert( index < size() && bool("Index out of bounds!") ); 00693 00694 return entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00695 } 00696 00699 entry_proxy<SCALARTYPE> operator[](size_type index) 00700 { 00701 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00702 assert( index < size() && bool("Index out of bounds!") ); 00703 00704 return entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00705 } 00706 00707 00710 const_entry_proxy<SCALARTYPE> operator()(size_type index) const 00711 { 00712 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00713 assert( index < size() && bool("Index out of bounds!") ); 00714 00715 return const_entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00716 } 00717 00720 const_entry_proxy<SCALARTYPE> operator[](size_type index) const 00721 { 00722 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00723 assert( index < size() && bool("Index out of bounds!") ); 00724 00725 return const_entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00726 } 00727 00728 // 00729 // Operator overloads with implicit conversion (thus cannot be made global without introducing additional headache) 00730 // 00731 self_type & operator += (const self_type & vec) 00732 { 00733 assert(vec.size() == size() && bool("Incompatible vector sizes!")); 00734 00735 if (size() > 0) 00736 viennacl::linalg::avbv(*this, 00737 *this, SCALARTYPE(1.0), 1, false, false, 00738 vec, SCALARTYPE(1.0), 1, false, false); 00739 return *this; 00740 } 00741 00742 self_type & operator -= (const self_type & vec) 00743 { 00744 assert(vec.size() == size() && bool("Incompatible vector sizes!")); 00745 00746 if (size() > 0) 00747 viennacl::linalg::avbv(*this, 00748 *this, SCALARTYPE(1.0), 1, false, false, 00749 vec, SCALARTYPE(-1.0), 1, false, false); 00750 return *this; 00751 } 00752 00753 template <typename LHS, typename RHS, typename OP> 00754 self_type & operator += (const vector_expression<const LHS, const RHS, OP> & proxy) 00755 { 00756 assert( (viennacl::traits::size(proxy) == size()) && bool("Incompatible vector sizes!")); 00757 assert( (size() > 0) && bool("Vector not yet initialized!") ); 00758 00759 linalg::detail::op_executor<self_type, op_inplace_add, vector_expression<const LHS, const RHS, OP> >::apply(*this, proxy); 00760 00761 return *this; 00762 } 00763 00764 template <typename LHS, typename RHS, typename OP> 00765 self_type & operator -= (const vector_expression<const LHS, const RHS, OP> & proxy) 00766 { 00767 assert( (viennacl::traits::size(proxy) == size()) && bool("Incompatible vector sizes!")); 00768 assert( (size() > 0) && bool("Vector not yet initialized!") ); 00769 00770 linalg::detail::op_executor<self_type, op_inplace_sub, vector_expression<const LHS, const RHS, OP> >::apply(*this, proxy); 00771 00772 return *this; 00773 } 00774 00777 self_type & operator *= (SCALARTYPE val) 00778 { 00779 if (size() > 0) 00780 viennacl::linalg::av(*this, 00781 *this, val, 1, false, false); 00782 return *this; 00783 } 00784 00787 self_type & operator /= (SCALARTYPE val) 00788 { 00789 if (size() > 0) 00790 viennacl::linalg::av(*this, 00791 *this, val, 1, true, false); 00792 return *this; 00793 } 00794 00795 00798 vector_expression< const self_type, const SCALARTYPE, op_mult> 00799 operator * (SCALARTYPE value) const 00800 { 00801 return vector_expression< const self_type, const SCALARTYPE, op_mult>(*this, value); 00802 } 00803 00804 00807 vector_expression< const self_type, const SCALARTYPE, op_div> 00808 operator / (SCALARTYPE value) const 00809 { 00810 return vector_expression< const self_type, const SCALARTYPE, op_div>(*this, value); 00811 } 00812 00813 00815 vector_expression<const self_type, const SCALARTYPE, op_mult> operator-() const 00816 { 00817 return vector_expression<const self_type, const SCALARTYPE, op_mult>(*this, SCALARTYPE(-1.0)); 00818 } 00819 00820 // 00822 // 00823 00825 iterator begin() 00826 { 00827 return iterator(*this, 0, start_, stride_); 00828 } 00829 00831 iterator end() 00832 { 00833 return iterator(*this, size(), start_, stride_); 00834 } 00835 00837 const_iterator begin() const 00838 { 00839 return const_iterator(*this, 0, start_, stride_); 00840 } 00841 00843 const_iterator end() const 00844 { 00845 return const_iterator(*this, size(), start_, stride_); 00846 } 00847 00850 self_type & swap(self_type & other) 00851 { 00852 viennacl::linalg::vector_swap(*this, other); 00853 return *this; 00854 }; 00855 00856 00859 size_type size() const { return size_; } 00860 00863 size_type internal_size() const { return internal_size_; } 00864 00867 size_type start() const { return start_; } 00868 00871 size_type stride() const { return stride_; } 00872 00873 00875 bool empty() const { return size_ == 0; } 00876 00878 const handle_type & handle() const { return elements_; } 00879 00881 handle_type & handle() { return elements_; } 00882 00885 void clear() 00886 { 00887 viennacl::linalg::vector_assign(*this, cpu_value_type(0.0), true); 00888 } 00889 00890 viennacl::memory_types memory_domain() const 00891 { 00892 return elements_.get_active_handle_id(); 00893 } 00894 00895 protected: 00896 00897 void set_handle(viennacl::backend::mem_handle const & h) 00898 { 00899 elements_ = h; 00900 } 00901 00904 self_type & fast_swap(self_type & other) 00905 { 00906 assert(this->size_ == other.size_ && bool("Vector size mismatch")); 00907 this->elements_.swap(other.elements_); 00908 return *this; 00909 } 00910 00912 void pad() 00913 { 00914 if (internal_size() != size()) 00915 { 00916 std::vector<SCALARTYPE> pad(internal_size() - size()); 00917 viennacl::backend::memory_write(elements_, sizeof(SCALARTYPE) * size(), sizeof(SCALARTYPE) * pad.size(), &(pad[0])); 00918 } 00919 } 00920 00921 void switch_memory_context(viennacl::context new_ctx) 00922 { 00923 viennacl::backend::switch_memory_context<SCALARTYPE>(elements_, new_ctx); 00924 } 00925 00926 //TODO: Think about implementing the following public member functions 00927 //void insert_element(unsigned int i, SCALARTYPE val){} 00928 //void erase_element(unsigned int i){} 00929 00930 //enlarge or reduce allocated memory and set unused memory to zero 00936 void resize(size_type new_size, bool preserve = true) 00937 { 00938 resize_impl(new_size, viennacl::traits::context(*this), preserve); 00939 } 00940 00947 void resize(size_type new_size, viennacl::context ctx, bool preserve = true) 00948 { 00949 resize_impl(new_size, ctx, preserve); 00950 } 00951 00952 private: 00953 00954 void resize_impl(size_type new_size, viennacl::context ctx, bool preserve = true) 00955 { 00956 assert(new_size > 0 && bool("Positive size required when resizing vector!")); 00957 00958 if (new_size != size_) 00959 { 00960 vcl_size_t new_internal_size = viennacl::tools::align_to_multiple<vcl_size_t>(new_size, alignment); 00961 00962 std::vector<SCALARTYPE> temp(size_); 00963 if (preserve && size_ > 0) 00964 fast_copy(*this, temp); 00965 temp.resize(new_size); //drop all entries above new_size 00966 temp.resize(new_internal_size); //enlarge to fit new internal size 00967 00968 if (new_internal_size != internal_size()) 00969 { 00970 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*new_internal_size, ctx, NULL); 00971 } 00972 00973 fast_copy(temp, *this); 00974 size_ = new_size; 00975 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00976 pad(); 00977 } 00978 00979 } 00980 00981 size_type size_; 00982 size_type start_; 00983 difference_type stride_; 00984 size_type internal_size_; 00985 handle_type elements_; 00986 }; //vector_base 00987 00988 00989 00990 // forward definition in forwards.h! 00999 template<class SCALARTYPE, unsigned int ALIGNMENT> 01000 class vector : public vector_base<SCALARTYPE> 01001 { 01002 typedef vector<SCALARTYPE, ALIGNMENT> self_type; 01003 typedef vector_base<SCALARTYPE> base_type; 01004 01005 public: 01006 typedef typename base_type::size_type size_type; 01007 typedef typename base_type::difference_type difference_type; 01008 01011 explicit vector() : base_type() { /* Note: One must not call ::init() here because the vector might have been created globally before the backend has become available */ } 01012 01017 explicit vector(size_type vec_size) : base_type(vec_size) {} 01018 01019 explicit vector(size_type vec_size, viennacl::context ctx) : base_type(vec_size, ctx) {} 01020 01021 explicit vector(SCALARTYPE * ptr_to_mem, viennacl::memory_types mem_type, size_type vec_size, size_type start = 0, difference_type stride = 1) 01022 : base_type(ptr_to_mem, mem_type, vec_size, start, stride) {} 01023 01024 #ifdef VIENNACL_WITH_OPENCL 01025 01033 explicit vector(cl_mem existing_mem, size_type vec_size, size_type start = 0, difference_type stride = 1) : base_type(existing_mem, vec_size, start, stride) {} 01034 01040 explicit vector(size_type vec_size, viennacl::ocl::context const & ctx) : base_type(vec_size, ctx) {} 01041 #endif 01042 01043 template <typename LHS, typename RHS, typename OP> 01044 vector(vector_expression<const LHS, const RHS, OP> const & proxy) : base_type(proxy) {} 01045 01046 vector(const base_type & v) : base_type(v.size(), viennacl::traits::context(v)) 01047 { 01048 if (v.size() > 0) 01049 base_type::operator=(v); 01050 } 01051 01052 vector(const self_type & v) : base_type(v.size(), viennacl::traits::context(v)) 01053 { 01054 if (v.size() > 0) 01055 base_type::operator=(v); 01056 } 01057 01059 vector(unit_vector<SCALARTYPE> const & v) : base_type(v.size()) 01060 { 01061 if (v.size() > 0) 01062 this->operator()(v.index()) = SCALARTYPE(1);; 01063 } 01064 01066 vector(zero_vector<SCALARTYPE> const & v) : base_type(v.size(), v.context()) 01067 { 01068 if (v.size() > 0) 01069 viennacl::linalg::vector_assign(*this, SCALARTYPE(0.0)); 01070 } 01071 01073 vector(scalar_vector<SCALARTYPE> const & v) : base_type(v.size(), v.context()) 01074 { 01075 if (v.size() > 0) 01076 viennacl::linalg::vector_assign(*this, v[0]); 01077 } 01078 01079 // the following is used to circumvent an issue with Clang 3.0 when 'using base_type::operator=;' directly 01080 template <typename T> 01081 self_type & operator=(T const & other) 01082 { 01083 base_type::operator=(other); 01084 return *this; 01085 } 01086 01087 using base_type::operator+=; 01088 using base_type::operator-=; 01089 01090 //enlarge or reduce allocated memory and set unused memory to zero 01096 void resize(size_type new_size, bool preserve = true) 01097 { 01098 base_type::resize(new_size, preserve); 01099 } 01100 01101 void resize(size_type new_size, viennacl::context ctx, bool preserve = true) 01102 { 01103 base_type::resize(new_size, ctx, preserve); 01104 } 01105 01108 self_type & fast_swap(self_type & other) 01109 { 01110 base_type::fast_swap(other); 01111 return *this; 01112 } 01113 01114 void switch_memory_context(viennacl::context new_ctx) 01115 { 01116 base_type::switch_memory_context(new_ctx); 01117 } 01118 01119 }; //vector 01120 01122 template <typename ScalarT> 01123 class vector_tuple 01124 { 01125 typedef vector_base<ScalarT> VectorType; 01126 01127 public: 01128 // 2 vectors 01129 01130 vector_tuple(VectorType const & v0, VectorType const & v1) : const_vectors_(2), non_const_vectors_() 01131 { 01132 const_vectors_[0] = &v0; 01133 const_vectors_[1] = &v1; 01134 } 01135 vector_tuple(VectorType & v0, VectorType & v1) : const_vectors_(2), non_const_vectors_(2) 01136 { 01137 const_vectors_[0] = &v0; non_const_vectors_[0] = &v0; 01138 const_vectors_[1] = &v1; non_const_vectors_[1] = &v1; 01139 } 01140 01141 // 3 vectors 01142 01143 vector_tuple(VectorType const & v0, VectorType const & v1, VectorType const & v2) : const_vectors_(3), non_const_vectors_() 01144 { 01145 const_vectors_[0] = &v0; 01146 const_vectors_[1] = &v1; 01147 const_vectors_[2] = &v2; 01148 } 01149 vector_tuple(VectorType & v0, VectorType & v1, VectorType & v2) : const_vectors_(3), non_const_vectors_(3) 01150 { 01151 const_vectors_[0] = &v0; non_const_vectors_[0] = &v0; 01152 const_vectors_[1] = &v1; non_const_vectors_[1] = &v1; 01153 const_vectors_[2] = &v2; non_const_vectors_[2] = &v2; 01154 } 01155 01156 // 4 vectors 01157 01158 vector_tuple(VectorType const & v0, VectorType const & v1, VectorType const & v2, VectorType const & v3) : const_vectors_(4), non_const_vectors_() 01159 { 01160 const_vectors_[0] = &v0; 01161 const_vectors_[1] = &v1; 01162 const_vectors_[2] = &v2; 01163 const_vectors_[3] = &v3; 01164 } 01165 vector_tuple(VectorType & v0, VectorType & v1, VectorType & v2, VectorType & v3) : const_vectors_(4), non_const_vectors_(4) 01166 { 01167 const_vectors_[0] = &v0; non_const_vectors_[0] = &v0; 01168 const_vectors_[1] = &v1; non_const_vectors_[1] = &v1; 01169 const_vectors_[2] = &v2; non_const_vectors_[2] = &v2; 01170 const_vectors_[3] = &v3; non_const_vectors_[3] = &v3; 01171 } 01172 01173 // add more overloads here 01174 01175 // generic interface: 01176 01177 vector_tuple(std::vector<VectorType const *> const & vecs) : const_vectors_(vecs.size()), non_const_vectors_() 01178 { 01179 for (vcl_size_t i=0; i<vecs.size(); ++i) 01180 const_vectors_[i] = vecs[i]; 01181 } 01182 01183 vector_tuple(std::vector<VectorType *> const & vecs) : const_vectors_(vecs.size()), non_const_vectors_(vecs.size()) 01184 { 01185 for (vcl_size_t i=0; i<vecs.size(); ++i) 01186 { 01187 const_vectors_[i] = vecs[i]; 01188 non_const_vectors_[i] = vecs[i]; 01189 } 01190 } 01191 01192 vcl_size_t size() const { return non_const_vectors_.size(); } 01193 vcl_size_t const_size() const { return const_vectors_.size(); } 01194 01195 VectorType & at(vcl_size_t i) const { return *(non_const_vectors_.at(i)); } 01196 VectorType const & const_at(vcl_size_t i) const { return *(const_vectors_.at(i)); } 01197 01198 private: 01199 std::vector<VectorType const *> const_vectors_; 01200 std::vector<VectorType *> non_const_vectors_; 01201 }; 01202 01203 // 2 args 01204 template <typename ScalarT> 01205 vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1) { return vector_tuple<ScalarT>(v0, v1); } 01206 01207 template <typename ScalarT> 01208 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, vector_base<ScalarT> & v1) { return vector_tuple<ScalarT>(v0, v1); } 01209 01210 // 3 args 01211 template <typename ScalarT> 01212 vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1, vector_base<ScalarT> const & v2) { return vector_tuple<ScalarT>(v0, v1, v2); } 01213 01214 template <typename ScalarT> 01215 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, vector_base<ScalarT> & v1, vector_base<ScalarT> & v2) { return vector_tuple<ScalarT>(v0, v1, v2); } 01216 01217 // 4 args 01218 template <typename ScalarT> 01219 vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1, vector_base<ScalarT> const & v2, vector_base<ScalarT> const & v3) 01220 { 01221 return vector_tuple<ScalarT>(v0, v1, v2, v3); 01222 } 01223 01224 template <typename ScalarT> 01225 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, vector_base<ScalarT> & v1, vector_base<ScalarT> & v2, vector_base<ScalarT> & v3) 01226 { 01227 return vector_tuple<ScalarT>(v0, v1, v2, v3); 01228 } 01229 01230 // 5 args 01231 template <typename ScalarT> 01232 vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, 01233 vector_base<ScalarT> const & v1, 01234 vector_base<ScalarT> const & v2, 01235 vector_base<ScalarT> const & v3, 01236 vector_base<ScalarT> const & v4) 01237 { 01238 typedef vector_base<ScalarT> const * VectorPointerType; 01239 std::vector<VectorPointerType> vec(5); 01240 vec[0] = &v0; 01241 vec[1] = &v1; 01242 vec[2] = &v2; 01243 vec[3] = &v3; 01244 vec[4] = &v4; 01245 return vector_tuple<ScalarT>(vec); 01246 } 01247 01248 template <typename ScalarT> 01249 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, 01250 vector_base<ScalarT> & v1, 01251 vector_base<ScalarT> & v2, 01252 vector_base<ScalarT> & v3, 01253 vector_base<ScalarT> & v4) 01254 { 01255 typedef vector_base<ScalarT> * VectorPointerType; 01256 std::vector<VectorPointerType> vec(5); 01257 vec[0] = &v0; 01258 vec[1] = &v1; 01259 vec[2] = &v2; 01260 vec[3] = &v3; 01261 vec[4] = &v4; 01262 return vector_tuple<ScalarT>(vec); 01263 } 01264 01265 // TODO: Add more arguments to tie() here. Maybe use some preprocessor magic to accomplish this. 01266 01267 // 01269 // 01270 01271 01283 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01284 void fast_copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01285 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01286 CPU_ITERATOR cpu_begin ) 01287 { 01288 if (gpu_begin != gpu_end) 01289 { 01290 if (gpu_begin.stride() == 1) 01291 { 01292 viennacl::backend::memory_read(gpu_begin.handle(), 01293 sizeof(SCALARTYPE)*gpu_begin.offset(), 01294 sizeof(SCALARTYPE)*gpu_begin.stride() * (gpu_end - gpu_begin), 01295 &(*cpu_begin)); 01296 } 01297 else 01298 { 01299 vcl_size_t gpu_size = (gpu_end - gpu_begin); 01300 std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * gpu_size); 01301 viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01302 01303 for (vcl_size_t i=0; i<gpu_size; ++i) 01304 { 01305 (&(*cpu_begin))[i] = temp_buffer[i * gpu_begin.stride()]; 01306 } 01307 } 01308 } 01309 } 01310 01316 template <typename NumericT, typename CPUVECTOR> 01317 void fast_copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01318 { 01319 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01320 } 01321 01322 01333 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01334 void async_copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01335 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01336 CPU_ITERATOR cpu_begin ) 01337 { 01338 if (gpu_begin != gpu_end) 01339 { 01340 if (gpu_begin.stride() == 1) 01341 { 01342 viennacl::backend::memory_read(gpu_begin.handle(), 01343 sizeof(SCALARTYPE)*gpu_begin.offset(), 01344 sizeof(SCALARTYPE)*gpu_begin.stride() * (gpu_end - gpu_begin), 01345 &(*cpu_begin), 01346 true); 01347 } 01348 else // no async copy possible, so fall-back to fast_copy 01349 fast_copy(gpu_begin, gpu_end, cpu_begin); 01350 } 01351 } 01352 01358 template <typename NumericT, typename CPUVECTOR> 01359 void async_copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01360 { 01361 viennacl::async_copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01362 } 01363 01364 01371 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01372 void copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01373 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01374 CPU_ITERATOR cpu_begin ) 01375 { 01376 assert(gpu_end - gpu_begin >= 0 && bool("Iterators incompatible")); 01377 if (gpu_end - gpu_begin != 0) 01378 { 01379 std::vector<SCALARTYPE> temp_buffer(gpu_end - gpu_begin); 01380 fast_copy(gpu_begin, gpu_end, temp_buffer.begin()); 01381 01382 //now copy entries to cpu_vec: 01383 std::copy(temp_buffer.begin(), temp_buffer.end(), cpu_begin); 01384 } 01385 } 01386 01393 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01394 void copy(const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01395 const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01396 CPU_ITERATOR cpu_begin ) 01397 01398 { 01399 viennacl::copy(const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_begin), 01400 const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_end), 01401 cpu_begin); 01402 } 01403 01409 template <typename NumericT, typename CPUVECTOR> 01410 void copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01411 { 01412 viennacl::copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01413 } 01414 01415 01416 01417 #ifdef VIENNACL_WITH_EIGEN 01418 template <unsigned int ALIGNMENT> 01419 void copy(vector<float, ALIGNMENT> const & gpu_vec, 01420 Eigen::VectorXf & eigen_vec) 01421 { 01422 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0])); 01423 } 01424 01425 template <unsigned int ALIGNMENT> 01426 void copy(vector<double, ALIGNMENT> & gpu_vec, 01427 Eigen::VectorXd & eigen_vec) 01428 { 01429 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0])); 01430 } 01431 #endif 01432 01433 01434 // 01436 // 01437 01449 template <typename CPU_ITERATOR, typename SCALARTYPE, unsigned int ALIGNMENT> 01450 void fast_copy(CPU_ITERATOR const & cpu_begin, 01451 CPU_ITERATOR const & cpu_end, 01452 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01453 { 01454 if (cpu_end - cpu_begin > 0) 01455 { 01456 if (gpu_begin.stride() == 1) 01457 { 01458 viennacl::backend::memory_write(gpu_begin.handle(), 01459 sizeof(SCALARTYPE)*gpu_begin.offset(), 01460 sizeof(SCALARTYPE)*gpu_begin.stride() * (cpu_end - cpu_begin), &(*cpu_begin)); 01461 } 01462 else //writing to slice: 01463 { 01464 vcl_size_t cpu_size = (cpu_end - cpu_begin); 01465 std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * cpu_size); 01466 01467 viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01468 01469 for (vcl_size_t i=0; i<cpu_size; ++i) 01470 temp_buffer[i * gpu_begin.stride()] = (&(*cpu_begin))[i]; 01471 01472 viennacl::backend::memory_write(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01473 } 01474 } 01475 } 01476 01477 01483 template <typename CPUVECTOR, typename NumericT> 01484 void fast_copy(const CPUVECTOR & cpu_vec, vector_base<NumericT> & gpu_vec) 01485 { 01486 viennacl::fast_copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01487 } 01488 01499 template <typename CPU_ITERATOR, typename SCALARTYPE, unsigned int ALIGNMENT> 01500 void async_copy(CPU_ITERATOR const & cpu_begin, 01501 CPU_ITERATOR const & cpu_end, 01502 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01503 { 01504 if (cpu_end - cpu_begin > 0) 01505 { 01506 if (gpu_begin.stride() == 1) 01507 { 01508 viennacl::backend::memory_write(gpu_begin.handle(), 01509 sizeof(SCALARTYPE)*gpu_begin.offset(), 01510 sizeof(SCALARTYPE)*gpu_begin.stride() * (cpu_end - cpu_begin), &(*cpu_begin), 01511 true); 01512 } 01513 else // fallback to blocking copy. There's nothing we can do to prevent this 01514 fast_copy(cpu_begin, cpu_end, gpu_begin); 01515 } 01516 } 01517 01518 01524 template <typename CPUVECTOR, typename NumericT> 01525 void async_copy(const CPUVECTOR & cpu_vec, vector_base<NumericT> & gpu_vec) 01526 { 01527 viennacl::async_copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01528 } 01529 01530 //from cpu to gpu. Safe assumption: cpu_vector does not necessarily occupy a linear memory segment, but is not larger than the allocated memory on the GPU 01537 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01538 void copy(CPU_ITERATOR const & cpu_begin, 01539 CPU_ITERATOR const & cpu_end, 01540 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01541 { 01542 assert(cpu_end - cpu_begin > 0 && bool("Iterators incompatible")); 01543 if (cpu_begin != cpu_end) 01544 { 01545 //we require that the size of the gpu_vector is larger or equal to the cpu-size 01546 std::vector<SCALARTYPE> temp_buffer(cpu_end - cpu_begin); 01547 std::copy(cpu_begin, cpu_end, temp_buffer.begin()); 01548 viennacl::fast_copy(temp_buffer.begin(), temp_buffer.end(), gpu_begin); 01549 } 01550 } 01551 01552 // for things like copy(std_vec.begin(), std_vec.end(), vcl_vec.begin() + 1); 01553 01559 template <typename CPUVECTOR, typename T> 01560 void copy(const CPUVECTOR & cpu_vec, vector_base<T> & gpu_vec) 01561 { 01562 viennacl::copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01563 } 01564 01565 01566 #ifdef VIENNACL_WITH_EIGEN 01567 template <unsigned int ALIGNMENT> 01568 void copy(Eigen::VectorXf const & eigen_vec, 01569 vector<float, ALIGNMENT> & gpu_vec) 01570 { 01571 std::vector<float> entries(eigen_vec.size()); 01572 for (vcl_size_t i = 0; i<entries.size(); ++i) 01573 entries[i] = eigen_vec(i); 01574 viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin()); 01575 } 01576 01577 template <unsigned int ALIGNMENT> 01578 void copy(Eigen::VectorXd const & eigen_vec, 01579 vector<double, ALIGNMENT> & gpu_vec) 01580 { 01581 std::vector<double> entries(eigen_vec.size()); 01582 for (vcl_size_t i = 0; i<entries.size(); ++i) 01583 entries[i] = eigen_vec(i); 01584 viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin()); 01585 } 01586 #endif 01587 01588 01589 01590 // 01592 // 01599 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01600 void copy(const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin, 01601 const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end, 01602 vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin) 01603 { 01604 assert(gpu_src_end - gpu_src_begin >= 0); 01605 assert(gpu_src_begin.stride() == 1 && bool("ViennaCL ERROR: copy() for GPU->GPU not implemented for slices! Use operator= instead for the moment.")); 01606 01607 if (gpu_src_begin.stride() == 1 && gpu_dest_begin.stride() == 1) 01608 { 01609 if (gpu_src_begin != gpu_src_end) 01610 viennacl::backend::memory_copy(gpu_src_begin.handle(), gpu_dest_begin.handle(), 01611 sizeof(SCALARTYPE) * gpu_src_begin.offset(), 01612 sizeof(SCALARTYPE) * gpu_dest_begin.offset(), 01613 sizeof(SCALARTYPE) * (gpu_src_end.offset() - gpu_src_begin.offset())); 01614 } 01615 else 01616 { 01617 assert( false && bool("not implemented yet")); 01618 } 01619 } 01620 01627 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01628 void copy(vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin, 01629 vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end, 01630 vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin) 01631 { 01632 viennacl::copy(static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_begin), 01633 static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_end), 01634 gpu_dest_begin); 01635 } 01636 01642 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01643 void copy(vector<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_vec, 01644 vector<SCALARTYPE, ALIGNMENT_DEST> & gpu_dest_vec ) 01645 { 01646 viennacl::copy(gpu_src_vec.begin(), gpu_src_vec.end(), gpu_dest_vec.begin()); 01647 } 01648 01649 01650 01651 01652 01653 01654 //global functions for handling vectors: 01659 template <typename T> 01660 std::ostream & operator<<(std::ostream & os, vector_base<T> const & val) 01661 { 01662 std::vector<T> tmp(val.size()); 01663 viennacl::copy(val.begin(), val.end(), tmp.begin()); 01664 os << "[" << val.size() << "]("; 01665 for (typename std::vector<T>::size_type i=0; i<val.size(); ++i) 01666 { 01667 if (i > 0) 01668 os << ","; 01669 os << tmp[i]; 01670 } 01671 os << ")"; 01672 return os; 01673 } 01674 01675 template <typename LHS, typename RHS, typename OP> 01676 std::ostream & operator<<(std::ostream & os, vector_expression<LHS, RHS, OP> const & proxy) 01677 01678 { 01679 typedef typename viennacl::result_of::cpu_value_type<typename LHS::value_type>::type ScalarType; 01680 viennacl::vector<ScalarType> result = proxy; 01681 os << result; 01682 return os; 01683 } 01684 01690 template <typename T> 01691 void swap(vector_base<T> & vec1, vector_base<T> & vec2) 01692 { 01693 viennacl::linalg::vector_swap(vec1, vec2); 01694 } 01695 01701 template <typename SCALARTYPE, unsigned int ALIGNMENT> 01702 vector<SCALARTYPE, ALIGNMENT> & fast_swap(vector<SCALARTYPE, ALIGNMENT> & v1, 01703 vector<SCALARTYPE, ALIGNMENT> & v2) 01704 { 01705 return v1.fast_swap(v2); 01706 } 01707 01708 01709 01710 01711 01712 // 01713 // 01715 // 01716 // 01717 01718 01719 // 01720 // operator *= 01721 // 01722 01725 template <typename T, typename S1> 01726 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01727 vector_base<T> & 01728 >::type 01729 operator *= (vector_base<T> & v1, S1 const & gpu_val) 01730 { 01731 if (v1.size() > 0) 01732 viennacl::linalg::av(v1, 01733 v1, gpu_val, 1, false, (viennacl::is_flip_sign_scalar<S1>::value ? true : false)); 01734 return v1; 01735 } 01736 01737 01738 // 01739 // operator /= 01740 // 01741 01742 01745 template <typename T, typename S1> 01746 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01747 vector_base<T> & 01748 >::type 01749 operator /= (vector_base<T> & v1, S1 const & gpu_val) 01750 { 01751 if (v1.size() > 0) 01752 viennacl::linalg::av(v1, 01753 v1, gpu_val, 1, true, (viennacl::is_flip_sign_scalar<S1>::value ? true : false)); 01754 return v1; 01755 } 01756 01757 01758 // 01759 // operator + 01760 // 01761 01762 01768 template <typename LHS1, typename RHS1, typename OP1, 01769 typename LHS2, typename RHS2, typename OP2> 01770 vector_expression< const vector_expression< LHS1, RHS1, OP1>, 01771 const vector_expression< LHS2, RHS2, OP2>, 01772 viennacl::op_add> 01773 operator + (vector_expression<LHS1, RHS1, OP1> const & proxy1, 01774 vector_expression<LHS2, RHS2, OP2> const & proxy2) 01775 { 01776 assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!")); 01777 return vector_expression< const vector_expression<LHS1, RHS1, OP1>, 01778 const vector_expression<LHS2, RHS2, OP2>, 01779 viennacl::op_add>(proxy1, proxy2); 01780 } 01781 01787 template <typename LHS, typename RHS, typename OP, typename T> 01788 vector_expression< const vector_expression<LHS, RHS, OP>, 01789 const vector_base<T>, 01790 viennacl::op_add> 01791 operator + (vector_expression<LHS, RHS, OP> const & proxy, 01792 vector_base<T> const & vec) 01793 { 01794 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01795 return vector_expression< const vector_expression<LHS, RHS, OP>, 01796 const vector_base<T>, 01797 viennacl::op_add>(proxy, vec); 01798 } 01799 01805 template <typename T, typename LHS, typename RHS, typename OP> 01806 vector_expression< const vector_base<T>, 01807 const vector_expression<LHS, RHS, OP>, 01808 viennacl::op_add> 01809 operator + (vector_base<T> const & vec, 01810 vector_expression<LHS, RHS, OP> const & proxy) 01811 { 01812 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01813 return vector_expression< const vector_base<T>, 01814 const vector_expression<LHS, RHS, OP>, 01815 viennacl::op_add>(vec, proxy); 01816 } 01817 01820 template <typename T> 01821 vector_expression< const vector_base<T>, const vector_base<T>, op_add> 01822 operator + (const vector_base<T> & v1, const vector_base<T> & v2) 01823 { 01824 return vector_expression< const vector_base<T>, const vector_base<T>, op_add>(v1, v2); 01825 } 01826 01827 01828 01829 // 01830 // operator - 01831 // 01832 01838 template <typename LHS1, typename RHS1, typename OP1, 01839 typename LHS2, typename RHS2, typename OP2> 01840 vector_expression< const vector_expression< LHS1, RHS1, OP1>, 01841 const vector_expression< LHS2, RHS2, OP2>, 01842 viennacl::op_sub> 01843 operator - (vector_expression<LHS1, RHS1, OP1> const & proxy1, 01844 vector_expression<LHS2, RHS2, OP2> const & proxy2) 01845 { 01846 assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!")); 01847 return vector_expression< const vector_expression<LHS1, RHS1, OP1>, 01848 const vector_expression<LHS2, RHS2, OP2>, 01849 viennacl::op_sub>(proxy1, proxy2); 01850 } 01851 01852 01858 template <typename LHS, typename RHS, typename OP, typename T> 01859 vector_expression< const vector_expression<LHS, RHS, OP>, 01860 const vector_base<T>, 01861 viennacl::op_sub> 01862 operator - (vector_expression<LHS, RHS, OP> const & proxy, 01863 vector_base<T> const & vec) 01864 { 01865 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01866 return vector_expression< const vector_expression<LHS, RHS, OP>, 01867 const vector_base<T>, 01868 viennacl::op_sub>(proxy, vec); 01869 } 01870 01876 template <typename T, typename LHS, typename RHS, typename OP> 01877 vector_expression< const vector_base<T>, 01878 const vector_expression<LHS, RHS, OP>, 01879 viennacl::op_sub> 01880 operator - (vector_base<T> const & vec, 01881 vector_expression<LHS, RHS, OP> const & proxy) 01882 { 01883 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01884 return vector_expression< const vector_base<T>, 01885 const vector_expression<LHS, RHS, OP>, 01886 viennacl::op_sub>(vec, proxy); 01887 } 01888 01891 template <typename T> 01892 vector_expression< const vector_base<T>, const vector_base<T>, op_sub> 01893 operator - (const vector_base<T> & v1, const vector_base<T> & v2) 01894 { 01895 return vector_expression< const vector_base<T>, const vector_base<T>, op_sub>(v1, v2); 01896 } 01897 01898 01899 // 01900 // operator * 01901 // 01902 01903 01909 template <typename S1, typename T> 01910 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01911 vector_expression< const vector_base<T>, const S1, op_mult> >::type 01912 operator * (S1 const & value, vector_base<T> const & vec) 01913 { 01914 return vector_expression< const vector_base<T>, const S1, op_mult>(vec, value); 01915 } 01916 01922 template <typename T> 01923 vector_expression< const vector_base<T>, const T, op_mult> 01924 operator * (char value, vector_base<T> const & vec) 01925 { 01926 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01927 } 01928 01934 template <typename T> 01935 vector_expression< const vector_base<T>, const T, op_mult> 01936 operator * (short value, vector_base<T> const & vec) 01937 { 01938 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01939 } 01940 01946 template <typename T> 01947 vector_expression< const vector_base<T>, const T, op_mult> 01948 operator * (int value, vector_base<T> const & vec) 01949 { 01950 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01951 } 01952 01958 template <typename T> 01959 vector_expression< const vector_base<T>, const T, op_mult> 01960 operator * (long value, vector_base<T> const & vec) 01961 { 01962 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01963 } 01964 01965 01966 01967 01973 template <typename LHS, typename RHS, typename OP, typename T> 01974 vector_expression< const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> 01975 operator * (scalar_expression<LHS, RHS, OP> const & expr, vector_base<T> const & vec) 01976 { 01977 return vector_expression< const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult>(vec, expr); 01978 } 01979 01982 template <typename T, typename S1> 01983 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01984 vector_expression< const vector_base<T>, const S1, op_mult> >::type 01985 operator * (vector_base<T> const & vec, S1 const & value) 01986 { 01987 return vector_expression< const vector_base<T>, const S1, op_mult>(vec, value); 01988 } 01989 01990 template <typename T> 01991 vector_expression< const vector_base<T>, const T, op_mult> 01992 operator * (vector_base<T> const & vec, T const & value) 01993 { 01994 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01995 } 01996 02002 template <typename LHS, typename RHS, typename OP, typename S1> 02003 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02004 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult> >::type 02005 operator * (vector_expression< LHS, RHS, OP> const & proxy, 02006 S1 const & val) 02007 { 02008 return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>(proxy, val); 02009 } 02010 02016 template <typename S1, typename LHS, typename RHS, typename OP> 02017 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02018 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult> >::type 02019 operator * (S1 const & val, 02020 vector_expression<LHS, RHS, OP> const & proxy) 02021 { 02022 return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>(proxy, val); 02023 } 02024 02025 // 02026 // operator / 02027 // 02028 02034 template <typename S1, typename LHS, typename RHS, typename OP> 02035 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02036 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_div> >::type 02037 operator / (vector_expression< LHS, RHS, OP> const & proxy, 02038 S1 const & val) 02039 { 02040 return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_div>(proxy, val); 02041 } 02042 02043 02046 template <typename T, typename S1> 02047 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02048 vector_expression< const vector_base<T>, const S1, op_div> >::type 02049 operator / (vector_base<T> const & v1, S1 const & s1) 02050 { 02051 return vector_expression<const vector_base<T>, const S1, op_div>(v1, s1); 02052 } 02053 02054 02055 02056 // 02057 // Specify available operations: 02058 // 02059 02062 namespace linalg 02063 { 02064 namespace detail 02065 { 02066 // x = y 02067 template <typename T> 02068 struct op_executor<vector_base<T>, op_assign, vector_base<T> > 02069 { 02070 static void apply(vector_base<T> & lhs, vector_base<T> const & rhs) 02071 { 02072 viennacl::linalg::av(lhs, rhs, T(1), 1, false, false); 02073 } 02074 }; 02075 02076 // x = inner_prod(z, {y0, y1, ...}) 02077 template <typename T> 02078 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const vector_tuple<T>, op_inner_prod> > 02079 { 02080 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_tuple<T>, op_inner_prod> const & rhs) 02081 { 02082 viennacl::linalg::inner_prod_impl(rhs.lhs(), rhs.rhs(), lhs); 02083 } 02084 }; 02085 02086 // x += y 02087 template <typename T> 02088 struct op_executor<vector_base<T>, op_inplace_add, vector_base<T> > 02089 { 02090 static void apply(vector_base<T> & lhs, vector_base<T> const & rhs) 02091 { 02092 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, rhs, T(1), 1, false, false); 02093 } 02094 }; 02095 02096 // x -= y 02097 template <typename T> 02098 struct op_executor<vector_base<T>, op_inplace_sub, vector_base<T> > 02099 { 02100 static void apply(vector_base<T> & lhs, vector_base<T> const & rhs) 02101 { 02102 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, rhs, T(1), 1, false, true); 02103 } 02104 }; 02105 02107 02108 02109 // x = alpha * y 02110 template <typename T, typename ScalarType> 02111 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const ScalarType, op_mult> > 02112 { 02113 // generic case: ScalarType is a scalar expression 02114 template <typename LHS, typename RHS, typename OP> 02115 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy) 02116 { 02117 T alpha = proxy.rhs(); 02118 viennacl::linalg::av(lhs, proxy.lhs(), alpha, 1, false, false); 02119 } 02120 02121 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy) 02122 { 02123 viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, false, false); 02124 } 02125 02126 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy) 02127 { 02128 viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, false, false); 02129 } 02130 }; 02131 02132 // x += alpha * y 02133 template <typename T, typename ScalarType> 02134 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_base<T>, const ScalarType, op_mult> > 02135 { 02136 // generic case: ScalarType is a scalar expression 02137 template <typename LHS, typename RHS, typename OP> 02138 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy) 02139 { 02140 T alpha = proxy.rhs(); 02141 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), alpha, 1, false, false); 02142 } 02143 02144 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy) 02145 { 02146 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, false); 02147 } 02148 02149 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy) 02150 { 02151 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, false); 02152 } 02153 }; 02154 02155 // x -= alpha * y 02156 template <typename T, typename ScalarType> 02157 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_base<T>, const ScalarType, op_mult> > 02158 { 02159 // generic case: ScalarType is a scalar expression 02160 template <typename LHS, typename RHS, typename OP> 02161 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy) 02162 { 02163 T alpha = proxy.rhs(); 02164 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), alpha, 1, false, true); 02165 } 02166 02167 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy) 02168 { 02169 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, true); 02170 } 02171 02172 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy) 02173 { 02174 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, true); 02175 } 02176 }; 02177 02178 02180 02181 // x = alpha * vec_expr 02182 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02183 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> > 02184 { 02185 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy) 02186 { 02187 vector<T> temp(proxy.lhs()); 02188 lhs = temp * proxy.rhs(); 02189 } 02190 }; 02191 02192 // x += alpha * vec_expr 02193 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02194 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> > 02195 { 02196 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy) 02197 { 02198 vector<T> temp(proxy.lhs()); 02199 lhs += temp * proxy.rhs(); 02200 } 02201 }; 02202 02203 // x -= alpha * vec_expr 02204 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02205 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> > 02206 { 02207 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy) 02208 { 02209 vector<T> temp(proxy.lhs()); 02210 lhs -= temp * proxy.rhs(); 02211 } 02212 }; 02213 02214 02216 02217 // x = y / alpha 02218 template <typename T, typename ScalarType> 02219 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const ScalarType, op_div> > 02220 { 02221 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy) 02222 { 02223 viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, true, false); 02224 } 02225 }; 02226 02227 // x += y / alpha 02228 template <typename T, typename ScalarType> 02229 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_base<T>, const ScalarType, op_div> > 02230 { 02231 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy) 02232 { 02233 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, true, false); 02234 } 02235 }; 02236 02237 // x -= y / alpha 02238 template <typename T, typename ScalarType> 02239 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_base<T>, const ScalarType, op_div> > 02240 { 02241 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy) 02242 { 02243 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, true, true); 02244 } 02245 }; 02246 02247 02249 02250 // x = vec_expr / alpha 02251 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02252 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> > 02253 { 02254 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy) 02255 { 02256 vector<T> temp(proxy.lhs()); 02257 lhs = temp / proxy.rhs(); 02258 } 02259 }; 02260 02261 // x += vec_expr / alpha 02262 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02263 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> > 02264 { 02265 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy) 02266 { 02267 vector<T> temp(proxy.lhs()); 02268 lhs += temp / proxy.rhs(); 02269 } 02270 }; 02271 02272 // x -= vec_expr / alpha 02273 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02274 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> > 02275 { 02276 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy) 02277 { 02278 vector<T> temp(proxy.lhs()); 02279 lhs -= temp / proxy.rhs(); 02280 } 02281 }; 02282 02283 02284 02285 // generic x = vec_expr1 + vec_expr2: 02286 template <typename T, typename LHS, typename RHS> 02287 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_add> > 02288 { 02289 // generic x = vec_expr1 + vec_expr2: 02290 template <typename LHS1, typename RHS1> 02291 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy) 02292 { 02293 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02294 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02295 02296 if (op_aliasing_lhs || op_aliasing_rhs) 02297 { 02298 vector_base<T> temp(proxy.lhs()); 02299 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs()); 02300 lhs = temp; 02301 } 02302 else 02303 { 02304 op_executor<vector_base<T>, op_assign, LHS>::apply(lhs, proxy.lhs()); 02305 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs()); 02306 } 02307 } 02308 02309 // x = y + z 02310 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy) 02311 { 02312 viennacl::linalg::avbv(lhs, 02313 proxy.lhs(), T(1), 1, false, false, 02314 proxy.rhs(), T(1), 1, false, false); 02315 } 02316 02317 // x = alpha * y + z 02318 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>, 02319 const vector_base<T>, 02320 op_add> const & proxy) 02321 { 02322 viennacl::linalg::avbv(lhs, 02323 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02324 proxy.rhs(), T(1), 1, false, false); 02325 } 02326 02327 // x = y / alpha + z 02328 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>, 02329 const vector_base<T>, 02330 op_add> const & proxy) 02331 { 02332 viennacl::linalg::avbv(lhs, 02333 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02334 proxy.rhs(), T(1), 1, false, false); 02335 } 02336 02337 // x = y + beta * z 02338 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02339 const vector_expression<const vector_base<T>, const T, op_mult>, 02340 op_add> const & proxy) 02341 { 02342 viennacl::linalg::avbv(lhs, 02343 proxy.lhs(), T(1), 1, false, false, 02344 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02345 } 02346 02347 // x = y + z / beta 02348 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02349 const vector_expression<const vector_base<T>, const T, op_div>, 02350 op_add> const & proxy) 02351 { 02352 viennacl::linalg::avbv(lhs, 02353 proxy.lhs(), T(1), 1, false, false, 02354 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02355 } 02356 02357 // x = alpha * y + beta * z 02358 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>, 02359 const vector_expression<const vector_base<T>, const T, op_mult>, 02360 op_add> const & proxy) 02361 { 02362 viennacl::linalg::avbv(lhs, 02363 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02364 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02365 } 02366 02367 // x = alpha * y + z / beta 02368 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>, 02369 const vector_expression<const vector_base<T>, const T, op_div>, 02370 op_add> const & proxy) 02371 { 02372 viennacl::linalg::avbv(lhs, 02373 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02374 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02375 } 02376 02377 // x = y / alpha + beta * z 02378 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>, 02379 const vector_expression<const vector_base<T>, const T, op_mult>, 02380 op_add> const & proxy) 02381 { 02382 viennacl::linalg::avbv(lhs, 02383 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02384 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02385 } 02386 02387 // x = y / alpha + z / beta 02388 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>, 02389 const vector_expression<const vector_base<T>, const T, op_div>, 02390 op_add> const & proxy) 02391 { 02392 viennacl::linalg::avbv(lhs, 02393 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02394 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02395 } 02396 }; 02397 02398 02399 // generic x += vec_expr1 + vec_expr2: 02400 template <typename T, typename LHS, typename RHS> 02401 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_add> > 02402 { 02403 // generic x += vec_expr1 + vec_expr2: 02404 template <typename LHS1, typename RHS1> 02405 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy) 02406 { 02407 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02408 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02409 02410 if (op_aliasing_lhs || op_aliasing_rhs) 02411 { 02412 vector_base<T> temp(proxy.lhs()); 02413 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs()); 02414 lhs += temp; 02415 } 02416 else 02417 { 02418 op_executor<vector_base<T>, op_inplace_add, LHS>::apply(lhs, proxy.lhs()); 02419 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs()); 02420 } 02421 } 02422 02423 // x += y + z 02424 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy) 02425 { 02426 viennacl::linalg::avbv_v(lhs, 02427 proxy.lhs(), T(1), 1, false, false, 02428 proxy.rhs(), T(1), 1, false, false); 02429 } 02430 02431 // x += alpha * y + z 02432 template <typename ScalarType> 02433 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02434 const vector_base<T>, 02435 op_add> const & proxy) 02436 { 02437 viennacl::linalg::avbv_v(lhs, 02438 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02439 proxy.rhs(), T(1), 1, false, false); 02440 } 02441 02442 // x += y / alpha + z 02443 template <typename ScalarType> 02444 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02445 const vector_base<T>, 02446 op_add> const & proxy) 02447 { 02448 viennacl::linalg::avbv_v(lhs, 02449 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02450 proxy.rhs(), T(1), 1, false, false); 02451 } 02452 02453 // x += y + beta * z 02454 template <typename ScalarType> 02455 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02456 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02457 op_add> const & proxy) 02458 { 02459 viennacl::linalg::avbv_v(lhs, 02460 proxy.lhs(), T(1), 1, false, false, 02461 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02462 } 02463 02464 // x += y + z / beta 02465 template <typename ScalarType> 02466 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02467 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02468 op_add> const & proxy) 02469 { 02470 viennacl::linalg::avbv_v(lhs, 02471 proxy.lhs(), T(1), 1, false, false, 02472 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02473 } 02474 02475 // x += alpha * y + beta * z 02476 template <typename ScalarType1, typename ScalarType2> 02477 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02478 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02479 op_add> const & proxy) 02480 { 02481 viennacl::linalg::avbv_v(lhs, 02482 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02483 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02484 } 02485 02486 // x += alpha * y + z / beta 02487 template <typename ScalarType1, typename ScalarType2> 02488 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02489 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02490 op_add> const & proxy) 02491 { 02492 viennacl::linalg::avbv_v(lhs, 02493 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02494 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02495 } 02496 02497 // x += y / alpha + beta * z 02498 template <typename ScalarType1, typename ScalarType2> 02499 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02500 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02501 op_add> const & proxy) 02502 { 02503 viennacl::linalg::avbv_v(lhs, 02504 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02505 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02506 } 02507 02508 // x += y / alpha + z / beta 02509 template <typename ScalarType1, typename ScalarType2> 02510 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02511 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02512 op_add> const & proxy) 02513 { 02514 viennacl::linalg::avbv_v(lhs, 02515 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02516 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02517 } 02518 }; 02519 02520 02521 02522 // generic x -= vec_expr1 + vec_expr2: 02523 template <typename T, typename LHS, typename RHS> 02524 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_add> > 02525 { 02526 // generic x -= vec_expr1 + vec_expr2: 02527 template <typename LHS1, typename RHS1> 02528 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy) 02529 { 02530 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02531 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02532 02533 if (op_aliasing_lhs || op_aliasing_rhs) 02534 { 02535 vector_base<T> temp(proxy.lhs()); 02536 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs()); 02537 lhs -= temp; 02538 } 02539 else 02540 { 02541 op_executor<vector_base<T>, op_inplace_sub, LHS>::apply(lhs, proxy.lhs()); 02542 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs()); 02543 } 02544 } 02545 02546 // x -= y + z 02547 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy) 02548 { 02549 viennacl::linalg::avbv_v(lhs, 02550 proxy.lhs(), T(1), 1, false, true, 02551 proxy.rhs(), T(1), 1, false, true); 02552 } 02553 02554 // x -= alpha * y + z 02555 template <typename ScalarType> 02556 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02557 const vector_base<T>, 02558 op_add> const & proxy) 02559 { 02560 viennacl::linalg::avbv_v(lhs, 02561 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02562 proxy.rhs(), T(1), 1, false, true); 02563 } 02564 02565 // x -= y / alpha + z 02566 template <typename ScalarType> 02567 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02568 const vector_base<T>, 02569 op_add> const & proxy) 02570 { 02571 viennacl::linalg::avbv_v(lhs, 02572 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 02573 proxy.rhs(), T(1), 1, false, true); 02574 } 02575 02576 // x -= y + beta * z 02577 template <typename ScalarType> 02578 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02579 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02580 op_add> const & proxy) 02581 { 02582 viennacl::linalg::avbv_v(lhs, 02583 proxy.lhs(), T(1), 1, false, true, 02584 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02585 } 02586 02587 // x -= y + z / beta 02588 template <typename ScalarType> 02589 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02590 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02591 op_add> const & proxy) 02592 { 02593 viennacl::linalg::avbv_v(lhs, 02594 proxy.lhs(), T(1), 1, false, true, 02595 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02596 } 02597 02598 // x -= alpha * y + beta * z 02599 template <typename ScalarType1, typename ScalarType2> 02600 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02601 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02602 op_add> const & proxy) 02603 { 02604 viennacl::linalg::avbv_v(lhs, 02605 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02606 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02607 } 02608 02609 // x -= alpha * y + z / beta 02610 template <typename ScalarType1, typename ScalarType2> 02611 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02612 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02613 op_add> const & proxy) 02614 { 02615 viennacl::linalg::avbv_v(lhs, 02616 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02617 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02618 } 02619 02620 // x -= y / alpha + beta * z 02621 template <typename ScalarType1, typename ScalarType2> 02622 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02623 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02624 op_add> const & proxy) 02625 { 02626 viennacl::linalg::avbv_v(lhs, 02627 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 02628 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02629 } 02630 02631 // x -= y / alpha + z / beta 02632 template <typename ScalarType1, typename ScalarType2> 02633 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02634 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02635 op_add> const & proxy) 02636 { 02637 viennacl::linalg::avbv_v(lhs, 02638 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 02639 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02640 } 02641 }; 02642 02643 02644 02646 02647 02648 02649 // generic x = vec_expr1 - vec_expr2: 02650 template <typename T, typename LHS, typename RHS> 02651 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_sub> > 02652 { 02653 // generic x = vec_expr1 - vec_expr2: 02654 template <typename LHS1, typename RHS1> 02655 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy) 02656 { 02657 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02658 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02659 02660 if (op_aliasing_lhs || op_aliasing_rhs) 02661 { 02662 vector_base<T> temp(proxy.lhs()); 02663 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs()); 02664 lhs = temp; 02665 } 02666 else 02667 { 02668 op_executor<vector_base<T>, op_assign, LHS>::apply(lhs, proxy.lhs()); 02669 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs()); 02670 } 02671 } 02672 02673 // x = y - z 02674 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy) 02675 { 02676 viennacl::linalg::avbv(lhs, 02677 proxy.lhs(), T(1), 1, false, false, 02678 proxy.rhs(), T(1), 1, false, true); 02679 } 02680 02681 // x = alpha * y - z 02682 template <typename ScalarType> 02683 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02684 const vector_base<T>, 02685 op_sub> const & proxy) 02686 { 02687 viennacl::linalg::avbv(lhs, 02688 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02689 proxy.rhs(), T(1), 1, false, true); 02690 } 02691 02692 // x = y / alpha - z 02693 template <typename ScalarType> 02694 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02695 const vector_base<T>, 02696 op_sub> const & proxy) 02697 { 02698 viennacl::linalg::avbv(lhs, 02699 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02700 proxy.rhs(), T(1), 1, false, true); 02701 } 02702 02703 // x = y - beta * z 02704 template <typename ScalarType> 02705 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02706 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02707 op_sub> const & proxy) 02708 { 02709 viennacl::linalg::avbv(lhs, 02710 proxy.lhs(), T(1), 1, false, false, 02711 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02712 } 02713 02714 // x = y - z / beta 02715 template <typename ScalarType> 02716 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02717 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02718 op_sub> const & proxy) 02719 { 02720 viennacl::linalg::avbv(lhs, 02721 proxy.lhs(), T(1), 1, false, false, 02722 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02723 } 02724 02725 // x = alpha * y - beta * z 02726 template <typename ScalarType1, typename ScalarType2> 02727 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02728 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02729 op_sub> const & proxy) 02730 { 02731 viennacl::linalg::avbv(lhs, 02732 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02733 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02734 } 02735 02736 // x = alpha * y - z / beta 02737 template <typename ScalarType1, typename ScalarType2> 02738 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02739 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02740 op_sub> const & proxy) 02741 { 02742 viennacl::linalg::avbv(lhs, 02743 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02744 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02745 } 02746 02747 // x = y / alpha - beta * z 02748 template <typename ScalarType1, typename ScalarType2> 02749 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02750 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02751 op_sub> const & proxy) 02752 { 02753 viennacl::linalg::avbv(lhs, 02754 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02755 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02756 } 02757 02758 // x = y / alpha - z / beta 02759 template <typename ScalarType1, typename ScalarType2> 02760 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02761 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02762 op_sub> const & proxy) 02763 { 02764 viennacl::linalg::avbv(lhs, 02765 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02766 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02767 } 02768 }; 02769 02770 02771 // generic x += vec_expr1 - vec_expr2: 02772 template <typename T, typename LHS, typename RHS> 02773 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_sub> > 02774 { 02775 // generic x += vec_expr1 - vec_expr2: 02776 template <typename LHS1, typename RHS1> 02777 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy) 02778 { 02779 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02780 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02781 02782 if (op_aliasing_lhs || op_aliasing_rhs) 02783 { 02784 vector_base<T> temp(proxy.lhs()); 02785 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs()); 02786 lhs += temp; 02787 } 02788 else 02789 { 02790 op_executor<vector_base<T>, op_inplace_add, LHS>::apply(lhs, proxy.lhs()); 02791 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs()); 02792 } 02793 } 02794 02795 // x += y - z 02796 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy) 02797 { 02798 viennacl::linalg::avbv_v(lhs, 02799 proxy.lhs(), T(1), 1, false, false, 02800 proxy.rhs(), T(1), 1, false, true); 02801 } 02802 02803 // x += alpha * y - z 02804 template <typename ScalarType> 02805 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02806 const vector_base<T>, 02807 op_sub> const & proxy) 02808 { 02809 viennacl::linalg::avbv_v(lhs, 02810 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02811 proxy.rhs(), T(1), 1, false, true); 02812 } 02813 02814 // x += y / alpha - z 02815 template <typename ScalarType> 02816 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02817 const vector_base<T>, 02818 op_sub> const & proxy) 02819 { 02820 viennacl::linalg::avbv_v(lhs, 02821 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02822 proxy.rhs(), T(1), 1, false, true); 02823 } 02824 02825 // x += y - beta * z 02826 template <typename ScalarType> 02827 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02828 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02829 op_sub> const & proxy) 02830 { 02831 viennacl::linalg::avbv_v(lhs, 02832 proxy.lhs(), T(1), 1, false, false, 02833 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02834 } 02835 02836 // x += y - z / beta 02837 template <typename ScalarType> 02838 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02839 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02840 op_sub> const & proxy) 02841 { 02842 viennacl::linalg::avbv_v(lhs, 02843 proxy.lhs(), T(1), 1, false, false, 02844 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02845 } 02846 02847 // x += alpha * y - beta * z 02848 template <typename ScalarType1, typename ScalarType2> 02849 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02850 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02851 op_sub> const & proxy) 02852 { 02853 viennacl::linalg::avbv_v(lhs, 02854 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02855 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02856 } 02857 02858 // x += alpha * y - z / beta 02859 template <typename ScalarType1, typename ScalarType2> 02860 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02861 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02862 op_sub> const & proxy) 02863 { 02864 viennacl::linalg::avbv_v(lhs, 02865 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02866 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02867 } 02868 02869 // x += y / alpha - beta * z 02870 template <typename ScalarType1, typename ScalarType2> 02871 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02872 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02873 op_sub> const & proxy) 02874 { 02875 viennacl::linalg::avbv_v(lhs, 02876 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02877 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02878 } 02879 02880 // x += y / alpha - z / beta 02881 template <typename ScalarType1, typename ScalarType2> 02882 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02883 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02884 op_sub> const & proxy) 02885 { 02886 viennacl::linalg::avbv_v(lhs, 02887 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02888 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02889 } 02890 }; 02891 02892 02893 02894 // generic x -= vec_expr1 - vec_expr2: 02895 template <typename T, typename LHS, typename RHS> 02896 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_sub> > 02897 { 02898 // generic x -= vec_expr1 - vec_expr2: 02899 template <typename LHS1, typename RHS1> 02900 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy) 02901 { 02902 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02903 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02904 02905 if (op_aliasing_lhs || op_aliasing_rhs) 02906 { 02907 vector_base<T> temp(proxy.lhs()); 02908 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs()); 02909 lhs -= temp; 02910 } 02911 else 02912 { 02913 op_executor<vector_base<T>, op_inplace_sub, LHS>::apply(lhs, proxy.lhs()); 02914 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs()); 02915 } 02916 } 02917 02918 // x -= y - z 02919 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy) 02920 { 02921 viennacl::linalg::avbv_v(lhs, 02922 proxy.lhs(), T(1), 1, false, true, 02923 proxy.rhs(), T(1), 1, false, false); 02924 } 02925 02926 // x -= alpha * y - z 02927 template <typename ScalarType> 02928 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02929 const vector_base<T>, 02930 op_sub> const & proxy) 02931 { 02932 viennacl::linalg::avbv_v(lhs, 02933 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02934 proxy.rhs(), T(1), 1, false, false); 02935 } 02936 02937 // x -= y / alpha - z 02938 template <typename ScalarType> 02939 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02940 const vector_base<T>, 02941 op_sub> const & proxy) 02942 { 02943 viennacl::linalg::avbv_v(lhs, 02944 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 02945 proxy.rhs(), T(1), 1, false, false); 02946 } 02947 02948 // x -= y - beta * z 02949 template <typename ScalarType> 02950 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02951 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02952 op_sub> const & proxy) 02953 { 02954 viennacl::linalg::avbv_v(lhs, 02955 proxy.lhs(), T(1), 1, false, true, 02956 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02957 } 02958 02959 // x -= y - z / beta 02960 template <typename ScalarType> 02961 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02962 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02963 op_sub> const & proxy) 02964 { 02965 viennacl::linalg::avbv_v(lhs, 02966 proxy.lhs(), T(1), 1, false, true, 02967 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02968 } 02969 02970 // x -= alpha * y - beta * z 02971 template <typename ScalarType1, typename ScalarType2> 02972 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02973 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02974 op_sub> const & proxy) 02975 { 02976 viennacl::linalg::avbv_v(lhs, 02977 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02978 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02979 } 02980 02981 // x -= alpha * y - z / beta 02982 template <typename ScalarType1, typename ScalarType2> 02983 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02984 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02985 op_sub> const & proxy) 02986 { 02987 viennacl::linalg::avbv_v(lhs, 02988 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02989 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02990 } 02991 02992 // x -= y / alpha - beta * z 02993 template <typename ScalarType1, typename ScalarType2> 02994 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 02995 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02996 op_sub> const & proxy) 02997 { 02998 viennacl::linalg::avbv_v(lhs, 02999 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 03000 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 03001 } 03002 03003 // x -= y / alpha - z / beta 03004 template <typename ScalarType1, typename ScalarType2> 03005 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>, 03006 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 03007 op_sub> const & proxy) 03008 { 03009 viennacl::linalg::avbv_v(lhs, 03010 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 03011 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 03012 } 03013 }; 03014 03015 03016 03017 03018 03019 03020 03021 03022 03023 03024 03025 03026 03027 03028 03029 03030 03031 03033 03034 // generic x = vec_expr1 .* vec_expr2: 03035 template <typename T, typename LHS, typename RHS, typename OP> 03036 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_element_binary<OP> > > 03037 { 03038 // x = y .* z or x = y ./ z 03039 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03040 { 03041 viennacl::linalg::element_op(lhs, proxy); 03042 } 03043 03044 // x = y .* vec_expr or x = y ./ vec_expr 03045 template <typename LHS2, typename RHS2, typename OP2> 03046 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_expression<const LHS2, const RHS2, OP2>, op_element_binary<OP> > const & proxy) 03047 { 03048 vector<T> temp(proxy.rhs()); 03049 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp)); 03050 } 03051 03052 // x = vec_expr .* z or x = vec_expr ./ z 03053 template <typename LHS1, typename RHS1, typename OP1> 03054 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03055 { 03056 vector<T> temp(proxy.lhs()); 03057 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs())); 03058 } 03059 03060 // x = vec_expr .* vec_expr or z = vec_expr .* vec_expr 03061 template <typename LHS1, typename RHS1, typename OP1, 03062 typename LHS2, typename RHS2, typename OP2> 03063 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, 03064 const vector_expression<const LHS2, const RHS2, OP2>, 03065 op_element_binary<OP> > const & proxy) 03066 { 03067 vector<T> temp1(proxy.lhs()); 03068 vector<T> temp2(proxy.rhs()); 03069 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2)); 03070 } 03071 }; 03072 03073 // generic x += vec_expr1 .* vec_expr2: 03074 template <typename T, typename LHS, typename RHS, typename OP> 03075 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_element_binary<OP> > > 03076 { 03077 // x += y .* z or x += y ./ z 03078 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03079 { 03080 viennacl::vector<T> temp(proxy); 03081 lhs += temp; 03082 } 03083 03084 // x += y .* vec_expr or x += y ./ vec_expr 03085 template <typename LHS2, typename RHS2, typename OP2> 03086 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_expression<const LHS2, const RHS2, OP2>, op_element_binary<OP> > const & proxy) 03087 { 03088 vector<T> temp(proxy.rhs()); 03089 vector<T> temp2(temp.size()); 03090 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp)); 03091 lhs += temp2; 03092 } 03093 03094 // x += vec_expr .* z or x += vec_expr ./ z 03095 template <typename LHS1, typename RHS1, typename OP1> 03096 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03097 { 03098 vector<T> temp(proxy.lhs()); 03099 vector<T> temp2(temp.size()); 03100 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs())); 03101 lhs += temp2; 03102 } 03103 03104 // x += vec_expr .* vec_expr or x += vec_expr ./ vec_expr 03105 template <typename LHS1, typename RHS1, typename OP1, 03106 typename LHS2, typename RHS2, typename OP2> 03107 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, 03108 const vector_expression<const LHS2, const RHS2, OP2>, 03109 op_element_binary<OP> > const & proxy) 03110 { 03111 vector<T> temp1(proxy.lhs()); 03112 vector<T> temp2(proxy.rhs()); 03113 vector<T> temp3(temp1.size()); 03114 viennacl::linalg::element_op(temp3, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2)); 03115 lhs += temp3; 03116 } 03117 }; 03118 03119 // generic x -= vec_expr1 .* vec_expr2: 03120 template <typename T, typename LHS, typename RHS, typename OP> 03121 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_element_binary<OP> > > 03122 { 03123 03124 // x -= y .* z or x -= y ./ z 03125 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03126 { 03127 viennacl::vector<T> temp(proxy); 03128 lhs -= temp; 03129 } 03130 03131 // x -= y .* vec_expr or x -= y ./ vec_expr 03132 template <typename LHS2, typename RHS2, typename OP2> 03133 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_expression<const LHS2, const RHS2, OP2>, op_element_binary<OP> > const & proxy) 03134 { 03135 vector<T> temp(proxy.rhs()); 03136 vector<T> temp2(temp.size()); 03137 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp)); 03138 lhs -= temp2; 03139 } 03140 03141 // x -= vec_expr .* z or x -= vec_expr ./ z 03142 template <typename LHS1, typename RHS1, typename OP1> 03143 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03144 { 03145 vector<T> temp(proxy.lhs()); 03146 vector<T> temp2(temp.size()); 03147 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs())); 03148 lhs -= temp2; 03149 } 03150 03151 // x -= vec_expr .* vec_expr or x -= vec_expr ./ vec_expr 03152 template <typename LHS1, typename RHS1, typename OP1, 03153 typename LHS2, typename RHS2, typename OP2> 03154 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, 03155 const vector_expression<const LHS2, const RHS2, OP2>, 03156 op_element_binary<OP> > const & proxy) 03157 { 03158 vector<T> temp1(proxy.lhs()); 03159 vector<T> temp2(proxy.rhs()); 03160 vector<T> temp3(temp1.size()); 03161 viennacl::linalg::element_op(temp3, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2)); 03162 lhs -= temp3; 03163 } 03164 }; 03165 03167 03168 template <typename T, typename LHS, typename RHS, typename OP> 03169 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_element_unary<OP> > > 03170 { 03171 // x = OP(y) 03172 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy) 03173 { 03174 viennacl::linalg::element_op(lhs, proxy); 03175 } 03176 03177 // x = OP(vec_expr) 03178 template <typename LHS2, typename RHS2, typename OP2> 03179 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>, 03180 const vector_expression<const LHS2, const RHS2, OP2>, 03181 op_element_unary<OP> > const & proxy) 03182 { 03183 vector<T> temp(proxy.rhs()); 03184 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> >(temp, temp)); 03185 } 03186 }; 03187 03188 template <typename T, typename LHS, typename RHS, typename OP> 03189 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_element_unary<OP> > > 03190 { 03191 // x += OP(y) 03192 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy) 03193 { 03194 vector<T> temp(proxy); 03195 lhs += temp; 03196 } 03197 03198 // x += OP(vec_expr) 03199 template <typename LHS2, typename RHS2, typename OP2> 03200 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>, 03201 const vector_expression<const LHS2, const RHS2, OP2>, 03202 op_element_unary<OP> > const & proxy) 03203 { 03204 vector<T> temp(proxy.rhs()); 03205 viennacl::linalg::element_op(temp, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> >(temp, temp)); // inplace operation is safe here 03206 lhs += temp; 03207 } 03208 }; 03209 03210 template <typename T, typename LHS, typename RHS, typename OP> 03211 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_element_unary<OP> > > 03212 { 03213 // x -= OP(y) 03214 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy) 03215 { 03216 vector<T> temp(proxy); 03217 lhs -= temp; 03218 } 03219 03220 // x -= OP(vec_expr) 03221 template <typename LHS2, typename RHS2, typename OP2> 03222 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>, 03223 const vector_expression<const LHS2, const RHS2, OP2>, 03224 op_element_unary<OP> > const & proxy) 03225 { 03226 vector<T> temp(proxy.rhs()); 03227 viennacl::linalg::element_op(temp, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> >(temp, temp)); // inplace operation is safe here 03228 lhs -= temp; 03229 } 03230 }; 03231 03232 } // namespace detail 03233 03234 } // namespace linalg 03235 03238 } // namespace viennacl 03239 03240 #endif