ViennaCL - The Vienna Computing Library
1.5.2
|
00001 #ifndef VIENNACL_VECTOR_HPP_ 00002 #define VIENNACL_VECTOR_HPP_ 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2014, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 Portions of this software are copyright by UChicago Argonne, LLC. 00009 00010 ----------------- 00011 ViennaCL - The Vienna Computing Library 00012 ----------------- 00013 00014 Project Head: Karl Rupp rupp@iue.tuwien.ac.at 00015 00016 (A list of authors and contributors can be found in the PDF manual) 00017 00018 License: MIT (X11), see file LICENSE in the base directory 00019 ============================================================================= */ 00020 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 00755 self_type & operator *= (SCALARTYPE val) 00756 { 00757 if (size() > 0) 00758 viennacl::linalg::av(*this, 00759 *this, val, 1, false, false); 00760 return *this; 00761 } 00762 00765 self_type & operator /= (SCALARTYPE val) 00766 { 00767 if (size() > 0) 00768 viennacl::linalg::av(*this, 00769 *this, val, 1, true, false); 00770 return *this; 00771 } 00772 00773 00776 vector_expression< const self_type, const SCALARTYPE, op_mult> 00777 operator * (SCALARTYPE value) const 00778 { 00779 return vector_expression< const self_type, const SCALARTYPE, op_mult>(*this, value); 00780 } 00781 00782 00785 vector_expression< const self_type, const SCALARTYPE, op_div> 00786 operator / (SCALARTYPE value) const 00787 { 00788 return vector_expression< const self_type, const SCALARTYPE, op_div>(*this, value); 00789 } 00790 00791 00793 vector_expression<const self_type, const SCALARTYPE, op_mult> operator-() const 00794 { 00795 return vector_expression<const self_type, const SCALARTYPE, op_mult>(*this, SCALARTYPE(-1.0)); 00796 } 00797 00798 // 00800 // 00801 00803 iterator begin() 00804 { 00805 return iterator(*this, 0, start_, stride_); 00806 } 00807 00809 iterator end() 00810 { 00811 return iterator(*this, size(), start_, stride_); 00812 } 00813 00815 const_iterator begin() const 00816 { 00817 return const_iterator(*this, 0, start_, stride_); 00818 } 00819 00821 const_iterator end() const 00822 { 00823 return const_iterator(*this, size(), start_, stride_); 00824 } 00825 00828 self_type & swap(self_type & other) 00829 { 00830 viennacl::linalg::vector_swap(*this, other); 00831 return *this; 00832 }; 00833 00834 00837 size_type size() const { return size_; } 00838 00841 size_type internal_size() const { return internal_size_; } 00842 00845 size_type start() const { return start_; } 00846 00849 size_type stride() const { return stride_; } 00850 00851 00853 bool empty() const { return size_ == 0; } 00854 00856 const handle_type & handle() const { return elements_; } 00857 00859 handle_type & handle() { return elements_; } 00860 00863 void clear() 00864 { 00865 viennacl::linalg::vector_assign(*this, cpu_value_type(0.0), true); 00866 } 00867 00868 viennacl::memory_types memory_domain() const 00869 { 00870 return elements_.get_active_handle_id(); 00871 } 00872 00873 protected: 00874 00875 void set_handle(viennacl::backend::mem_handle const & h) 00876 { 00877 elements_ = h; 00878 } 00879 00882 self_type & fast_swap(self_type & other) 00883 { 00884 assert(this->size_ == other.size_ && bool("Vector size mismatch")); 00885 this->elements_.swap(other.elements_); 00886 return *this; 00887 } 00888 00890 void pad() 00891 { 00892 if (internal_size() != size()) 00893 { 00894 std::vector<SCALARTYPE> pad(internal_size() - size()); 00895 viennacl::backend::memory_write(elements_, sizeof(SCALARTYPE) * size(), sizeof(SCALARTYPE) * pad.size(), &(pad[0])); 00896 } 00897 } 00898 00899 void switch_memory_context(viennacl::context new_ctx) 00900 { 00901 viennacl::backend::switch_memory_context<SCALARTYPE>(elements_, new_ctx); 00902 } 00903 00904 //TODO: Think about implementing the following public member functions 00905 //void insert_element(unsigned int i, SCALARTYPE val){} 00906 //void erase_element(unsigned int i){} 00907 00908 //enlarge or reduce allocated memory and set unused memory to zero 00914 void resize(size_type new_size, bool preserve = true) 00915 { 00916 resize_impl(new_size, viennacl::traits::context(*this), preserve); 00917 } 00918 00925 void resize(size_type new_size, viennacl::context ctx, bool preserve = true) 00926 { 00927 resize_impl(new_size, ctx, preserve); 00928 } 00929 00930 private: 00931 00932 void resize_impl(size_type new_size, viennacl::context ctx, bool preserve = true) 00933 { 00934 assert(new_size > 0 && bool("Positive size required when resizing vector!")); 00935 00936 if (new_size != size_) 00937 { 00938 vcl_size_t new_internal_size = viennacl::tools::align_to_multiple<vcl_size_t>(new_size, alignment); 00939 00940 std::vector<SCALARTYPE> temp(size_); 00941 if (preserve && size_ > 0) 00942 fast_copy(*this, temp); 00943 temp.resize(new_size); //drop all entries above new_size 00944 temp.resize(new_internal_size); //enlarge to fit new internal size 00945 00946 if (new_internal_size != internal_size()) 00947 { 00948 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*new_internal_size, ctx, NULL); 00949 } 00950 00951 fast_copy(temp, *this); 00952 size_ = new_size; 00953 internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment); 00954 pad(); 00955 } 00956 00957 } 00958 00959 size_type size_; 00960 size_type start_; 00961 difference_type stride_; 00962 size_type internal_size_; 00963 handle_type elements_; 00964 }; //vector_base 00965 00966 00967 00968 // forward definition in forwards.h! 00977 template<class SCALARTYPE, unsigned int ALIGNMENT> 00978 class vector : public vector_base<SCALARTYPE> 00979 { 00980 typedef vector<SCALARTYPE, ALIGNMENT> self_type; 00981 typedef vector_base<SCALARTYPE> base_type; 00982 00983 public: 00984 typedef typename base_type::size_type size_type; 00985 typedef typename base_type::difference_type difference_type; 00986 00989 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 */ } 00990 00995 explicit vector(size_type vec_size) : base_type(vec_size) {} 00996 00997 explicit vector(size_type vec_size, viennacl::context ctx) : base_type(vec_size, ctx) {} 00998 00999 explicit vector(SCALARTYPE * ptr_to_mem, viennacl::memory_types mem_type, size_type vec_size, size_type start = 0, difference_type stride = 1) 01000 : base_type(ptr_to_mem, mem_type, vec_size, start, stride) {} 01001 01002 #ifdef VIENNACL_WITH_OPENCL 01003 01011 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) {} 01012 01018 explicit vector(size_type vec_size, viennacl::ocl::context const & ctx) : base_type(vec_size, ctx) {} 01019 #endif 01020 01021 template <typename LHS, typename RHS, typename OP> 01022 vector(vector_expression<const LHS, const RHS, OP> const & proxy) : base_type(proxy) {} 01023 01024 vector(const base_type & v) : base_type(v.size(), viennacl::traits::context(v)) 01025 { 01026 if (v.size() > 0) 01027 base_type::operator=(v); 01028 } 01029 01030 vector(const self_type & v) : base_type(v.size(), viennacl::traits::context(v)) 01031 { 01032 if (v.size() > 0) 01033 base_type::operator=(v); 01034 } 01035 01037 vector(unit_vector<SCALARTYPE> const & v) : base_type(v.size()) 01038 { 01039 if (v.size() > 0) 01040 this->operator()(v.index()) = SCALARTYPE(1);; 01041 } 01042 01044 vector(zero_vector<SCALARTYPE> const & v) : base_type(v.size(), v.context()) 01045 { 01046 if (v.size() > 0) 01047 viennacl::linalg::vector_assign(*this, SCALARTYPE(0.0)); 01048 } 01049 01051 vector(scalar_vector<SCALARTYPE> const & v) : base_type(v.size(), v.context()) 01052 { 01053 if (v.size() > 0) 01054 viennacl::linalg::vector_assign(*this, v[0]); 01055 } 01056 01057 // the following is used to circumvent an issue with Clang 3.0 when 'using base_type::operator=;' directly 01058 template <typename T> 01059 self_type & operator=(T const & other) 01060 { 01061 base_type::operator=(other); 01062 return *this; 01063 } 01064 01065 using base_type::operator+=; 01066 using base_type::operator-=; 01067 01068 //enlarge or reduce allocated memory and set unused memory to zero 01074 void resize(size_type new_size, bool preserve = true) 01075 { 01076 base_type::resize(new_size, preserve); 01077 } 01078 01079 void resize(size_type new_size, viennacl::context ctx, bool preserve = true) 01080 { 01081 base_type::resize(new_size, ctx, preserve); 01082 } 01083 01086 self_type & fast_swap(self_type & other) 01087 { 01088 base_type::fast_swap(other); 01089 return *this; 01090 } 01091 01092 void switch_memory_context(viennacl::context new_ctx) 01093 { 01094 base_type::switch_memory_context(new_ctx); 01095 } 01096 01097 }; //vector 01098 01100 template <typename ScalarT> 01101 class vector_tuple 01102 { 01103 typedef vector_base<ScalarT> VectorType; 01104 01105 public: 01106 // 2 vectors 01107 01108 vector_tuple(VectorType const & v0, VectorType const & v1) : const_vectors_(2), non_const_vectors_() 01109 { 01110 const_vectors_[0] = &v0; 01111 const_vectors_[1] = &v1; 01112 } 01113 vector_tuple(VectorType & v0, VectorType & v1) : const_vectors_(2), non_const_vectors_(2) 01114 { 01115 const_vectors_[0] = &v0; non_const_vectors_[0] = &v0; 01116 const_vectors_[1] = &v1; non_const_vectors_[1] = &v1; 01117 } 01118 01119 // 3 vectors 01120 01121 vector_tuple(VectorType const & v0, VectorType const & v1, VectorType const & v2) : const_vectors_(3), non_const_vectors_() 01122 { 01123 const_vectors_[0] = &v0; 01124 const_vectors_[1] = &v1; 01125 const_vectors_[2] = &v2; 01126 } 01127 vector_tuple(VectorType & v0, VectorType & v1, VectorType & v2) : const_vectors_(3), non_const_vectors_(3) 01128 { 01129 const_vectors_[0] = &v0; non_const_vectors_[0] = &v0; 01130 const_vectors_[1] = &v1; non_const_vectors_[1] = &v1; 01131 const_vectors_[2] = &v2; non_const_vectors_[2] = &v2; 01132 } 01133 01134 // 4 vectors 01135 01136 vector_tuple(VectorType const & v0, VectorType const & v1, VectorType const & v2, VectorType const & v3) : const_vectors_(4), non_const_vectors_() 01137 { 01138 const_vectors_[0] = &v0; 01139 const_vectors_[1] = &v1; 01140 const_vectors_[2] = &v2; 01141 const_vectors_[3] = &v3; 01142 } 01143 vector_tuple(VectorType & v0, VectorType & v1, VectorType & v2, VectorType & v3) : const_vectors_(4), non_const_vectors_(4) 01144 { 01145 const_vectors_[0] = &v0; non_const_vectors_[0] = &v0; 01146 const_vectors_[1] = &v1; non_const_vectors_[1] = &v1; 01147 const_vectors_[2] = &v2; non_const_vectors_[2] = &v2; 01148 const_vectors_[3] = &v3; non_const_vectors_[3] = &v3; 01149 } 01150 01151 // add more overloads here 01152 01153 // generic interface: 01154 01155 vector_tuple(std::vector<VectorType const *> const & vecs) : const_vectors_(vecs.size()), non_const_vectors_() 01156 { 01157 for (vcl_size_t i=0; i<vecs.size(); ++i) 01158 const_vectors_[i] = vecs[i]; 01159 } 01160 01161 vector_tuple(std::vector<VectorType *> const & vecs) : const_vectors_(vecs.size()), non_const_vectors_(vecs.size()) 01162 { 01163 for (vcl_size_t i=0; i<vecs.size(); ++i) 01164 { 01165 const_vectors_[i] = vecs[i]; 01166 non_const_vectors_[i] = vecs[i]; 01167 } 01168 } 01169 01170 vcl_size_t size() const { return non_const_vectors_.size(); } 01171 vcl_size_t const_size() const { return const_vectors_.size(); } 01172 01173 VectorType & at(vcl_size_t i) const { return *(non_const_vectors_.at(i)); } 01174 VectorType const & const_at(vcl_size_t i) const { return *(const_vectors_.at(i)); } 01175 01176 private: 01177 std::vector<VectorType const *> const_vectors_; 01178 std::vector<VectorType *> non_const_vectors_; 01179 }; 01180 01181 // 2 args 01182 template <typename ScalarT> 01183 vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1) { return vector_tuple<ScalarT>(v0, v1); } 01184 01185 template <typename ScalarT> 01186 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, vector_base<ScalarT> & v1) { return vector_tuple<ScalarT>(v0, v1); } 01187 01188 // 3 args 01189 template <typename ScalarT> 01190 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); } 01191 01192 template <typename ScalarT> 01193 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, vector_base<ScalarT> & v1, vector_base<ScalarT> & v2) { return vector_tuple<ScalarT>(v0, v1, v2); } 01194 01195 // 4 args 01196 template <typename ScalarT> 01197 vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1, vector_base<ScalarT> const & v2, vector_base<ScalarT> const & v3) 01198 { 01199 return vector_tuple<ScalarT>(v0, v1, v2, v3); 01200 } 01201 01202 template <typename ScalarT> 01203 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, vector_base<ScalarT> & v1, vector_base<ScalarT> & v2, vector_base<ScalarT> & v3) 01204 { 01205 return vector_tuple<ScalarT>(v0, v1, v2, v3); 01206 } 01207 01208 // 5 args 01209 template <typename ScalarT> 01210 vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, 01211 vector_base<ScalarT> const & v1, 01212 vector_base<ScalarT> const & v2, 01213 vector_base<ScalarT> const & v3, 01214 vector_base<ScalarT> const & v4) 01215 { 01216 typedef vector_base<ScalarT> const * VectorPointerType; 01217 std::vector<VectorPointerType> vec(5); 01218 vec[0] = &v0; 01219 vec[1] = &v1; 01220 vec[2] = &v2; 01221 vec[3] = &v3; 01222 vec[4] = &v4; 01223 return vector_tuple<ScalarT>(vec); 01224 } 01225 01226 template <typename ScalarT> 01227 vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0, 01228 vector_base<ScalarT> & v1, 01229 vector_base<ScalarT> & v2, 01230 vector_base<ScalarT> & v3, 01231 vector_base<ScalarT> & v4) 01232 { 01233 typedef vector_base<ScalarT> * VectorPointerType; 01234 std::vector<VectorPointerType> vec(5); 01235 vec[0] = &v0; 01236 vec[1] = &v1; 01237 vec[2] = &v2; 01238 vec[3] = &v3; 01239 vec[4] = &v4; 01240 return vector_tuple<ScalarT>(vec); 01241 } 01242 01243 // TODO: Add more arguments to tie() here. Maybe use some preprocessor magic to accomplish this. 01244 01245 // 01247 // 01248 01249 01261 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01262 void fast_copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01263 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01264 CPU_ITERATOR cpu_begin ) 01265 { 01266 if (gpu_begin != gpu_end) 01267 { 01268 if (gpu_begin.stride() == 1) 01269 { 01270 viennacl::backend::memory_read(gpu_begin.handle(), 01271 sizeof(SCALARTYPE)*gpu_begin.offset(), 01272 sizeof(SCALARTYPE)*gpu_begin.stride() * (gpu_end - gpu_begin), 01273 &(*cpu_begin)); 01274 } 01275 else 01276 { 01277 vcl_size_t gpu_size = (gpu_end - gpu_begin); 01278 std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * gpu_size); 01279 viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01280 01281 for (vcl_size_t i=0; i<gpu_size; ++i) 01282 { 01283 (&(*cpu_begin))[i] = temp_buffer[i * gpu_begin.stride()]; 01284 } 01285 } 01286 } 01287 } 01288 01294 template <typename NumericT, typename CPUVECTOR> 01295 void fast_copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01296 { 01297 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01298 } 01299 01300 01311 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01312 void async_copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01313 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01314 CPU_ITERATOR cpu_begin ) 01315 { 01316 if (gpu_begin != gpu_end) 01317 { 01318 if (gpu_begin.stride() == 1) 01319 { 01320 viennacl::backend::memory_read(gpu_begin.handle(), 01321 sizeof(SCALARTYPE)*gpu_begin.offset(), 01322 sizeof(SCALARTYPE)*gpu_begin.stride() * (gpu_end - gpu_begin), 01323 &(*cpu_begin), 01324 true); 01325 } 01326 else // no async copy possible, so fall-back to fast_copy 01327 fast_copy(gpu_begin, gpu_end, cpu_begin); 01328 } 01329 } 01330 01336 template <typename NumericT, typename CPUVECTOR> 01337 void async_copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01338 { 01339 viennacl::async_copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01340 } 01341 01342 01349 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01350 void copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01351 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01352 CPU_ITERATOR cpu_begin ) 01353 { 01354 assert(gpu_end - gpu_begin >= 0 && bool("Iterators incompatible")); 01355 if (gpu_end - gpu_begin != 0) 01356 { 01357 std::vector<SCALARTYPE> temp_buffer(gpu_end - gpu_begin); 01358 fast_copy(gpu_begin, gpu_end, temp_buffer.begin()); 01359 01360 //now copy entries to cpu_vec: 01361 std::copy(temp_buffer.begin(), temp_buffer.end(), cpu_begin); 01362 } 01363 } 01364 01371 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01372 void copy(const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01373 const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01374 CPU_ITERATOR cpu_begin ) 01375 01376 { 01377 viennacl::copy(const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_begin), 01378 const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_end), 01379 cpu_begin); 01380 } 01381 01387 template <typename NumericT, typename CPUVECTOR> 01388 void copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01389 { 01390 viennacl::copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01391 } 01392 01393 01394 01395 #ifdef VIENNACL_WITH_EIGEN 01396 template <unsigned int ALIGNMENT> 01397 void copy(vector<float, ALIGNMENT> const & gpu_vec, 01398 Eigen::VectorXf & eigen_vec) 01399 { 01400 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0])); 01401 } 01402 01403 template <unsigned int ALIGNMENT> 01404 void copy(vector<double, ALIGNMENT> & gpu_vec, 01405 Eigen::VectorXd & eigen_vec) 01406 { 01407 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0])); 01408 } 01409 #endif 01410 01411 01412 // 01414 // 01415 01427 template <typename CPU_ITERATOR, typename SCALARTYPE, unsigned int ALIGNMENT> 01428 void fast_copy(CPU_ITERATOR const & cpu_begin, 01429 CPU_ITERATOR const & cpu_end, 01430 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01431 { 01432 if (cpu_end - cpu_begin > 0) 01433 { 01434 if (gpu_begin.stride() == 1) 01435 { 01436 viennacl::backend::memory_write(gpu_begin.handle(), 01437 sizeof(SCALARTYPE)*gpu_begin.offset(), 01438 sizeof(SCALARTYPE)*gpu_begin.stride() * (cpu_end - cpu_begin), &(*cpu_begin)); 01439 } 01440 else //writing to slice: 01441 { 01442 vcl_size_t cpu_size = (cpu_end - cpu_begin); 01443 std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * cpu_size); 01444 01445 viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01446 01447 for (vcl_size_t i=0; i<cpu_size; ++i) 01448 temp_buffer[i * gpu_begin.stride()] = (&(*cpu_begin))[i]; 01449 01450 viennacl::backend::memory_write(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01451 } 01452 } 01453 } 01454 01455 01461 template <typename CPUVECTOR, typename NumericT> 01462 void fast_copy(const CPUVECTOR & cpu_vec, vector_base<NumericT> & gpu_vec) 01463 { 01464 viennacl::fast_copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01465 } 01466 01477 template <typename CPU_ITERATOR, typename SCALARTYPE, unsigned int ALIGNMENT> 01478 void async_copy(CPU_ITERATOR const & cpu_begin, 01479 CPU_ITERATOR const & cpu_end, 01480 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01481 { 01482 if (cpu_end - cpu_begin > 0) 01483 { 01484 if (gpu_begin.stride() == 1) 01485 { 01486 viennacl::backend::memory_write(gpu_begin.handle(), 01487 sizeof(SCALARTYPE)*gpu_begin.offset(), 01488 sizeof(SCALARTYPE)*gpu_begin.stride() * (cpu_end - cpu_begin), &(*cpu_begin), 01489 true); 01490 } 01491 else // fallback to blocking copy. There's nothing we can do to prevent this 01492 fast_copy(cpu_begin, cpu_end, gpu_begin); 01493 } 01494 } 01495 01496 01502 template <typename CPUVECTOR, typename NumericT> 01503 void async_copy(const CPUVECTOR & cpu_vec, vector_base<NumericT> & gpu_vec) 01504 { 01505 viennacl::async_copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01506 } 01507 01508 //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 01515 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01516 void copy(CPU_ITERATOR const & cpu_begin, 01517 CPU_ITERATOR const & cpu_end, 01518 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01519 { 01520 assert(cpu_end - cpu_begin > 0 && bool("Iterators incompatible")); 01521 if (cpu_begin != cpu_end) 01522 { 01523 //we require that the size of the gpu_vector is larger or equal to the cpu-size 01524 std::vector<SCALARTYPE> temp_buffer(cpu_end - cpu_begin); 01525 std::copy(cpu_begin, cpu_end, temp_buffer.begin()); 01526 viennacl::fast_copy(temp_buffer.begin(), temp_buffer.end(), gpu_begin); 01527 } 01528 } 01529 01530 // for things like copy(std_vec.begin(), std_vec.end(), vcl_vec.begin() + 1); 01531 01537 template <typename CPUVECTOR, typename T> 01538 void copy(const CPUVECTOR & cpu_vec, vector_base<T> & gpu_vec) 01539 { 01540 viennacl::copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01541 } 01542 01543 01544 #ifdef VIENNACL_WITH_EIGEN 01545 template <unsigned int ALIGNMENT> 01546 void copy(Eigen::VectorXf const & eigen_vec, 01547 vector<float, ALIGNMENT> & gpu_vec) 01548 { 01549 std::vector<float> entries(eigen_vec.size()); 01550 for (vcl_size_t i = 0; i<entries.size(); ++i) 01551 entries[i] = eigen_vec(i); 01552 viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin()); 01553 } 01554 01555 template <unsigned int ALIGNMENT> 01556 void copy(Eigen::VectorXd const & eigen_vec, 01557 vector<double, ALIGNMENT> & gpu_vec) 01558 { 01559 std::vector<double> entries(eigen_vec.size()); 01560 for (vcl_size_t i = 0; i<entries.size(); ++i) 01561 entries[i] = eigen_vec(i); 01562 viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin()); 01563 } 01564 #endif 01565 01566 01567 01568 // 01570 // 01577 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01578 void copy(const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin, 01579 const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end, 01580 vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin) 01581 { 01582 assert(gpu_src_end - gpu_src_begin >= 0); 01583 assert(gpu_src_begin.stride() == 1 && bool("ViennaCL ERROR: copy() for GPU->GPU not implemented for slices! Use operator= instead for the moment.")); 01584 01585 if (gpu_src_begin.stride() == 1 && gpu_dest_begin.stride() == 1) 01586 { 01587 if (gpu_src_begin != gpu_src_end) 01588 viennacl::backend::memory_copy(gpu_src_begin.handle(), gpu_dest_begin.handle(), 01589 sizeof(SCALARTYPE) * gpu_src_begin.offset(), 01590 sizeof(SCALARTYPE) * gpu_dest_begin.offset(), 01591 sizeof(SCALARTYPE) * (gpu_src_end.offset() - gpu_src_begin.offset())); 01592 } 01593 else 01594 { 01595 assert( false && bool("not implemented yet")); 01596 } 01597 } 01598 01605 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01606 void copy(vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin, 01607 vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end, 01608 vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin) 01609 { 01610 viennacl::copy(static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_begin), 01611 static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_end), 01612 gpu_dest_begin); 01613 } 01614 01620 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01621 void copy(vector<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_vec, 01622 vector<SCALARTYPE, ALIGNMENT_DEST> & gpu_dest_vec ) 01623 { 01624 viennacl::copy(gpu_src_vec.begin(), gpu_src_vec.end(), gpu_dest_vec.begin()); 01625 } 01626 01627 01628 01629 01630 01631 01632 //global functions for handling vectors: 01637 template <typename T> 01638 std::ostream & operator<<(std::ostream & os, vector_base<T> const & val) 01639 { 01640 std::vector<T> tmp(val.size()); 01641 viennacl::copy(val.begin(), val.end(), tmp.begin()); 01642 os << "[" << val.size() << "]("; 01643 for (typename std::vector<T>::size_type i=0; i<val.size(); ++i) 01644 { 01645 if (i > 0) 01646 os << ","; 01647 os << tmp[i]; 01648 } 01649 os << ")"; 01650 return os; 01651 } 01652 01653 template <typename LHS, typename RHS, typename OP> 01654 std::ostream & operator<<(std::ostream & os, vector_expression<LHS, RHS, OP> const & proxy) 01655 01656 { 01657 typedef typename viennacl::result_of::cpu_value_type<typename LHS::value_type>::type ScalarType; 01658 viennacl::vector<ScalarType> result = proxy; 01659 os << result; 01660 return os; 01661 } 01662 01668 template <typename T> 01669 void swap(vector_base<T> & vec1, vector_base<T> & vec2) 01670 { 01671 viennacl::linalg::vector_swap(vec1, vec2); 01672 } 01673 01679 template <typename SCALARTYPE, unsigned int ALIGNMENT> 01680 vector<SCALARTYPE, ALIGNMENT> & fast_swap(vector<SCALARTYPE, ALIGNMENT> & v1, 01681 vector<SCALARTYPE, ALIGNMENT> & v2) 01682 { 01683 return v1.fast_swap(v2); 01684 } 01685 01686 01687 01688 01689 01690 // 01691 // 01693 // 01694 // 01695 01696 01697 // 01698 // operator *= 01699 // 01700 01703 template <typename T, typename S1> 01704 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01705 vector_base<T> & 01706 >::type 01707 operator *= (vector_base<T> & v1, S1 const & gpu_val) 01708 { 01709 if (v1.size() > 0) 01710 viennacl::linalg::av(v1, 01711 v1, gpu_val, 1, false, (viennacl::is_flip_sign_scalar<S1>::value ? true : false)); 01712 return v1; 01713 } 01714 01715 01716 // 01717 // operator /= 01718 // 01719 01720 01723 template <typename T, typename S1> 01724 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01725 vector_base<T> & 01726 >::type 01727 operator /= (vector_base<T> & v1, S1 const & gpu_val) 01728 { 01729 if (v1.size() > 0) 01730 viennacl::linalg::av(v1, 01731 v1, gpu_val, 1, true, (viennacl::is_flip_sign_scalar<S1>::value ? true : false)); 01732 return v1; 01733 } 01734 01735 01736 // 01737 // operator + 01738 // 01739 01740 01746 template <typename LHS1, typename RHS1, typename OP1, 01747 typename LHS2, typename RHS2, typename OP2> 01748 vector_expression< const vector_expression< LHS1, RHS1, OP1>, 01749 const vector_expression< LHS2, RHS2, OP2>, 01750 viennacl::op_add> 01751 operator + (vector_expression<LHS1, RHS1, OP1> const & proxy1, 01752 vector_expression<LHS2, RHS2, OP2> const & proxy2) 01753 { 01754 assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!")); 01755 return vector_expression< const vector_expression<LHS1, RHS1, OP1>, 01756 const vector_expression<LHS2, RHS2, OP2>, 01757 viennacl::op_add>(proxy1, proxy2); 01758 } 01759 01765 template <typename LHS, typename RHS, typename OP, typename T> 01766 vector_expression< const vector_expression<LHS, RHS, OP>, 01767 const vector_base<T>, 01768 viennacl::op_add> 01769 operator + (vector_expression<LHS, RHS, OP> const & proxy, 01770 vector_base<T> const & vec) 01771 { 01772 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01773 return vector_expression< const vector_expression<LHS, RHS, OP>, 01774 const vector_base<T>, 01775 viennacl::op_add>(proxy, vec); 01776 } 01777 01783 template <typename T, typename LHS, typename RHS, typename OP> 01784 vector_expression< const vector_base<T>, 01785 const vector_expression<LHS, RHS, OP>, 01786 viennacl::op_add> 01787 operator + (vector_base<T> const & vec, 01788 vector_expression<LHS, RHS, OP> const & proxy) 01789 { 01790 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01791 return vector_expression< const vector_base<T>, 01792 const vector_expression<LHS, RHS, OP>, 01793 viennacl::op_add>(vec, proxy); 01794 } 01795 01798 template <typename T> 01799 vector_expression< const vector_base<T>, const vector_base<T>, op_add> 01800 operator + (const vector_base<T> & v1, const vector_base<T> & v2) 01801 { 01802 return vector_expression< const vector_base<T>, const vector_base<T>, op_add>(v1, v2); 01803 } 01804 01805 01806 01807 // 01808 // operator - 01809 // 01810 01816 template <typename LHS1, typename RHS1, typename OP1, 01817 typename LHS2, typename RHS2, typename OP2> 01818 vector_expression< const vector_expression< LHS1, RHS1, OP1>, 01819 const vector_expression< LHS2, RHS2, OP2>, 01820 viennacl::op_sub> 01821 operator - (vector_expression<LHS1, RHS1, OP1> const & proxy1, 01822 vector_expression<LHS2, RHS2, OP2> const & proxy2) 01823 { 01824 assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!")); 01825 return vector_expression< const vector_expression<LHS1, RHS1, OP1>, 01826 const vector_expression<LHS2, RHS2, OP2>, 01827 viennacl::op_sub>(proxy1, proxy2); 01828 } 01829 01830 01836 template <typename LHS, typename RHS, typename OP, typename T> 01837 vector_expression< const vector_expression<LHS, RHS, OP>, 01838 const vector_base<T>, 01839 viennacl::op_sub> 01840 operator - (vector_expression<LHS, RHS, OP> const & proxy, 01841 vector_base<T> const & vec) 01842 { 01843 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01844 return vector_expression< const vector_expression<LHS, RHS, OP>, 01845 const vector_base<T>, 01846 viennacl::op_sub>(proxy, vec); 01847 } 01848 01854 template <typename T, typename LHS, typename RHS, typename OP> 01855 vector_expression< const vector_base<T>, 01856 const vector_expression<LHS, RHS, OP>, 01857 viennacl::op_sub> 01858 operator - (vector_base<T> const & vec, 01859 vector_expression<LHS, RHS, OP> const & proxy) 01860 { 01861 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 01862 return vector_expression< const vector_base<T>, 01863 const vector_expression<LHS, RHS, OP>, 01864 viennacl::op_sub>(vec, proxy); 01865 } 01866 01869 template <typename T> 01870 vector_expression< const vector_base<T>, const vector_base<T>, op_sub> 01871 operator - (const vector_base<T> & v1, const vector_base<T> & v2) 01872 { 01873 return vector_expression< const vector_base<T>, const vector_base<T>, op_sub>(v1, v2); 01874 } 01875 01876 01877 // 01878 // operator * 01879 // 01880 01881 01887 template <typename S1, typename T> 01888 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01889 vector_expression< const vector_base<T>, const S1, op_mult> >::type 01890 operator * (S1 const & value, vector_base<T> const & vec) 01891 { 01892 return vector_expression< const vector_base<T>, const S1, op_mult>(vec, value); 01893 } 01894 01900 template <typename T> 01901 vector_expression< const vector_base<T>, const T, op_mult> 01902 operator * (char value, vector_base<T> const & vec) 01903 { 01904 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01905 } 01906 01912 template <typename T> 01913 vector_expression< const vector_base<T>, const T, op_mult> 01914 operator * (short value, vector_base<T> const & vec) 01915 { 01916 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01917 } 01918 01924 template <typename T> 01925 vector_expression< const vector_base<T>, const T, op_mult> 01926 operator * (int value, vector_base<T> const & vec) 01927 { 01928 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01929 } 01930 01936 template <typename T> 01937 vector_expression< const vector_base<T>, const T, op_mult> 01938 operator * (long value, vector_base<T> const & vec) 01939 { 01940 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01941 } 01942 01943 01944 01945 01951 template <typename LHS, typename RHS, typename OP, typename T> 01952 vector_expression< const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> 01953 operator * (scalar_expression<LHS, RHS, OP> const & expr, vector_base<T> const & vec) 01954 { 01955 return vector_expression< const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult>(vec, expr); 01956 } 01957 01960 template <typename T, typename S1> 01961 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01962 vector_expression< const vector_base<T>, const S1, op_mult> >::type 01963 operator * (vector_base<T> const & vec, S1 const & value) 01964 { 01965 return vector_expression< const vector_base<T>, const S1, op_mult>(vec, value); 01966 } 01967 01968 template <typename T> 01969 vector_expression< const vector_base<T>, const T, op_mult> 01970 operator * (vector_base<T> const & vec, T const & value) 01971 { 01972 return vector_expression< const vector_base<T>, const T, op_mult>(vec, value); 01973 } 01974 01980 template <typename LHS, typename RHS, typename OP, typename S1> 01981 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01982 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult> >::type 01983 operator * (vector_expression< LHS, RHS, OP> const & proxy, 01984 S1 const & val) 01985 { 01986 return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>(proxy, val); 01987 } 01988 01994 template <typename S1, typename LHS, typename RHS, typename OP> 01995 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01996 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult> >::type 01997 operator * (S1 const & val, 01998 vector_expression<LHS, RHS, OP> const & proxy) 01999 { 02000 return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>(proxy, val); 02001 } 02002 02003 // 02004 // operator / 02005 // 02006 02012 template <typename S1, typename LHS, typename RHS, typename OP> 02013 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02014 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_div> >::type 02015 operator / (vector_expression< LHS, RHS, OP> const & proxy, 02016 S1 const & val) 02017 { 02018 return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_div>(proxy, val); 02019 } 02020 02021 02024 template <typename T, typename S1> 02025 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02026 vector_expression< const vector_base<T>, const S1, op_div> >::type 02027 operator / (vector_base<T> const & v1, S1 const & s1) 02028 { 02029 return vector_expression<const vector_base<T>, const S1, op_div>(v1, s1); 02030 } 02031 02032 02033 02034 // 02035 // Specify available operations: 02036 // 02037 02040 namespace linalg 02041 { 02042 namespace detail 02043 { 02044 // x = y 02045 template <typename T> 02046 struct op_executor<vector_base<T>, op_assign, vector_base<T> > 02047 { 02048 static void apply(vector_base<T> & lhs, vector_base<T> const & rhs) 02049 { 02050 viennacl::linalg::av(lhs, rhs, T(1), 1, false, false); 02051 } 02052 }; 02053 02054 // x = inner_prod(z, {y0, y1, ...}) 02055 template <typename T> 02056 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const vector_tuple<T>, op_inner_prod> > 02057 { 02058 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_tuple<T>, op_inner_prod> const & rhs) 02059 { 02060 viennacl::linalg::inner_prod_impl(rhs.lhs(), rhs.rhs(), lhs); 02061 } 02062 }; 02063 02064 // x += y 02065 template <typename T> 02066 struct op_executor<vector_base<T>, op_inplace_add, vector_base<T> > 02067 { 02068 static void apply(vector_base<T> & lhs, vector_base<T> const & rhs) 02069 { 02070 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, rhs, T(1), 1, false, false); 02071 } 02072 }; 02073 02074 // x -= y 02075 template <typename T> 02076 struct op_executor<vector_base<T>, op_inplace_sub, vector_base<T> > 02077 { 02078 static void apply(vector_base<T> & lhs, vector_base<T> const & rhs) 02079 { 02080 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, rhs, T(1), 1, false, true); 02081 } 02082 }; 02083 02085 02086 02087 // x = alpha * y 02088 template <typename T, typename ScalarType> 02089 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const ScalarType, op_mult> > 02090 { 02091 // generic case: ScalarType is a scalar expression 02092 template <typename LHS, typename RHS, typename OP> 02093 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy) 02094 { 02095 T alpha = proxy.rhs(); 02096 viennacl::linalg::av(lhs, proxy.lhs(), alpha, 1, false, false); 02097 } 02098 02099 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy) 02100 { 02101 viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, false, false); 02102 } 02103 02104 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy) 02105 { 02106 viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, false, false); 02107 } 02108 }; 02109 02110 // x += alpha * y 02111 template <typename T, typename ScalarType> 02112 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_base<T>, const ScalarType, op_mult> > 02113 { 02114 // generic case: ScalarType is a scalar expression 02115 template <typename LHS, typename RHS, typename OP> 02116 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy) 02117 { 02118 T alpha = proxy.rhs(); 02119 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), alpha, 1, false, false); 02120 } 02121 02122 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy) 02123 { 02124 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, false); 02125 } 02126 02127 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy) 02128 { 02129 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, false); 02130 } 02131 }; 02132 02133 // x -= alpha * y 02134 template <typename T, typename ScalarType> 02135 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_base<T>, const ScalarType, op_mult> > 02136 { 02137 // generic case: ScalarType is a scalar expression 02138 template <typename LHS, typename RHS, typename OP> 02139 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy) 02140 { 02141 T alpha = proxy.rhs(); 02142 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), alpha, 1, false, true); 02143 } 02144 02145 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy) 02146 { 02147 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, true); 02148 } 02149 02150 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy) 02151 { 02152 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, true); 02153 } 02154 }; 02155 02156 02158 02159 // x = alpha * vec_expr 02160 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02161 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> > 02162 { 02163 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy) 02164 { 02165 vector<T> temp(proxy.lhs()); 02166 lhs = temp * proxy.rhs(); 02167 } 02168 }; 02169 02170 // x += alpha * vec_expr 02171 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02172 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> > 02173 { 02174 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy) 02175 { 02176 vector<T> temp(proxy.lhs()); 02177 lhs += temp * proxy.rhs(); 02178 } 02179 }; 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_inplace_sub, 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 02194 02195 // x = y / alpha 02196 template <typename T, typename ScalarType> 02197 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const ScalarType, op_div> > 02198 { 02199 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy) 02200 { 02201 viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, true, false); 02202 } 02203 }; 02204 02205 // x += y / alpha 02206 template <typename T, typename ScalarType> 02207 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_base<T>, const ScalarType, op_div> > 02208 { 02209 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy) 02210 { 02211 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, true, false); 02212 } 02213 }; 02214 02215 // x -= y / alpha 02216 template <typename T, typename ScalarType> 02217 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_base<T>, const ScalarType, op_div> > 02218 { 02219 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy) 02220 { 02221 viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, true, true); 02222 } 02223 }; 02224 02225 02227 02228 // x = vec_expr / alpha 02229 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02230 struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> > 02231 { 02232 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy) 02233 { 02234 vector<T> temp(proxy.lhs()); 02235 lhs = temp / proxy.rhs(); 02236 } 02237 }; 02238 02239 // x += vec_expr / alpha 02240 template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType> 02241 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> > 02242 { 02243 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy) 02244 { 02245 vector<T> temp(proxy.lhs()); 02246 lhs += temp / proxy.rhs(); 02247 } 02248 }; 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_inplace_sub, 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 02262 02263 // generic x = vec_expr1 + vec_expr2: 02264 template <typename T, typename LHS, typename RHS> 02265 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_add> > 02266 { 02267 // generic x = vec_expr1 + vec_expr2: 02268 template <typename LHS1, typename RHS1> 02269 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy) 02270 { 02271 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02272 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02273 02274 if (op_aliasing_lhs || op_aliasing_rhs) 02275 { 02276 vector_base<T> temp(proxy.lhs()); 02277 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs()); 02278 lhs = temp; 02279 } 02280 else 02281 { 02282 op_executor<vector_base<T>, op_assign, LHS>::apply(lhs, proxy.lhs()); 02283 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs()); 02284 } 02285 } 02286 02287 // x = y + z 02288 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy) 02289 { 02290 viennacl::linalg::avbv(lhs, 02291 proxy.lhs(), T(1), 1, false, false, 02292 proxy.rhs(), T(1), 1, false, false); 02293 } 02294 02295 // x = alpha * y + z 02296 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>, 02297 const vector_base<T>, 02298 op_add> const & proxy) 02299 { 02300 viennacl::linalg::avbv(lhs, 02301 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02302 proxy.rhs(), T(1), 1, false, false); 02303 } 02304 02305 // x = y / alpha + z 02306 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>, 02307 const vector_base<T>, 02308 op_add> const & proxy) 02309 { 02310 viennacl::linalg::avbv(lhs, 02311 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02312 proxy.rhs(), T(1), 1, false, false); 02313 } 02314 02315 // x = y + beta * z 02316 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02317 const vector_expression<const vector_base<T>, const T, op_mult>, 02318 op_add> const & proxy) 02319 { 02320 viennacl::linalg::avbv(lhs, 02321 proxy.lhs(), T(1), 1, false, false, 02322 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02323 } 02324 02325 // x = y + z / beta 02326 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02327 const vector_expression<const vector_base<T>, const T, op_div>, 02328 op_add> const & proxy) 02329 { 02330 viennacl::linalg::avbv(lhs, 02331 proxy.lhs(), T(1), 1, false, false, 02332 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02333 } 02334 02335 // x = alpha * y + beta * z 02336 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>, 02337 const vector_expression<const vector_base<T>, const T, op_mult>, 02338 op_add> const & proxy) 02339 { 02340 viennacl::linalg::avbv(lhs, 02341 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02342 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02343 } 02344 02345 // x = alpha * y + z / beta 02346 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>, 02347 const vector_expression<const vector_base<T>, const T, op_div>, 02348 op_add> const & proxy) 02349 { 02350 viennacl::linalg::avbv(lhs, 02351 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02352 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02353 } 02354 02355 // x = y / alpha + beta * z 02356 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>, 02357 const vector_expression<const vector_base<T>, const T, op_mult>, 02358 op_add> const & proxy) 02359 { 02360 viennacl::linalg::avbv(lhs, 02361 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02362 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02363 } 02364 02365 // x = y / alpha + z / beta 02366 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>, 02367 const vector_expression<const vector_base<T>, const T, op_div>, 02368 op_add> const & proxy) 02369 { 02370 viennacl::linalg::avbv(lhs, 02371 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02372 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02373 } 02374 }; 02375 02376 02377 // generic x += vec_expr1 + vec_expr2: 02378 template <typename T, typename LHS, typename RHS> 02379 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_add> > 02380 { 02381 // generic x += vec_expr1 + vec_expr2: 02382 template <typename LHS1, typename RHS1> 02383 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy) 02384 { 02385 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02386 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02387 02388 if (op_aliasing_lhs || op_aliasing_rhs) 02389 { 02390 vector_base<T> temp(proxy.lhs()); 02391 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs()); 02392 lhs += temp; 02393 } 02394 else 02395 { 02396 op_executor<vector_base<T>, op_inplace_add, LHS>::apply(lhs, proxy.lhs()); 02397 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs()); 02398 } 02399 } 02400 02401 // x += y + z 02402 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy) 02403 { 02404 viennacl::linalg::avbv_v(lhs, 02405 proxy.lhs(), T(1), 1, false, false, 02406 proxy.rhs(), T(1), 1, false, false); 02407 } 02408 02409 // x += alpha * y + z 02410 template <typename ScalarType> 02411 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02412 const vector_base<T>, 02413 op_add> const & proxy) 02414 { 02415 viennacl::linalg::avbv_v(lhs, 02416 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02417 proxy.rhs(), T(1), 1, false, false); 02418 } 02419 02420 // x += y / alpha + z 02421 template <typename ScalarType> 02422 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02423 const vector_base<T>, 02424 op_add> const & proxy) 02425 { 02426 viennacl::linalg::avbv_v(lhs, 02427 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02428 proxy.rhs(), T(1), 1, false, false); 02429 } 02430 02431 // x += y + beta * z 02432 template <typename ScalarType> 02433 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02434 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02435 op_add> const & proxy) 02436 { 02437 viennacl::linalg::avbv_v(lhs, 02438 proxy.lhs(), T(1), 1, false, false, 02439 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02440 } 02441 02442 // x += y + z / beta 02443 template <typename ScalarType> 02444 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02445 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02446 op_add> const & proxy) 02447 { 02448 viennacl::linalg::avbv_v(lhs, 02449 proxy.lhs(), T(1), 1, false, false, 02450 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02451 } 02452 02453 // x += alpha * y + beta * z 02454 template <typename ScalarType1, typename ScalarType2> 02455 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02456 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02457 op_add> const & proxy) 02458 { 02459 viennacl::linalg::avbv_v(lhs, 02460 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02461 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02462 } 02463 02464 // x += alpha * y + z / beta 02465 template <typename ScalarType1, typename ScalarType2> 02466 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02467 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02468 op_add> const & proxy) 02469 { 02470 viennacl::linalg::avbv_v(lhs, 02471 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02472 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02473 } 02474 02475 // x += y / alpha + 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_div>, 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, true, false, 02483 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02484 } 02485 02486 // x += y / alpha + 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_div>, 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, true, false, 02494 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02495 } 02496 }; 02497 02498 02499 02500 // generic x -= vec_expr1 + vec_expr2: 02501 template <typename T, typename LHS, typename RHS> 02502 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_add> > 02503 { 02504 // generic x -= vec_expr1 + vec_expr2: 02505 template <typename LHS1, typename RHS1> 02506 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy) 02507 { 02508 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02509 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02510 02511 if (op_aliasing_lhs || op_aliasing_rhs) 02512 { 02513 vector_base<T> temp(proxy.lhs()); 02514 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs()); 02515 lhs -= temp; 02516 } 02517 else 02518 { 02519 op_executor<vector_base<T>, op_inplace_sub, LHS>::apply(lhs, proxy.lhs()); 02520 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs()); 02521 } 02522 } 02523 02524 // x -= y + z 02525 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy) 02526 { 02527 viennacl::linalg::avbv_v(lhs, 02528 proxy.lhs(), T(1), 1, false, true, 02529 proxy.rhs(), T(1), 1, false, true); 02530 } 02531 02532 // x -= alpha * y + z 02533 template <typename ScalarType> 02534 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02535 const vector_base<T>, 02536 op_add> const & proxy) 02537 { 02538 viennacl::linalg::avbv_v(lhs, 02539 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02540 proxy.rhs(), T(1), 1, false, true); 02541 } 02542 02543 // x -= y / alpha + z 02544 template <typename ScalarType> 02545 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02546 const vector_base<T>, 02547 op_add> const & proxy) 02548 { 02549 viennacl::linalg::avbv_v(lhs, 02550 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 02551 proxy.rhs(), T(1), 1, false, true); 02552 } 02553 02554 // x -= y + beta * z 02555 template <typename ScalarType> 02556 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02557 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02558 op_add> const & proxy) 02559 { 02560 viennacl::linalg::avbv_v(lhs, 02561 proxy.lhs(), T(1), 1, false, true, 02562 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02563 } 02564 02565 // x -= y + z / beta 02566 template <typename ScalarType> 02567 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02568 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02569 op_add> const & proxy) 02570 { 02571 viennacl::linalg::avbv_v(lhs, 02572 proxy.lhs(), T(1), 1, false, true, 02573 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02574 } 02575 02576 // x -= alpha * y + beta * z 02577 template <typename ScalarType1, typename ScalarType2> 02578 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02579 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02580 op_add> const & proxy) 02581 { 02582 viennacl::linalg::avbv_v(lhs, 02583 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02584 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02585 } 02586 02587 // x -= alpha * y + z / beta 02588 template <typename ScalarType1, typename ScalarType2> 02589 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02590 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02591 op_add> const & proxy) 02592 { 02593 viennacl::linalg::avbv_v(lhs, 02594 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02595 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02596 } 02597 02598 // x -= y / alpha + 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_div>, 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, true, true, 02606 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02607 } 02608 02609 // x -= y / alpha + 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_div>, 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, true, true, 02617 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02618 } 02619 }; 02620 02621 02622 02624 02625 02626 02627 // generic x = vec_expr1 - vec_expr2: 02628 template <typename T, typename LHS, typename RHS> 02629 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_sub> > 02630 { 02631 // generic x = vec_expr1 - vec_expr2: 02632 template <typename LHS1, typename RHS1> 02633 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy) 02634 { 02635 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02636 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02637 02638 if (op_aliasing_lhs || op_aliasing_rhs) 02639 { 02640 vector_base<T> temp(proxy.lhs()); 02641 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs()); 02642 lhs = temp; 02643 } 02644 else 02645 { 02646 op_executor<vector_base<T>, op_assign, LHS>::apply(lhs, proxy.lhs()); 02647 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs()); 02648 } 02649 } 02650 02651 // x = y - z 02652 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy) 02653 { 02654 viennacl::linalg::avbv(lhs, 02655 proxy.lhs(), T(1), 1, false, false, 02656 proxy.rhs(), T(1), 1, false, true); 02657 } 02658 02659 // x = alpha * y - z 02660 template <typename ScalarType> 02661 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02662 const vector_base<T>, 02663 op_sub> const & proxy) 02664 { 02665 viennacl::linalg::avbv(lhs, 02666 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02667 proxy.rhs(), T(1), 1, false, true); 02668 } 02669 02670 // x = y / alpha - z 02671 template <typename ScalarType> 02672 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02673 const vector_base<T>, 02674 op_sub> const & proxy) 02675 { 02676 viennacl::linalg::avbv(lhs, 02677 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02678 proxy.rhs(), T(1), 1, false, true); 02679 } 02680 02681 // x = y - beta * z 02682 template <typename ScalarType> 02683 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02684 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02685 op_sub> const & proxy) 02686 { 02687 viennacl::linalg::avbv(lhs, 02688 proxy.lhs(), T(1), 1, false, false, 02689 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02690 } 02691 02692 // x = y - z / beta 02693 template <typename ScalarType> 02694 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02695 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02696 op_sub> const & proxy) 02697 { 02698 viennacl::linalg::avbv(lhs, 02699 proxy.lhs(), T(1), 1, false, false, 02700 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02701 } 02702 02703 // x = alpha * y - beta * z 02704 template <typename ScalarType1, typename ScalarType2> 02705 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02706 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02707 op_sub> const & proxy) 02708 { 02709 viennacl::linalg::avbv(lhs, 02710 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02711 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02712 } 02713 02714 // x = alpha * y - z / beta 02715 template <typename ScalarType1, typename ScalarType2> 02716 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02717 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02718 op_sub> const & proxy) 02719 { 02720 viennacl::linalg::avbv(lhs, 02721 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02722 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02723 } 02724 02725 // x = y / alpha - 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_div>, 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, true, false, 02733 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02734 } 02735 02736 // x = y / alpha - 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_div>, 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, true, false, 02744 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02745 } 02746 }; 02747 02748 02749 // generic x += vec_expr1 - vec_expr2: 02750 template <typename T, typename LHS, typename RHS> 02751 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_sub> > 02752 { 02753 // generic x += vec_expr1 - vec_expr2: 02754 template <typename LHS1, typename RHS1> 02755 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy) 02756 { 02757 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02758 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02759 02760 if (op_aliasing_lhs || op_aliasing_rhs) 02761 { 02762 vector_base<T> temp(proxy.lhs()); 02763 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs()); 02764 lhs += temp; 02765 } 02766 else 02767 { 02768 op_executor<vector_base<T>, op_inplace_add, LHS>::apply(lhs, proxy.lhs()); 02769 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs()); 02770 } 02771 } 02772 02773 // x += y - z 02774 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy) 02775 { 02776 viennacl::linalg::avbv_v(lhs, 02777 proxy.lhs(), T(1), 1, false, false, 02778 proxy.rhs(), T(1), 1, false, true); 02779 } 02780 02781 // x += alpha * y - z 02782 template <typename ScalarType> 02783 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02784 const vector_base<T>, 02785 op_sub> const & proxy) 02786 { 02787 viennacl::linalg::avbv_v(lhs, 02788 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02789 proxy.rhs(), T(1), 1, false, true); 02790 } 02791 02792 // x += y / alpha - z 02793 template <typename ScalarType> 02794 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02795 const vector_base<T>, 02796 op_sub> const & proxy) 02797 { 02798 viennacl::linalg::avbv_v(lhs, 02799 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false, 02800 proxy.rhs(), T(1), 1, false, true); 02801 } 02802 02803 // x += y - beta * z 02804 template <typename ScalarType> 02805 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02806 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02807 op_sub> const & proxy) 02808 { 02809 viennacl::linalg::avbv_v(lhs, 02810 proxy.lhs(), T(1), 1, false, false, 02811 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02812 } 02813 02814 // x += y - z / beta 02815 template <typename ScalarType> 02816 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02817 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02818 op_sub> const & proxy) 02819 { 02820 viennacl::linalg::avbv_v(lhs, 02821 proxy.lhs(), T(1), 1, false, false, 02822 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02823 } 02824 02825 // x += alpha * y - beta * z 02826 template <typename ScalarType1, typename ScalarType2> 02827 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02828 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02829 op_sub> const & proxy) 02830 { 02831 viennacl::linalg::avbv_v(lhs, 02832 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02833 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02834 } 02835 02836 // x += alpha * y - z / beta 02837 template <typename ScalarType1, typename ScalarType2> 02838 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02839 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02840 op_sub> const & proxy) 02841 { 02842 viennacl::linalg::avbv_v(lhs, 02843 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false, 02844 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02845 } 02846 02847 // x += y / alpha - 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_div>, 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, true, false, 02855 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true); 02856 } 02857 02858 // x += y / alpha - 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_div>, 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, true, false, 02866 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true); 02867 } 02868 }; 02869 02870 02871 02872 // generic x -= vec_expr1 - vec_expr2: 02873 template <typename T, typename LHS, typename RHS> 02874 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_sub> > 02875 { 02876 // generic x -= vec_expr1 - vec_expr2: 02877 template <typename LHS1, typename RHS1> 02878 static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy) 02879 { 02880 bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs()); 02881 bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs()); 02882 02883 if (op_aliasing_lhs || op_aliasing_rhs) 02884 { 02885 vector_base<T> temp(proxy.lhs()); 02886 op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs()); 02887 lhs -= temp; 02888 } 02889 else 02890 { 02891 op_executor<vector_base<T>, op_inplace_sub, LHS>::apply(lhs, proxy.lhs()); 02892 op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs()); 02893 } 02894 } 02895 02896 // x -= y - z 02897 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy) 02898 { 02899 viennacl::linalg::avbv_v(lhs, 02900 proxy.lhs(), T(1), 1, false, true, 02901 proxy.rhs(), T(1), 1, false, false); 02902 } 02903 02904 // x -= alpha * y - z 02905 template <typename ScalarType> 02906 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02907 const vector_base<T>, 02908 op_sub> const & proxy) 02909 { 02910 viennacl::linalg::avbv_v(lhs, 02911 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02912 proxy.rhs(), T(1), 1, false, false); 02913 } 02914 02915 // x -= y / alpha - z 02916 template <typename ScalarType> 02917 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02918 const vector_base<T>, 02919 op_sub> const & proxy) 02920 { 02921 viennacl::linalg::avbv_v(lhs, 02922 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true, 02923 proxy.rhs(), T(1), 1, false, false); 02924 } 02925 02926 // x -= y - beta * z 02927 template <typename ScalarType> 02928 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02929 const vector_expression<const vector_base<T>, const ScalarType, op_mult>, 02930 op_sub> const & proxy) 02931 { 02932 viennacl::linalg::avbv_v(lhs, 02933 proxy.lhs(), T(1), 1, false, true, 02934 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02935 } 02936 02937 // x -= y - z / beta 02938 template <typename ScalarType> 02939 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, 02940 const vector_expression<const vector_base<T>, const ScalarType, op_div>, 02941 op_sub> const & proxy) 02942 { 02943 viennacl::linalg::avbv_v(lhs, 02944 proxy.lhs(), T(1), 1, false, true, 02945 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02946 } 02947 02948 // x -= alpha * y - beta * z 02949 template <typename ScalarType1, typename ScalarType2> 02950 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02951 const vector_expression<const vector_base<T>, const ScalarType2, op_mult>, 02952 op_sub> const & proxy) 02953 { 02954 viennacl::linalg::avbv_v(lhs, 02955 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02956 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02957 } 02958 02959 // x -= alpha * y - z / beta 02960 template <typename ScalarType1, typename ScalarType2> 02961 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>, 02962 const vector_expression<const vector_base<T>, const ScalarType2, op_div>, 02963 op_sub> const & proxy) 02964 { 02965 viennacl::linalg::avbv_v(lhs, 02966 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true, 02967 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02968 } 02969 02970 // x -= y / alpha - 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_div>, 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, true, true, 02978 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false); 02979 } 02980 02981 // x -= y / alpha - 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_div>, 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, true, true, 02989 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false); 02990 } 02991 }; 02992 02993 02994 02995 02996 02997 02998 02999 03000 03001 03002 03003 03004 03005 03006 03007 03008 03009 03011 03012 // generic x = vec_expr1 .* vec_expr2: 03013 template <typename T, typename LHS, typename RHS, typename OP> 03014 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_element_binary<OP> > > 03015 { 03016 // x = y .* z or x = y ./ z 03017 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03018 { 03019 viennacl::linalg::element_op(lhs, proxy); 03020 } 03021 03022 // x = y .* vec_expr or x = y ./ vec_expr 03023 template <typename LHS2, typename RHS2, typename OP2> 03024 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) 03025 { 03026 vector<T> temp(proxy.rhs()); 03027 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp)); 03028 } 03029 03030 // x = vec_expr .* z or x = vec_expr ./ z 03031 template <typename LHS1, typename RHS1, typename OP1> 03032 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) 03033 { 03034 vector<T> temp(proxy.lhs()); 03035 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs())); 03036 } 03037 03038 // x = vec_expr .* vec_expr or z = vec_expr .* vec_expr 03039 template <typename LHS1, typename RHS1, typename OP1, 03040 typename LHS2, typename RHS2, typename OP2> 03041 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, 03042 const vector_expression<const LHS2, const RHS2, OP2>, 03043 op_element_binary<OP> > const & proxy) 03044 { 03045 vector<T> temp1(proxy.lhs()); 03046 vector<T> temp2(proxy.rhs()); 03047 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2)); 03048 } 03049 }; 03050 03051 // generic x += vec_expr1 .* vec_expr2: 03052 template <typename T, typename LHS, typename RHS, typename OP> 03053 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_element_binary<OP> > > 03054 { 03055 // x += y .* z or x += y ./ z 03056 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03057 { 03058 viennacl::vector<T> temp(proxy); 03059 lhs += temp; 03060 } 03061 03062 // x += y .* vec_expr or x += y ./ vec_expr 03063 template <typename LHS2, typename RHS2, typename OP2> 03064 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) 03065 { 03066 vector<T> temp(proxy.rhs()); 03067 vector<T> temp2(temp.size()); 03068 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp)); 03069 lhs += temp2; 03070 } 03071 03072 // x += vec_expr .* z or x += vec_expr ./ z 03073 template <typename LHS1, typename RHS1, typename OP1> 03074 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) 03075 { 03076 vector<T> temp(proxy.lhs()); 03077 vector<T> temp2(temp.size()); 03078 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs())); 03079 lhs += temp2; 03080 } 03081 03082 // x += vec_expr .* vec_expr or x += vec_expr ./ vec_expr 03083 template <typename LHS1, typename RHS1, typename OP1, 03084 typename LHS2, typename RHS2, typename OP2> 03085 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, 03086 const vector_expression<const LHS2, const RHS2, OP2>, 03087 op_element_binary<OP> > const & proxy) 03088 { 03089 vector<T> temp1(proxy.lhs()); 03090 vector<T> temp2(proxy.rhs()); 03091 vector<T> temp3(temp1.size()); 03092 viennacl::linalg::element_op(temp3, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2)); 03093 lhs += temp3; 03094 } 03095 }; 03096 03097 // generic x -= vec_expr1 .* vec_expr2: 03098 template <typename T, typename LHS, typename RHS, typename OP> 03099 struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_element_binary<OP> > > 03100 { 03101 03102 // x -= y .* z or x -= y ./ z 03103 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy) 03104 { 03105 viennacl::vector<T> temp(proxy); 03106 lhs -= temp; 03107 } 03108 03109 // x -= y .* vec_expr or x -= y ./ vec_expr 03110 template <typename LHS2, typename RHS2, typename OP2> 03111 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) 03112 { 03113 vector<T> temp(proxy.rhs()); 03114 vector<T> temp2(temp.size()); 03115 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp)); 03116 lhs -= temp2; 03117 } 03118 03119 // x -= vec_expr .* z or x -= vec_expr ./ z 03120 template <typename LHS1, typename RHS1, typename OP1> 03121 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) 03122 { 03123 vector<T> temp(proxy.lhs()); 03124 vector<T> temp2(temp.size()); 03125 viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs())); 03126 lhs -= temp2; 03127 } 03128 03129 // x -= vec_expr .* vec_expr or x -= vec_expr ./ vec_expr 03130 template <typename LHS1, typename RHS1, typename OP1, 03131 typename LHS2, typename RHS2, typename OP2> 03132 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, 03133 const vector_expression<const LHS2, const RHS2, OP2>, 03134 op_element_binary<OP> > const & proxy) 03135 { 03136 vector<T> temp1(proxy.lhs()); 03137 vector<T> temp2(proxy.rhs()); 03138 vector<T> temp3(temp1.size()); 03139 viennacl::linalg::element_op(temp3, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2)); 03140 lhs -= temp3; 03141 } 03142 }; 03143 03145 03146 template <typename T, typename LHS, typename RHS, typename OP> 03147 struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_element_unary<OP> > > 03148 { 03149 // x = OP(y) 03150 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy) 03151 { 03152 viennacl::linalg::element_op(lhs, proxy); 03153 } 03154 03155 // x = OP(vec_expr) 03156 template <typename LHS2, typename RHS2, typename OP2> 03157 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>, 03158 const vector_expression<const LHS2, const RHS2, OP2>, 03159 op_element_unary<OP> > const & proxy) 03160 { 03161 vector<T> temp(proxy.rhs()); 03162 viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> >(temp, temp)); 03163 } 03164 }; 03165 03166 template <typename T, typename LHS, typename RHS, typename OP> 03167 struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_element_unary<OP> > > 03168 { 03169 // x += OP(y) 03170 static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy) 03171 { 03172 vector<T> temp(proxy); 03173 lhs += temp; 03174 } 03175 03176 // x += OP(vec_expr) 03177 template <typename LHS2, typename RHS2, typename OP2> 03178 static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>, 03179 const vector_expression<const LHS2, const RHS2, OP2>, 03180 op_element_unary<OP> > const & proxy) 03181 { 03182 vector<T> temp(proxy.rhs()); 03183 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 03184 lhs += temp; 03185 } 03186 }; 03187 03188 template <typename T, typename LHS, typename RHS, typename OP> 03189 struct op_executor<vector_base<T>, op_inplace_sub, 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 } // namespace detail 03211 03212 } // namespace linalg 03213 03216 } // namespace viennacl 03217 03218 #endif