|
ViennaCL - The Vienna Computing Library
1.4.2
|
00001 #ifndef VIENNACL_VECTOR_HPP_ 00002 #define VIENNACL_VECTOR_HPP_ 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2013, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 Portions of this software are copyright by UChicago Argonne, LLC. 00009 00010 ----------------- 00011 ViennaCL - The Vienna Computing Library 00012 ----------------- 00013 00014 Project Head: Karl Rupp rupp@iue.tuwien.ac.at 00015 00016 (A list of authors and contributors can be found in the PDF manual) 00017 00018 License: MIT (X11), see file LICENSE in the base directory 00019 ============================================================================= */ 00020 00027 #include "viennacl/forwards.h" 00028 #include "viennacl/backend/memory.hpp" 00029 #include "viennacl/scalar.hpp" 00030 #include "viennacl/tools/tools.hpp" 00031 #include "viennacl/tools/entry_proxy.hpp" 00032 #include "viennacl/linalg/vector_operations.hpp" 00033 #include "viennacl/meta/result_of.hpp" 00034 00035 00036 namespace viennacl 00037 { 00038 // 00039 // Initializer types 00040 // 00042 template <typename SCALARTYPE> 00043 class unit_vector 00044 { 00045 public: 00046 typedef vcl_size_t size_type; 00047 00048 unit_vector(size_type s, size_type ind) : size_(s), index_(ind) 00049 { 00050 assert( (ind < s) && bool("Provided index out of range!") ); 00051 } 00052 00053 size_type size() const { return size_; } 00054 size_type index() const { return index_; } 00055 00056 private: 00057 size_type size_; 00058 size_type index_; 00059 }; 00060 00061 00063 template <typename SCALARTYPE> 00064 class zero_vector 00065 { 00066 public: 00067 typedef vcl_size_t size_type; 00068 typedef SCALARTYPE const_reference; 00069 00070 zero_vector(size_type s) : size_(s) {} 00071 00072 size_type size() const { return size_; } 00073 const_reference operator()(size_type /*i*/) const { return 0; } 00074 const_reference operator[](size_type /*i*/) const { return 0; } 00075 00076 private: 00077 size_type size_; 00078 }; 00079 00080 00082 template <typename SCALARTYPE> 00083 class scalar_vector 00084 { 00085 public: 00086 typedef vcl_size_t size_type; 00087 typedef SCALARTYPE const & const_reference; 00088 00089 scalar_vector(size_type s, SCALARTYPE val) : size_(s), value_(val) {} 00090 00091 size_type size() const { return size_; } 00092 const_reference operator()(size_type /*i*/) const { return value_; } 00093 const_reference operator[](size_type /*i*/) const { return value_; } 00094 00095 private: 00096 size_type size_; 00097 SCALARTYPE value_; 00098 }; 00099 00100 00101 // 00102 // Vector expression 00103 // 00104 00117 template <typename LHS, typename RHS, typename OP> 00118 class vector_expression 00119 { 00120 typedef typename result_of::reference_if_nonscalar<LHS>::type lhs_reference_type; 00121 typedef typename result_of::reference_if_nonscalar<RHS>::type rhs_reference_type; 00122 00123 public: 00124 enum { alignment = 1 }; 00125 00128 typedef typename viennacl::tools::VECTOR_EXTRACTOR<LHS, RHS>::ResultType VectorType; 00129 typedef vcl_size_t size_type; 00130 00131 vector_expression(LHS & l, RHS & r) : lhs_(l), rhs_(r) {} 00132 00135 lhs_reference_type lhs() const { return lhs_; } 00138 rhs_reference_type rhs() const { return rhs_; } 00139 00141 size_type size() const { return viennacl::traits::size(*this); } 00142 00143 private: 00145 lhs_reference_type lhs_; 00147 rhs_reference_type rhs_; 00148 }; 00149 00168 template<class SCALARTYPE, unsigned int ALIGNMENT> 00169 class const_vector_iterator 00170 { 00171 typedef const_vector_iterator<SCALARTYPE, ALIGNMENT> self_type; 00172 public: 00173 typedef scalar<SCALARTYPE> value_type; 00174 typedef long difference_type; 00175 typedef backend::mem_handle handle_type; 00176 00177 //const_vector_iterator() {}; 00178 00185 const_vector_iterator(vector_base<SCALARTYPE> const & vec, 00186 std::size_t index, 00187 std::size_t start = 0, 00188 vcl_ptrdiff_t stride = 1) : elements_(vec.handle()), index_(index), start_(start), stride_(stride) {}; 00189 00196 const_vector_iterator(handle_type const & elements, 00197 std::size_t index, 00198 std::size_t start = 0, 00199 vcl_ptrdiff_t stride = 1) : elements_(elements), index_(index), start_(start), stride_(stride) {}; 00200 00202 value_type operator*(void) const 00203 { 00204 value_type result; 00205 result = const_entry_proxy<SCALARTYPE>(start_ + index_ * stride_, elements_); 00206 return result; 00207 } 00208 self_type operator++(void) { index_ += stride_; return *this; } 00209 self_type operator++(int) { self_type tmp = *this; ++(*this); return tmp; } 00210 00211 bool operator==(self_type const & other) const { return index_ == other.index_; } 00212 bool operator!=(self_type const & other) const { return index_ != other.index_; } 00213 00214 // self_type & operator=(self_type const & other) 00215 // { 00216 // index_ = other._index; 00217 // elements_ = other._elements; 00218 // return *this; 00219 // } 00220 00221 difference_type operator-(self_type const & other) const 00222 { 00223 assert( (other.start_ == start_) && (other.stride_ == stride_) && bool("Iterators are not from the same vector (proxy)!")); 00224 return static_cast<difference_type>(index_) - static_cast<difference_type>(other.index_); 00225 } 00226 self_type operator+(difference_type diff) const { return self_type(elements_, index_ + diff * stride_, start_, stride_); } 00227 00228 //std::size_t index() const { return index_; } 00230 std::size_t offset() const { return start_ + index_ * stride_; } 00231 00233 std::size_t stride() const { return stride_; } 00234 handle_type const & handle() const { return elements_; } 00235 00236 protected: 00238 handle_type const & elements_; 00239 std::size_t index_; //offset from the beginning of elements_ 00240 std::size_t start_; 00241 vcl_ptrdiff_t stride_; 00242 }; 00243 00244 00264 template<class SCALARTYPE, unsigned int ALIGNMENT> 00265 class vector_iterator : public const_vector_iterator<SCALARTYPE, ALIGNMENT> 00266 { 00267 typedef const_vector_iterator<SCALARTYPE, ALIGNMENT> base_type; 00268 typedef vector_iterator<SCALARTYPE, ALIGNMENT> self_type; 00269 public: 00270 typedef typename base_type::handle_type handle_type; 00271 typedef typename base_type::difference_type difference_type; 00272 00273 vector_iterator() : base_type(), elements_(NULL) {}; 00274 vector_iterator(handle_type & elements, 00275 std::size_t index, 00276 std::size_t start = 0, 00277 vcl_ptrdiff_t stride = 1) : base_type(elements, index, start, stride), elements_(elements) {}; 00284 vector_iterator(vector_base<SCALARTYPE> & vec, 00285 std::size_t index, 00286 std::size_t start = 0, 00287 vcl_ptrdiff_t stride = 1) : base_type(vec, index, start, stride), elements_(vec.handle()) {}; 00288 //vector_iterator(base_type const & b) : base_type(b) {}; 00289 00290 typename base_type::value_type operator*(void) 00291 { 00292 typename base_type::value_type result; 00293 result = entry_proxy<SCALARTYPE>(base_type::start_ + base_type::index_ * base_type::stride_, elements_); 00294 return result; 00295 } 00296 00297 difference_type operator-(self_type const & other) const { difference_type result = base_type::index_; return (result - static_cast<difference_type>(other.index_)); } 00298 self_type operator+(difference_type diff) const { return self_type(elements_, base_type::index_ + diff * base_type::stride_, base_type::start_, base_type::stride_); } 00299 00300 handle_type & handle() { return elements_; } 00301 handle_type const & handle() const { return base_type::elements_; } 00302 00303 //operator base_type() const 00304 //{ 00305 // return base_type(base_type::elements_, base_type::index_, base_type::start_, base_type::stride_); 00306 //} 00307 private: 00308 handle_type & elements_; 00309 }; 00310 00311 00316 template<class SCALARTYPE, typename SizeType /* see forwards.h for default type */, typename DistanceType /* see forwards.h for default type */> 00317 class vector_base 00318 { 00319 typedef vector_base<SCALARTYPE> self_type; 00320 00321 public: 00322 typedef scalar<typename viennacl::tools::CHECK_SCALAR_TEMPLATE_ARGUMENT<SCALARTYPE>::ResultType> value_type; 00323 typedef SCALARTYPE cpu_value_type; 00324 typedef backend::mem_handle handle_type; 00325 typedef SizeType size_type; 00326 typedef DistanceType difference_type; 00327 typedef const_vector_iterator<SCALARTYPE, 1> const_iterator; 00328 typedef vector_iterator<SCALARTYPE, 1> iterator; 00329 00330 static const size_type alignment = 1; 00331 00334 explicit vector_base() : size_(0), start_(0), stride_(1) { /* Note: One must not call ::init() here because a vector might have been created globally before the backend has become available */ } 00335 00345 explicit vector_base(viennacl::backend::mem_handle & h, 00346 size_type vec_size, size_type vec_start, difference_type vec_stride) : size_(vec_size), start_(vec_start), stride_(vec_stride), elements_(h) {} 00347 00349 explicit vector_base(size_type vec_size) : size_(vec_size), start_(0), stride_(1) 00350 { 00351 if (size_ > 0) 00352 { 00353 std::vector<SCALARTYPE> temp(internal_size()); 00354 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), &(temp[0])); 00355 pad(); 00356 } 00357 } 00358 00360 explicit vector_base(size_type vec_size, viennacl::memory_types mem_type) : size_(vec_size), start_(0), stride_(1) 00361 { 00362 elements_.switch_active_handle_id(mem_type); 00363 if (size_ > 0) 00364 { 00365 std::vector<SCALARTYPE> temp(internal_size()); 00366 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size(), &(temp[0])); 00367 pad(); 00368 } 00369 } 00370 00371 // 00372 // operator= 00373 // 00374 00375 00378 self_type & operator=(const self_type & vec) 00379 { 00380 assert( ( (vec.size() == size()) || (size() == 0) ) 00381 && bool("Incompatible vector sizes!")); 00382 00383 if (vec.size() > 0) 00384 { 00385 if (size_ == 0) 00386 { 00387 size_ = vec.size(); 00388 elements_.switch_active_handle_id(vec.handle().get_active_handle_id()); 00389 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00390 } 00391 00392 viennacl::linalg::av(*this, 00393 vec, cpu_value_type(1.0), 1, false, false); 00394 } 00395 00396 return *this; 00397 } 00398 00399 00404 template <typename T, typename S1, typename OP> 00405 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 00406 self_type & >::type 00407 operator = (const vector_expression< const vector_base<T>, const S1, OP> & proxy) 00408 { 00409 assert( ( (proxy.lhs().size() == size()) || (size() == 0) ) 00410 && bool("Incompatible vector sizes!")); 00411 00412 // initialize the necessary buffer 00413 if (size() == 0) 00414 { 00415 size_ = proxy.lhs().size(); 00416 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00417 pad(); 00418 } 00419 00420 viennacl::linalg::av(*this, 00421 proxy.lhs(), proxy.rhs(), 1, (viennacl::is_division<OP>::value ? true : false), false); 00422 00423 return *this; 00424 } 00425 00426 //v1 = v2 +- v3; 00431 template <typename T, typename OP> 00432 typename viennacl::enable_if< viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value, 00433 self_type &>::type 00434 operator = (const vector_expression< const vector_base<T>, 00435 const vector_base<T>, 00436 OP> & proxy) 00437 { 00438 assert( ( (proxy.lhs().size() == size()) || (size() == 0) ) 00439 && bool("Incompatible vector sizes!")); 00440 00441 if (size() == 0) 00442 { 00443 size_ = proxy.lhs().size(); 00444 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00445 pad(); 00446 } 00447 00448 viennacl::linalg::avbv(*this, 00449 proxy.lhs(), SCALARTYPE(1.0), 1, false, false, 00450 proxy.rhs(), SCALARTYPE(1.0), 1, false, (viennacl::is_subtraction<OP>::value ? true : false)); 00451 return *this; 00452 } 00453 00458 template <typename T, typename S2, typename OP2, 00459 typename OP> 00460 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value && (viennacl::is_product<OP2>::value || viennacl::is_division<OP2>::value) 00461 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 00462 self_type &>::type 00463 operator = (const vector_expression< const vector_base<T>, 00464 const vector_expression<const vector_base<T>, const S2, OP2>, 00465 OP> & proxy) 00466 { 00467 assert( ( (proxy.lhs().size() == size()) || (size() == 0) ) 00468 && bool("Incompatible vector sizes!")); 00469 00470 if (size() == 0) 00471 { 00472 size_ = proxy.lhs().size(); 00473 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00474 pad(); 00475 } 00476 00477 bool flip_sign_2 = (viennacl::is_subtraction<OP>::value ? true : false); 00478 if (viennacl::is_flip_sign_scalar<S2>::value) 00479 flip_sign_2 = !flip_sign_2; 00480 viennacl::linalg::avbv(*this, 00481 proxy.lhs(), SCALARTYPE(1.0), 1, false , false, 00482 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, (viennacl::is_division<OP2>::value ? true : false), flip_sign_2); 00483 00484 return *this; 00485 } 00486 00491 template <typename T, typename S1, typename OP1, 00492 typename OP> 00493 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value && (viennacl::is_product<OP1>::value || viennacl::is_division<OP1>::value) 00494 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 00495 self_type &>::type 00496 operator = (const vector_expression< const vector_expression<const vector_base<T>, const S1, OP1>, 00497 const vector_base<T>, 00498 OP> & proxy) 00499 { 00500 assert( ( (proxy.size() == size()) || (size() == 0) ) 00501 && bool("Incompatible vector sizes!")); 00502 00503 if (size() == 0) 00504 { 00505 size_ = proxy.lhs().size(); 00506 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00507 pad(); 00508 } 00509 00510 viennacl::linalg::avbv(*this, 00511 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, (viennacl::is_division<OP1>::value ? true : false), (viennacl::is_flip_sign_scalar<S1>::value ? true : false), 00512 proxy.rhs(), SCALARTYPE(1.0), 1, false , (viennacl::is_subtraction<OP>::value ? true : false)); 00513 return *this; 00514 } 00515 00520 template <typename T, 00521 typename S1, typename OP1, 00522 typename S2, typename OP2, 00523 typename OP> 00524 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value && (viennacl::is_product<OP1>::value || viennacl::is_division<OP1>::value) 00525 && viennacl::is_any_scalar<S2>::value && (viennacl::is_product<OP2>::value || viennacl::is_division<OP2>::value) 00526 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 00527 self_type &>::type 00528 operator = (const vector_expression< const vector_expression<const vector_base<T>, const S1, OP1>, 00529 const vector_expression<const vector_base<T>, const S2, OP2>, 00530 OP> & proxy) 00531 { 00532 assert( ( (proxy.lhs().size() == size()) || (size() == 0) ) 00533 && bool("Incompatible vector sizes!")); 00534 00535 if (size() == 0) 00536 { 00537 size_ = proxy.lhs().size(); 00538 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00539 pad(); 00540 } 00541 00542 bool flip_sign_2 = (viennacl::is_subtraction<OP>::value ? true : false); 00543 if (viennacl::is_flip_sign_scalar<S2>::value) 00544 flip_sign_2 = !flip_sign_2; 00545 viennacl::linalg::avbv(*this, 00546 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, (viennacl::is_division<OP1>::value ? true : false), (viennacl::is_flip_sign_scalar<S1>::value ? true : false), 00547 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, (viennacl::is_division<OP2>::value ? true : false), flip_sign_2); 00548 00549 return *this; 00550 } 00551 00552 00553 //v1 = v2 * / v3; 00558 template <typename T, typename OP> 00559 typename viennacl::enable_if< (viennacl::is_product<OP>::value || viennacl::is_division<OP>::value), 00560 self_type &>::type 00561 operator = (const vector_expression< const vector_base<T>, 00562 const vector_base<T>, 00563 OP> & proxy) 00564 { 00565 assert( ( (proxy.lhs().size() == size()) || (size() == 0) ) 00566 && bool("Incompatible vector sizes!")); 00567 00568 if (size() == 0) 00569 { 00570 size_ = proxy.lhs().size(); 00571 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00572 pad(); 00573 } 00574 00575 viennacl::linalg::element_op(*this, proxy); 00576 return *this; 00577 } 00578 00579 00580 00581 // assign vector range or vector slice 00582 template <typename T> 00583 self_type & 00584 operator = (const vector_base<T> & v1) 00585 { 00586 assert( ( (v1.size() == size()) || (size() == 0) ) 00587 && bool("Incompatible vector sizes!")); 00588 00589 if (size() == 0) 00590 { 00591 size_ = v1.size(); 00592 if (size_ > 0) 00593 { 00594 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00595 pad(); 00596 } 00597 } 00598 00599 viennacl::linalg::av(*this, 00600 v1, SCALARTYPE(1.0), 1, false, false); 00601 00602 return *this; 00603 } 00604 00606 self_type & operator = (unit_vector<SCALARTYPE> const & v) 00607 { 00608 assert( ( (v.size() == size()) || (size() == 0) ) 00609 && bool("Incompatible vector sizes!")); 00610 00611 if (size() == 0) 00612 { 00613 size_ = v.size(); 00614 if (size_ > 0) 00615 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00616 } 00617 00618 if (size_ > 0) 00619 { 00620 clear(); 00621 this->operator()(v.index()) = SCALARTYPE(1); 00622 } 00623 00624 return *this; 00625 } 00626 00628 self_type & operator = (zero_vector<SCALARTYPE> const & v) 00629 { 00630 assert( ( (v.size() == size()) || (size() == 0) ) 00631 && bool("Incompatible vector sizes!")); 00632 00633 if (size() == 0) 00634 { 00635 size_ = v.size(); 00636 if (size_ > 0) 00637 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00638 } 00639 00640 if (size_ > 0) 00641 clear(); 00642 00643 return *this; 00644 } 00645 00647 self_type & operator = (scalar_vector<SCALARTYPE> const & v) 00648 { 00649 assert( ( (v.size() == size()) || (size() == 0) ) 00650 && bool("Incompatible vector sizes!")); 00651 00652 if (size() == 0) 00653 { 00654 size_ = v.size(); 00655 if (size_ > 0) 00656 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*internal_size()); 00657 } 00658 00659 if (size_ > 0) 00660 viennacl::linalg::vector_assign(*this, v[0]); 00661 00662 return *this; 00663 } 00664 00665 00666 00668 00669 //Note: The following operator overloads are defined in matrix_operations.hpp, compressed_matrix_operations.hpp and coordinate_matrix_operations.hpp 00670 //This is certainly not the nicest approach and will most likely by changed in the future, but it works :-) 00671 00672 //matrix<> 00677 template <typename F> 00678 self_type & operator=(const viennacl::vector_expression< const matrix_base<SCALARTYPE, F>, const vector_base<SCALARTYPE>, viennacl::op_prod> & proxy) 00679 { 00680 assert(viennacl::traits::size1(proxy.lhs()) == size() && bool("Size check failed for v1 = A * v2: size1(A) != size(v1)")); 00681 00682 // check for the special case x = A * x 00683 if (viennacl::traits::handle(proxy.rhs()) == viennacl::traits::handle(*this)) 00684 { 00685 viennacl::vector<SCALARTYPE> result(viennacl::traits::size1(proxy.lhs())); 00686 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result); 00687 *this = result; 00688 } 00689 else 00690 { 00691 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), *this); 00692 } 00693 return *this; 00694 } 00695 00696 00697 //transposed_matrix_proxy: 00702 template <typename F> 00703 self_type & operator=(const vector_expression< const matrix_expression< const matrix_base<SCALARTYPE, F>, const matrix_base<SCALARTYPE, F>, op_trans >, 00704 const vector_base<SCALARTYPE>, 00705 op_prod> & proxy) 00706 { 00707 assert(viennacl::traits::size1(proxy.lhs()) == size() && bool("Size check failed in v1 = trans(A) * v2: size2(A) != size(v1)")); 00708 00709 // check for the special case x = trans(A) * x 00710 if (viennacl::traits::handle(proxy.rhs()) == viennacl::traits::handle(*this)) 00711 { 00712 viennacl::vector<SCALARTYPE> result(viennacl::traits::size1(proxy.lhs())); 00713 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), result); 00714 *this = result; 00715 } 00716 else 00717 { 00718 viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), *this); 00719 } 00720 return *this; 00721 } 00722 00724 00725 00726 //read-write access to an element of the vector 00729 entry_proxy<SCALARTYPE> operator()(size_type index) 00730 { 00731 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00732 assert( index < size() && bool("Index out of bounds!") ); 00733 00734 return entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00735 } 00736 00739 entry_proxy<SCALARTYPE> operator[](size_type index) 00740 { 00741 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00742 assert( index < size() && bool("Index out of bounds!") ); 00743 00744 return entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00745 } 00746 00747 00750 const_entry_proxy<SCALARTYPE> operator()(size_type index) const 00751 { 00752 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00753 assert( index < size() && bool("Index out of bounds!") ); 00754 00755 return const_entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00756 } 00757 00760 const_entry_proxy<SCALARTYPE> operator[](size_type index) const 00761 { 00762 assert( (size() > 0) && bool("Cannot apply operator() to vector of size zero!")); 00763 assert( index < size() && bool("Index out of bounds!") ); 00764 00765 return const_entry_proxy<SCALARTYPE>(start_ + stride_ * index, elements_); 00766 } 00767 00768 // 00769 // Operator overloads with implicit conversion (thus cannot be made global without introducing additional headache) 00770 // 00771 00772 self_type & operator += (const self_type & vec) 00773 { 00774 assert(vec.size() == size() && bool("Incompatible vector sizes!")); 00775 00776 if (size() > 0) 00777 viennacl::linalg::avbv(*this, 00778 *this, SCALARTYPE(1.0), 1, false, false, 00779 vec, SCALARTYPE(1.0), 1, false, false); 00780 return *this; 00781 } 00782 00783 self_type & operator -= (const self_type & vec) 00784 { 00785 assert(vec.size() == size() && bool("Incompatible vector sizes!")); 00786 00787 if (size() > 0) 00788 viennacl::linalg::avbv(*this, 00789 *this, SCALARTYPE(1.0), 1, false, false, 00790 vec, SCALARTYPE(-1.0), 1, false, false); 00791 return *this; 00792 } 00793 00796 self_type & operator *= (SCALARTYPE val) 00797 { 00798 if (size() > 0) 00799 viennacl::linalg::av(*this, 00800 *this, val, 1, false, false); 00801 return *this; 00802 } 00803 00806 self_type & operator /= (SCALARTYPE val) 00807 { 00808 if (size() > 0) 00809 viennacl::linalg::av(*this, 00810 *this, val, 1, true, false); 00811 return *this; 00812 } 00813 00814 00817 vector_expression< const self_type, const SCALARTYPE, op_prod> 00818 operator * (SCALARTYPE value) const 00819 { 00820 return vector_expression< const self_type, const SCALARTYPE, op_prod>(*this, value); 00821 } 00822 00823 00826 vector_expression< const self_type, const SCALARTYPE, op_prod> 00827 operator / (SCALARTYPE value) const 00828 { 00829 return vector_expression< const self_type, const SCALARTYPE, op_prod>(*this, SCALARTYPE(1.0) / value); 00830 } 00831 00832 00834 vector_expression<const self_type, const SCALARTYPE, op_prod> operator-() const 00835 { 00836 return vector_expression<const self_type, const SCALARTYPE, op_prod>(*this, SCALARTYPE(-1.0)); 00837 } 00838 00839 // 00841 // 00842 00844 iterator begin() 00845 { 00846 return iterator(*this, 0, start_, stride_); 00847 } 00848 00850 iterator end() 00851 { 00852 return iterator(*this, size(), start_, stride_); 00853 } 00854 00856 const_iterator begin() const 00857 { 00858 return const_iterator(*this, 0, start_, stride_); 00859 } 00860 00862 const_iterator end() const 00863 { 00864 return const_iterator(*this, size(), start_, stride_); 00865 } 00866 00869 self_type & swap(self_type & other) 00870 { 00871 viennacl::linalg::vector_swap(*this, other); 00872 return *this; 00873 }; 00874 00875 00878 size_type size() const { return size_; } 00879 00882 size_type internal_size() const { return viennacl::tools::roundUpToNextMultiple<size_type>(size_, 1); } 00883 00886 size_type start() const { return start_; } 00887 00890 size_type stride() const { return stride_; } 00891 00892 00894 bool empty() const { return size_ == 0; } 00895 00897 const handle_type & handle() const { return elements_; } 00898 00900 handle_type & handle() { return elements_; } 00901 00904 void clear() 00905 { 00906 viennacl::linalg::vector_assign(*this, cpu_value_type(0.0)); 00907 } 00908 00909 viennacl::memory_types memory_domain() const 00910 { 00911 return elements_.get_active_handle_id(); 00912 } 00913 00914 protected: 00915 00916 void set_handle(viennacl::backend::mem_handle const & h) 00917 { 00918 elements_ = h; 00919 } 00920 00923 self_type & fast_swap(self_type & other) 00924 { 00925 assert(this->size_ == other.size_ && bool("Vector size mismatch")); 00926 this->elements_.swap(other.elements_); 00927 return *this; 00928 } 00929 00931 void pad() 00932 { 00933 if (internal_size() != size()) 00934 { 00935 std::vector<SCALARTYPE> pad(internal_size() - size()); 00936 viennacl::backend::memory_write(elements_, 0, sizeof(SCALARTYPE) * pad.size(), &(pad[0])); 00937 } 00938 } 00939 00940 void switch_memory_domain(viennacl::memory_types new_domain) 00941 { 00942 viennacl::backend::switch_memory_domain<SCALARTYPE>(elements_, new_domain); 00943 } 00944 00945 //TODO: Think about implementing the following public member functions 00946 //void insert_element(unsigned int i, SCALARTYPE val){} 00947 //void erase_element(unsigned int i){} 00948 00949 //enlarge or reduce allocated memory and set unused memory to zero 00955 void resize(size_type new_size, bool preserve = true) 00956 { 00957 assert(new_size > 0 && bool("Positive size required when resizing vector!")); 00958 00959 if (new_size != size_) 00960 { 00961 std::size_t new_internal_size = viennacl::tools::roundUpToNextMultiple<std::size_t>(new_size, 1); 00962 00963 std::vector<SCALARTYPE> temp(size_); 00964 if (preserve && size_ > 0) 00965 fast_copy(*this, temp); 00966 temp.resize(new_size); //drop all entries above new_size 00967 temp.resize(new_internal_size); //enlarge to fit new internal size 00968 00969 if (new_internal_size != internal_size()) 00970 { 00971 viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*new_internal_size); 00972 } 00973 00974 fast_copy(temp, *this); 00975 size_ = new_size; 00976 } 00977 00978 } 00979 00980 00981 private: 00982 size_type size_; 00983 size_type start_; 00984 difference_type stride_; 00985 handle_type elements_; 00986 }; //vector_base 00987 00988 00989 00990 // forward definition in forwards.h! 00999 template<class SCALARTYPE, unsigned int ALIGNMENT> 01000 class vector : public vector_base<SCALARTYPE> 01001 { 01002 typedef vector<SCALARTYPE, ALIGNMENT> self_type; 01003 typedef vector_base<SCALARTYPE> base_type; 01004 01005 public: 01006 typedef typename base_type::size_type size_type; 01007 01010 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 */ } 01011 01016 explicit vector(size_type vec_size) : base_type(vec_size) {} 01017 01018 #ifdef VIENNACL_WITH_OPENCL 01019 01027 explicit vector(cl_mem existing_mem, size_type vec_size) : base_type(vec_size) 01028 { 01029 viennacl::backend::mem_handle h; 01030 h.switch_active_handle_id(viennacl::OPENCL_MEMORY); 01031 h.opencl_handle() = existing_mem; 01032 h.opencl_handle().inc(); //prevents that the user-provided memory is deleted once the vector object is destroyed. 01033 h.raw_size(sizeof(SCALARTYPE) * vec_size); 01034 01035 base_type::set_handle(h); 01036 } 01037 #endif 01038 01039 template <typename LHS, typename RHS, typename OP> 01040 vector(vector_expression<const LHS, const RHS, OP> const & proxy) : base_type(proxy.size(), viennacl::traits::active_handle_id(proxy)) 01041 { 01042 self_type::operator=(proxy); 01043 } 01044 01045 vector(const base_type & v) : base_type(v.size(), v.handle().get_active_handle_id()) 01046 { 01047 if (v.size() > 0) 01048 base_type::operator=(v); 01049 } 01050 01051 vector(const self_type & v) : base_type(v.size(), v.handle().get_active_handle_id()) 01052 { 01053 if (v.size() > 0) 01054 base_type::operator=(v); 01055 } 01056 01058 vector(unit_vector<SCALARTYPE> const & v) : base_type(v.size()) 01059 { 01060 if (v.size() > 0) 01061 this->operator()(v.index()) = 1; 01062 } 01063 01065 vector(zero_vector<SCALARTYPE> const & v) : base_type(v.size()) 01066 { 01067 if (v.size() > 0) 01068 viennacl::linalg::vector_assign(*this, SCALARTYPE(0.0)); 01069 } 01070 01072 vector(scalar_vector<SCALARTYPE> const & v) : base_type(v.size()) 01073 { 01074 if (v.size() > 0) 01075 viennacl::linalg::vector_assign(*this, v[0]); 01076 } 01077 01078 using base_type::operator=; 01079 01081 01082 // Note: Dense operations are already handled in vector_base 01083 01084 // 01085 // Sparse matrices 01086 // 01087 template <typename SparseMatrixType> 01088 typename viennacl::enable_if< viennacl::is_any_sparse_matrix<SparseMatrixType>::value, 01089 self_type & >::type 01090 operator=(const viennacl::vector_expression< const SparseMatrixType, 01091 const base_type, 01092 viennacl::op_prod> & proxy) ; 01093 01094 // 01095 // circulant_matrix<> 01096 // 01101 template <unsigned int MAT_ALIGNMENT> 01102 self_type & operator=(const vector_expression< const circulant_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01103 const base_type, 01104 op_prod> & proxy); 01105 01110 template <unsigned int MAT_ALIGNMENT> 01111 self_type & operator+=(const vector_expression< const circulant_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01112 const base_type, 01113 op_prod> & proxy); 01114 01119 template <unsigned int MAT_ALIGNMENT> 01120 self_type & operator-=(const vector_expression< const circulant_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01121 const base_type, 01122 op_prod> & proxy); 01123 01128 template <unsigned int MAT_ALIGNMENT> 01129 self_type operator+(const vector_expression< const circulant_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01130 const base_type, 01131 op_prod> & proxy); 01132 01137 template <unsigned int MAT_ALIGNMENT> 01138 self_type operator-(const vector_expression< const circulant_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01139 const base_type, 01140 op_prod> & proxy); 01141 01142 01143 // 01144 // hankel_matrix<> 01145 // 01150 template <unsigned int MAT_ALIGNMENT> 01151 self_type & operator=(const vector_expression< const hankel_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01152 const base_type, 01153 op_prod> & proxy); 01154 01159 template <unsigned int MAT_ALIGNMENT> 01160 self_type & operator+=(const vector_expression< const hankel_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01161 const base_type, 01162 op_prod> & proxy); 01163 01168 template <unsigned int MAT_ALIGNMENT> 01169 self_type & operator-=(const vector_expression< const hankel_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01170 const base_type, 01171 op_prod> & proxy); 01172 01177 template <unsigned int MAT_ALIGNMENT> 01178 self_type operator+(const vector_expression< const hankel_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01179 const base_type, 01180 op_prod> & proxy); 01181 01186 template <unsigned int MAT_ALIGNMENT> 01187 self_type operator-(const vector_expression< const hankel_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01188 const base_type, 01189 op_prod> & proxy); 01190 01191 // 01192 // toeplitz_matrix<> 01193 // 01198 template <unsigned int MAT_ALIGNMENT> 01199 self_type & operator=(const vector_expression< const toeplitz_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01200 const base_type, 01201 op_prod> & proxy); 01202 01207 template <unsigned int MAT_ALIGNMENT> 01208 self_type & operator+=(const vector_expression< const toeplitz_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01209 const base_type, 01210 op_prod> & proxy); 01211 01216 template <unsigned int MAT_ALIGNMENT> 01217 self_type & operator-=(const vector_expression< const toeplitz_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01218 const base_type, 01219 op_prod> & proxy); 01220 01225 template <unsigned int MAT_ALIGNMENT> 01226 self_type operator+(const vector_expression< const toeplitz_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01227 const base_type, 01228 op_prod> & proxy); 01229 01234 template <unsigned int MAT_ALIGNMENT> 01235 self_type operator-(const vector_expression< const toeplitz_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01236 const base_type, 01237 op_prod> & proxy); 01238 01239 01240 // 01241 // vandermonde_matrix<> 01242 // 01247 template <unsigned int MAT_ALIGNMENT> 01248 self_type & operator=(const vector_expression< const vandermonde_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01249 const base_type, 01250 op_prod> & proxy); 01251 01256 template <unsigned int MAT_ALIGNMENT> 01257 self_type & operator+=(const vector_expression< const vandermonde_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01258 const base_type, 01259 op_prod> & proxy); 01260 01265 template <unsigned int MAT_ALIGNMENT> 01266 self_type & operator-=(const vector_expression< const vandermonde_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01267 const base_type, 01268 op_prod> & proxy); 01269 01274 template <unsigned int MAT_ALIGNMENT> 01275 self_type operator+(const vector_expression< const vandermonde_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01276 const base_type, 01277 op_prod> & proxy); 01278 01283 template <unsigned int MAT_ALIGNMENT> 01284 self_type operator-(const vector_expression< const vandermonde_matrix<SCALARTYPE, MAT_ALIGNMENT>, 01285 const base_type, 01286 op_prod> & proxy); 01287 01289 01291 vector_expression<const vector_base<SCALARTYPE>, const SCALARTYPE, op_prod> operator-() const 01292 { 01293 return vector_expression<const vector_base<SCALARTYPE>, const SCALARTYPE, op_prod>(*this, SCALARTYPE(-1.0)); 01294 } 01295 01296 01297 //enlarge or reduce allocated memory and set unused memory to zero 01303 void resize(size_type new_size, bool preserve = true) 01304 { 01305 base_type::resize(new_size, preserve); 01306 } 01307 01308 01311 self_type & fast_swap(self_type & other) 01312 { 01313 base_type::fast_swap(other); 01314 return *this; 01315 } 01316 01317 void switch_memory_domain(viennacl::memory_types new_domain) 01318 { 01319 base_type::switch_memory_domain(new_domain); 01320 } 01321 01322 }; //vector 01323 01324 01325 // 01327 // 01328 01329 01341 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01342 void fast_copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01343 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01344 CPU_ITERATOR cpu_begin ) 01345 { 01346 if (gpu_begin != gpu_end) 01347 { 01348 if (gpu_begin.stride() == 1) 01349 { 01350 viennacl::backend::memory_read(gpu_begin.handle(), 01351 sizeof(SCALARTYPE)*gpu_begin.offset(), 01352 sizeof(SCALARTYPE)*gpu_begin.stride() * (gpu_end - gpu_begin), 01353 &(*cpu_begin)); 01354 } 01355 else 01356 { 01357 std::size_t gpu_size = (gpu_end - gpu_begin); 01358 std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * gpu_size); 01359 viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01360 01361 for (std::size_t i=0; i<gpu_size; ++i) 01362 { 01363 (&(*cpu_begin))[i] = temp_buffer[i * gpu_begin.stride()]; 01364 } 01365 } 01366 } 01367 } 01368 01374 template <typename NumericT, typename CPUVECTOR> 01375 void fast_copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01376 { 01377 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01378 } 01379 01380 01387 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01388 void copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01389 const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01390 CPU_ITERATOR cpu_begin ) 01391 { 01392 assert(gpu_end - gpu_begin >= 0 && bool("Iterators incompatible")); 01393 if (gpu_end - gpu_begin != 0) 01394 { 01395 std::vector<SCALARTYPE> temp_buffer(gpu_end - gpu_begin); 01396 fast_copy(gpu_begin, gpu_end, temp_buffer.begin()); 01397 01398 //now copy entries to cpu_vec: 01399 std::copy(temp_buffer.begin(), temp_buffer.end(), cpu_begin); 01400 } 01401 } 01402 01409 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01410 void copy(const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin, 01411 const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end, 01412 CPU_ITERATOR cpu_begin ) 01413 01414 { 01415 viennacl::copy(const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_begin), 01416 const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_end), 01417 cpu_begin); 01418 } 01419 01425 template <typename NumericT, typename CPUVECTOR> 01426 void copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec ) 01427 { 01428 viennacl::copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin()); 01429 } 01430 01431 01432 01433 #ifdef VIENNACL_WITH_EIGEN 01434 template <unsigned int ALIGNMENT> 01435 void copy(vector<float, ALIGNMENT> const & gpu_vec, 01436 Eigen::VectorXf & eigen_vec) 01437 { 01438 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0])); 01439 } 01440 01441 template <unsigned int ALIGNMENT> 01442 void copy(vector<double, ALIGNMENT> & gpu_vec, 01443 Eigen::VectorXd & eigen_vec) 01444 { 01445 viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0])); 01446 } 01447 #endif 01448 01449 01450 // 01452 // 01453 01465 template <typename CPU_ITERATOR, typename SCALARTYPE, unsigned int ALIGNMENT> 01466 void fast_copy(CPU_ITERATOR const & cpu_begin, 01467 CPU_ITERATOR const & cpu_end, 01468 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01469 { 01470 if (cpu_end - cpu_begin > 0) 01471 { 01472 if (gpu_begin.stride() == 1) 01473 { 01474 viennacl::backend::memory_write(gpu_begin.handle(), 01475 sizeof(SCALARTYPE)*gpu_begin.offset(), 01476 sizeof(SCALARTYPE)*gpu_begin.stride() * (cpu_end - cpu_begin), &(*cpu_begin)); 01477 } 01478 else //writing to slice: 01479 { 01480 std::size_t cpu_size = (cpu_end - cpu_begin); 01481 std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * cpu_size); 01482 01483 viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01484 01485 for (std::size_t i=0; i<cpu_size; ++i) 01486 temp_buffer[i * gpu_begin.stride()] = (&(*cpu_begin))[i]; 01487 01488 viennacl::backend::memory_write(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0])); 01489 } 01490 } 01491 } 01492 01493 01499 template <typename CPUVECTOR, typename NumericT> 01500 void fast_copy(const CPUVECTOR & cpu_vec, vector_base<NumericT> & gpu_vec) 01501 { 01502 viennacl::fast_copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01503 } 01504 01505 //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 01512 template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR> 01513 void copy(CPU_ITERATOR const & cpu_begin, 01514 CPU_ITERATOR const & cpu_end, 01515 vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin) 01516 { 01517 assert(cpu_end - cpu_begin > 0 && bool("Iterators incompatible")); 01518 if (cpu_begin != cpu_end) 01519 { 01520 //we require that the size of the gpu_vector is larger or equal to the cpu-size 01521 std::vector<SCALARTYPE> temp_buffer(cpu_end - cpu_begin); 01522 std::copy(cpu_begin, cpu_end, temp_buffer.begin()); 01523 viennacl::fast_copy(temp_buffer.begin(), temp_buffer.end(), gpu_begin); 01524 } 01525 } 01526 01527 // for things like copy(std_vec.begin(), std_vec.end(), vcl_vec.begin() + 1); 01528 01534 template <typename CPUVECTOR, typename T> 01535 void copy(const CPUVECTOR & cpu_vec, vector_base<T> & gpu_vec) 01536 { 01537 viennacl::copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin()); 01538 } 01539 01540 01541 #ifdef VIENNACL_WITH_EIGEN 01542 template <unsigned int ALIGNMENT> 01543 void copy(Eigen::VectorXf const & eigen_vec, 01544 vector<float, ALIGNMENT> & gpu_vec) 01545 { 01546 std::vector<float> entries(eigen_vec.size()); 01547 for (std::size_t i = 0; i<entries.size(); ++i) 01548 entries[i] = eigen_vec(i); 01549 viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin()); 01550 } 01551 01552 template <unsigned int ALIGNMENT> 01553 void copy(Eigen::VectorXd const & eigen_vec, 01554 vector<double, ALIGNMENT> & gpu_vec) 01555 { 01556 std::vector<double> entries(eigen_vec.size()); 01557 for (std::size_t i = 0; i<entries.size(); ++i) 01558 entries[i] = eigen_vec(i); 01559 viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin()); 01560 } 01561 #endif 01562 01563 01564 01565 // 01567 // 01574 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01575 void copy(const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin, 01576 const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end, 01577 vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin) 01578 { 01579 assert(gpu_src_end - gpu_src_begin >= 0); 01580 assert(gpu_src_begin.stride() == 1 && bool("ViennaCL ERROR: copy() for GPU->GPU not implemented for slices! Use operator= instead for the moment.")); 01581 01582 if (gpu_src_begin.stride() == 1 && gpu_dest_begin.stride() == 1) 01583 { 01584 if (gpu_src_begin != gpu_src_end) 01585 viennacl::backend::memory_copy(gpu_src_begin.handle(), gpu_dest_begin.handle(), 01586 sizeof(SCALARTYPE) * gpu_src_begin.offset(), 01587 sizeof(SCALARTYPE) * gpu_dest_begin.offset(), 01588 sizeof(SCALARTYPE) * (gpu_src_end.offset() - gpu_src_begin.offset())); 01589 } 01590 else 01591 { 01592 assert( false && bool("not implemented yet")); 01593 } 01594 } 01595 01602 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01603 void copy(vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin, 01604 vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end, 01605 vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin) 01606 { 01607 viennacl::copy(static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_begin), 01608 static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_end), 01609 gpu_dest_begin); 01610 } 01611 01617 template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST> 01618 void copy(vector<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_vec, 01619 vector<SCALARTYPE, ALIGNMENT_DEST> & gpu_dest_vec ) 01620 { 01621 viennacl::copy(gpu_src_vec.begin(), gpu_src_vec.end(), gpu_dest_vec.begin()); 01622 } 01623 01624 01625 01626 01627 01628 01629 //global functions for handling vectors: 01634 template <typename T> 01635 std::ostream & operator<<(std::ostream & s, vector_base<T> const & val) 01636 { 01637 std::vector<T> tmp(val.size()); 01638 viennacl::copy(val.begin(), val.end(), tmp.begin()); 01639 std::cout << "[" << val.size() << "]("; 01640 for (typename std::vector<T>::size_type i=0; i<val.size(); ++i) 01641 { 01642 if (i > 0) 01643 s << ","; 01644 s << tmp[i]; 01645 } 01646 std::cout << ")"; 01647 return s; 01648 } 01649 01650 template <typename LHS, typename RHS, typename OP> 01651 std::ostream & operator<<(std::ostream & s, vector_expression<LHS, RHS, OP> const & proxy) 01652 { 01653 typedef typename viennacl::result_of::cpu_value_type<typename LHS::value_type>::type ScalarType; 01654 viennacl::vector<ScalarType> result = proxy; 01655 s << result; 01656 return s; 01657 } 01658 01664 template <typename T> 01665 void swap(vector_base<T> & vec1, vector_base<T> & vec2) 01666 { 01667 viennacl::linalg::vector_swap(vec1, vec2); 01668 } 01669 01675 template <typename SCALARTYPE, unsigned int ALIGNMENT> 01676 vector<SCALARTYPE, ALIGNMENT> & fast_swap(vector<SCALARTYPE, ALIGNMENT> & v1, 01677 vector<SCALARTYPE, ALIGNMENT> & v2) 01678 { 01679 return v1.fast_swap(v2); 01680 } 01681 01682 01683 01684 01685 01686 // 01687 // 01689 // 01690 // 01691 01692 // 01693 // operator += 01694 // 01695 01696 01699 template <typename T> 01700 vector_base<T> & operator += (vector_base<T> & v1, const vector_base<T> & v2) 01701 { 01702 01703 assert(v1.size() == v2.size() && bool("Incompatible vector sizes!")); 01704 01705 if (v1.size() > 0) 01706 viennacl::linalg::avbv(v1, 01707 v1, T(1.0), 1, false, false, 01708 v2, T(1.0), 1, false, false); 01709 return v1; 01710 } 01711 01714 template <typename T, typename S2, typename OP> 01715 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value, 01716 vector_base<T> &>::type 01717 operator += (vector_base<T> & v1, 01718 const vector_expression< const vector_base<T>, const S2, OP> & proxy) 01719 { 01720 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01721 01722 if (v1.size() > 0) 01723 viennacl::linalg::avbv(v1, 01724 v1, T(1.0), 1, false, false, 01725 proxy.lhs(), proxy.rhs(), 1, (viennacl::is_division<OP>::value ? true : false), (viennacl::is_flip_sign_scalar<S2>::value ? true : false) ); 01726 return v1; 01727 } 01728 01729 01735 template <typename T, typename OP> 01736 typename viennacl::enable_if< (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01737 vector_base<T> &>::type 01738 operator += (vector_base<T> & v1, 01739 const vector_expression< const vector_base<T>, const vector_base<T>, OP> & proxy) 01740 { 01741 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01742 01743 if (v1.size() > 0) 01744 viennacl::linalg::avbv_v(v1, 01745 proxy.lhs(), T(1.0), 1, false, false, 01746 proxy.rhs(), T(1.0), 1, false, (viennacl::is_subtraction<OP>::value ? true : false) ); 01747 return v1; 01748 } 01749 01755 template < typename T, 01756 typename S3, typename OP3, 01757 typename OP> 01758 typename viennacl::enable_if< viennacl::is_any_scalar<S3>::value && (viennacl::is_product<OP3>::value || viennacl::is_division<OP3>::value) 01759 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01760 vector_base<T> &>::type 01761 operator += (vector_base<T> & v1, 01762 const vector_expression< const vector_base<T>, 01763 const vector_expression<const vector_base<T>, const S3, OP3>, 01764 OP> & proxy) 01765 { 01766 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01767 01768 if (v1.size() > 0) 01769 { 01770 bool flip_sign_3 = (viennacl::is_subtraction<OP>::value ? true : false); 01771 if (viennacl::is_flip_sign_scalar<S3>::value) 01772 flip_sign_3 = !flip_sign_3; 01773 viennacl::linalg::avbv_v(v1, 01774 proxy.lhs(), T(1.0), 1, false , false, 01775 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, (viennacl::is_division<OP3>::value ? true : false), flip_sign_3 ); 01776 } 01777 return v1; 01778 } 01779 01785 template <typename T, typename S2, typename OP2, 01786 typename OP> 01787 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value && (viennacl::is_product<OP2>::value || viennacl::is_division<OP2>::value) 01788 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01789 vector_base<T> &>::type 01790 operator += (vector_base<T> & v1, 01791 const vector_expression< const vector_expression<const vector_base<T>, const S2, OP2>, 01792 const vector_base<T>, 01793 OP> & proxy) 01794 { 01795 assert(proxy.size() == v1.size() && bool("Incompatible vector sizes!")); 01796 01797 if (v1.size() > 0) 01798 viennacl::linalg::avbv_v(v1, 01799 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, (viennacl::is_division<OP2>::value ? true : false), (viennacl::is_flip_sign_scalar<S2>::value ? true : false), 01800 proxy.rhs(), T(1.0), 1, false , (viennacl::is_subtraction<OP>::value ? true : false) ); 01801 return v1; 01802 } 01803 01809 template <typename T, 01810 typename S2, typename OP2, 01811 typename S3, typename OP3, 01812 typename OP> 01813 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value && (viennacl::is_product<OP2>::value || viennacl::is_division<OP2>::value) 01814 && viennacl::is_any_scalar<S3>::value && (viennacl::is_product<OP3>::value || viennacl::is_division<OP3>::value) 01815 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01816 vector_base<T> &>::type 01817 operator += (vector_base<T> & v1, 01818 const vector_expression< const vector_expression<const vector_base<T>, const S2, OP2>, 01819 const vector_expression<const vector_base<T>, const S3, OP3>, 01820 OP> & proxy) 01821 { 01822 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01823 01824 if (v1.size() > 0) 01825 { 01826 bool flip_sign_3 = (viennacl::is_subtraction<OP>::value ? true : false); 01827 if (viennacl::is_flip_sign_scalar<S3>::value) 01828 flip_sign_3 = !flip_sign_3; 01829 viennacl::linalg::avbv_v(v1, 01830 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, (viennacl::is_division<OP2>::value ? true : false), (viennacl::is_flip_sign_scalar<S2>::value ? true : false), 01831 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, (viennacl::is_division<OP3>::value ? true : false), flip_sign_3 ); 01832 } 01833 return v1; 01834 } 01835 01836 01837 // 01838 // operator -= 01839 // 01840 01842 template <typename T> 01843 vector_base<T> & operator -= (vector_base<T> & v1, const vector_base<T> & vec) 01844 { 01845 assert(vec.size() == v1.size() && bool("Incompatible vector sizes!")); 01846 01847 if (v1.size() > 0) 01848 viennacl::linalg::avbv(v1, 01849 v1, T( 1.0), 1, false, false, 01850 vec, T(-1.0), 1, false, false); 01851 return v1; 01852 } 01853 01854 01857 template <typename T, typename S2, typename OP> 01858 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value, 01859 vector_base<T> &>::type 01860 operator -= (vector_base<T> & v1, 01861 const vector_expression< const vector_base<T>, const S2, OP> & proxy) 01862 { 01863 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01864 01865 if (v1.size() > 0) 01866 viennacl::linalg::avbv(v1, 01867 v1, T(1.0), 1, false, false, 01868 proxy.lhs(), proxy.rhs(), 1, (viennacl::is_division<OP>::value ? true : false), (viennacl::is_flip_sign_scalar<S2>::value ? false : true)); 01869 return v1; 01870 } 01871 01877 template <typename T, typename OP> 01878 typename viennacl::enable_if< (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01879 vector_base<T> &>::type 01880 operator -= (vector_base<T> & v1, 01881 const vector_expression< const vector_base<T>, const vector_base<T>, OP> & proxy) 01882 { 01883 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01884 01885 if (v1.size() > 0) 01886 viennacl::linalg::avbv_v(v1, 01887 proxy.lhs(), T(1.0), 1, false, true, 01888 proxy.rhs(), T(1.0), 1, false, (viennacl::is_subtraction<OP>::value ? false : true) ); 01889 return v1; 01890 } 01891 01897 template <typename T, 01898 typename S3, typename OP3, 01899 typename OP> 01900 typename viennacl::enable_if< viennacl::is_any_scalar<S3>::value && (viennacl::is_product<OP3>::value || viennacl::is_division<OP3>::value) 01901 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01902 vector_base<T> &>::type 01903 operator -= (vector_base<T> & v1, 01904 const vector_expression< const vector_base<T>, 01905 const vector_expression<const vector_base<T>, const S3, OP3>, 01906 OP> & proxy) 01907 { 01908 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01909 01910 if (v1.size() > 0) 01911 { 01912 bool flip_sign_3 = (viennacl::is_subtraction<OP>::value ? false : true); 01913 if (viennacl::is_flip_sign_scalar<S3>::value) 01914 flip_sign_3 = !flip_sign_3; 01915 viennacl::linalg::avbv_v(v1, 01916 proxy.lhs(), T(1.0), 1, false , true, 01917 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, (viennacl::is_division<OP3>::value ? true : false), flip_sign_3); 01918 } 01919 return v1; 01920 } 01921 01927 template <typename T, typename S2, typename OP2, 01928 typename OP> 01929 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value && (viennacl::is_product<OP2>::value || viennacl::is_division<OP2>::value) 01930 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01931 vector_base<T> &>::type 01932 operator -= (vector_base<T> & v1, 01933 const vector_expression< const vector_expression<const vector_base<T>, const S2, OP2>, 01934 const vector_base<T>, 01935 OP> & proxy) 01936 { 01937 assert(proxy.size() == v1.size() && bool("Incompatible vector sizes!")); 01938 01939 if (v1.size() > 0) 01940 viennacl::linalg::avbv_v(v1, 01941 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, (viennacl::is_division<OP2>::value ? true : false), (viennacl::is_flip_sign_scalar<S2>::value ? false : true), 01942 proxy.rhs(), T(1.0), 1, false , (viennacl::is_subtraction<OP>::value ? false : true) ); 01943 return v1; 01944 } 01945 01951 template <typename T, 01952 typename S2, typename OP2, 01953 typename S3, typename OP3, 01954 typename OP> 01955 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value && (viennacl::is_product<OP2>::value || viennacl::is_division<OP2>::value) 01956 && viennacl::is_any_scalar<S3>::value && (viennacl::is_product<OP3>::value || viennacl::is_division<OP3>::value) 01957 && (viennacl::is_addition<OP>::value || viennacl::is_subtraction<OP>::value), 01958 vector_base<T> &>::type 01959 operator -= (vector_base<T> & v1, 01960 const vector_expression< const vector_expression<const vector_base<T>, const S2, OP2>, 01961 const vector_expression<const vector_base<T>, const S3, OP3>, 01962 OP> & proxy) 01963 { 01964 assert(proxy.lhs().size() == v1.size() && bool("Incompatible vector sizes!")); 01965 01966 if (v1.size() > 0) 01967 { 01968 bool flip_sign_3 = (viennacl::is_subtraction<OP>::value ? false : true); 01969 if (viennacl::is_flip_sign_scalar<S3>::value) 01970 flip_sign_3 = !flip_sign_3; 01971 viennacl::linalg::avbv_v(v1, 01972 proxy.lhs().lhs(), proxy.lhs().rhs(), 1, (viennacl::is_division<OP2>::value ? true : false), (viennacl::is_flip_sign_scalar<S2>::value ? false : true), 01973 proxy.rhs().lhs(), proxy.rhs().rhs(), 1, (viennacl::is_division<OP3>::value ? true : false), flip_sign_3); 01974 } 01975 return v1; 01976 } 01977 01978 01979 // 01980 // operator *= 01981 // 01982 01985 template <typename T, typename S1> 01986 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 01987 vector_base<T> & 01988 >::type 01989 operator *= (vector_base<T> & v1, S1 const & gpu_val) 01990 { 01991 if (v1.size() > 0) 01992 viennacl::linalg::av(v1, 01993 v1, gpu_val, 1, false, (viennacl::is_flip_sign_scalar<S1>::value ? true : false)); 01994 return v1; 01995 } 01996 01997 01998 // 01999 // operator /= 02000 // 02001 02002 02005 template <typename T, typename S1> 02006 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02007 vector_base<T> & 02008 >::type 02009 operator /= (vector_base<T> & v1, S1 const & gpu_val) 02010 { 02011 if (v1.size() > 0) 02012 viennacl::linalg::av(v1, 02013 v1, gpu_val, 1, true, (viennacl::is_flip_sign_scalar<S1>::value ? true : false)); 02014 return v1; 02015 } 02016 02017 02018 // 02019 // operator + 02020 // 02021 02022 //addition and subtraction of two vector_expressions: 02028 template <typename LHS1, typename RHS1, typename OP1, 02029 typename LHS2, typename RHS2, typename OP2> 02030 typename vector_expression< LHS1, RHS1, OP1>::VectorType 02031 operator + (vector_expression< LHS1, RHS1, OP1> const & proxy1, 02032 vector_expression< LHS2, RHS2, OP2> const & proxy2) 02033 { 02034 assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!")); 02035 typename vector_expression< LHS1, RHS1, OP1>::VectorType result = proxy1; 02036 result += proxy2; 02037 return result; 02038 } 02039 02040 02046 template <typename LHS, typename RHS, typename OP, typename T> 02047 viennacl::vector<T> 02048 operator + (vector_expression<LHS, RHS, OP> const & proxy, 02049 vector_base<T> const & vec) 02050 { 02051 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 02052 viennacl::vector<T> result = proxy; 02053 result += vec; 02054 return result; 02055 } 02056 02062 template <typename T, typename LHS, typename RHS, typename OP> 02063 viennacl::vector<T> 02064 operator + (vector_base<T> const & vec, 02065 vector_expression<LHS, RHS, OP> const & proxy) 02066 { 02067 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 02068 viennacl::vector<T> result = vec; 02069 result += proxy; 02070 return result; 02071 } 02072 02073 02079 template <typename T, typename S1, typename OP1> 02080 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02081 vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02082 const vector_base<T>, 02083 op_add> 02084 >::type 02085 operator + (vector_expression<const vector_base<T>, const S1, OP1> const & proxy, 02086 vector_base<T> const & vec) 02087 { 02088 return vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02089 const vector_base<T>, 02090 op_add>(proxy, vec); 02091 } 02092 02098 template <typename T, 02099 typename S1, typename OP1, 02100 typename S2, typename OP2> 02101 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value && viennacl::is_any_scalar<S2>::value, 02102 vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02103 const vector_expression<const vector_base<T>, const S2, OP2>, 02104 op_add> 02105 >::type 02106 operator + (vector_expression<const vector_base<T>, const S1, OP1> const & lhs, 02107 vector_expression<const vector_base<T>, const S2, OP2> const & rhs) 02108 { 02109 return vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02110 const vector_expression<const vector_base<T>, const S2, OP2>, 02111 op_add>(lhs, rhs); 02112 } 02113 02114 02117 template <typename T> 02118 vector_expression< const vector_base<T>, const vector_base<T>, op_add> 02119 operator+(const vector_base<T> & v1, const vector_base<T> & v2) 02120 { 02121 return vector_expression< const vector_base<T>, const vector_base<T>, op_add>(v1, v2); 02122 } 02123 02126 template <typename T, typename S2, typename OP2> 02127 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value, 02128 vector_expression< const vector_base<T>, 02129 const vector_expression< const vector_base<T>, const S2, OP2>, 02130 op_add> 02131 >::type 02132 operator+(const vector_base<T> & v1, 02133 const vector_expression< const vector_base<T>, 02134 const S2, 02135 OP2> & proxy) 02136 { 02137 return vector_expression< const vector_base<T>, 02138 const vector_expression< const vector_base<T>, const S2, OP2>, 02139 op_add>(v1, proxy); 02140 } 02141 02142 02143 02144 02145 // 02146 // operator - 02147 // 02148 02154 template <typename LHS1, typename RHS1, typename OP1, 02155 typename LHS2, typename RHS2, typename OP2> 02156 typename vector_expression< LHS1, RHS1, OP1>::VectorType 02157 operator - (vector_expression< LHS1, RHS1, OP1> const & proxy1, 02158 vector_expression< LHS2, RHS2, OP2> const & proxy2) 02159 { 02160 assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!")); 02161 typename vector_expression< LHS1, RHS1, OP1>::VectorType result = proxy1; 02162 result -= proxy2; 02163 return result; 02164 } 02165 02166 02172 template <typename LHS, typename RHS, typename OP, typename T> 02173 viennacl::vector<T> 02174 operator - (vector_expression< LHS, RHS, OP> const & proxy, 02175 vector_base<T> const & vec) 02176 { 02177 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 02178 viennacl::vector<T> result = proxy; 02179 result -= vec; 02180 return result; 02181 } 02182 02188 template <typename T, typename LHS, typename RHS, typename OP> 02189 viennacl::vector<T> 02190 operator - (vector_base<T> const & vec, 02191 vector_expression< LHS, RHS, OP> const & proxy) 02192 { 02193 assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!")); 02194 viennacl::vector<T> result = vec; 02195 result -= proxy; 02196 return result; 02197 } 02198 02204 template <typename T, typename S1, typename OP1> 02205 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02206 vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02207 const vector_base<T>, 02208 op_sub> 02209 >::type 02210 operator - (vector_expression<const vector_base<T>, const S1, OP1> const & proxy, 02211 vector_base<T> const & vec) 02212 { 02213 return vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02214 const vector_base<T>, 02215 op_sub>(proxy, vec); 02216 } 02217 02223 template <typename T, 02224 typename S1, typename OP1, 02225 typename S2, typename OP2> 02226 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value 02227 && viennacl::is_any_scalar<S2>::value, 02228 vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02229 const vector_expression<const vector_base<T>, const S2, OP2>, 02230 op_sub> 02231 >::type 02232 operator - (vector_expression<const vector_base<T>, const S1, OP1> const & lhs, 02233 vector_expression<const vector_base<T>, const S2, OP2> const & rhs) 02234 { 02235 return vector_expression<const vector_expression<const vector_base<T>, const S1, OP1>, 02236 const vector_expression<const vector_base<T>, const S2, OP2>, 02237 op_sub>(lhs, rhs); 02238 } 02239 02242 template <typename T> 02243 vector_expression< const vector_base<T>, const vector_base<T>, op_sub> 02244 operator-(const vector_base<T> & v1, const vector_base<T> & v2) 02245 { 02246 return vector_expression< const vector_base<T>, const vector_base<T>, op_sub>(v1, v2); 02247 } 02248 02249 02252 template <typename T, typename S2, typename OP2> 02253 typename viennacl::enable_if< viennacl::is_any_scalar<S2>::value, 02254 vector_expression< const vector_base<T>, 02255 const vector_expression< const vector_base<T>, const S2, OP2>, 02256 op_sub> 02257 >::type 02258 operator-(const vector_base<T> & v1, 02259 const vector_expression< const vector_base<T>, 02260 const S2, 02261 OP2> & proxy) 02262 { 02263 return vector_expression< const vector_base<T>, 02264 const vector_expression< const vector_base<T>, const S2, OP2>, 02265 op_sub>(v1, proxy); 02266 } 02267 02268 02269 // 02270 // operator * 02271 // 02272 02273 02279 template <typename S1, typename T> 02280 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02281 vector_expression< const vector_base<T>, const S1, op_prod> >::type 02282 operator * (S1 const & value, vector_base<T> const & vec) 02283 { 02284 return vector_expression< const vector_base<T>, const S1, op_prod>(vec, value); 02285 } 02286 02287 02293 template <typename LHS, typename RHS, typename OP, typename S1> 02294 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02295 viennacl::vector<typename viennacl::result_of::cpu_value_type<RHS>::type> >::type 02296 operator * (vector_expression< LHS, RHS, OP> const & proxy, 02297 S1 const & val) 02298 { 02299 viennacl::vector<typename viennacl::result_of::cpu_value_type<RHS>::type> result = proxy; 02300 result *= val; 02301 return result; 02302 } 02303 02304 02310 template <typename S1, typename LHS, typename RHS, typename OP> 02311 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02312 viennacl::vector<typename viennacl::result_of::cpu_value_type<RHS>::type> >::type 02313 operator * (S1 const & val, 02314 vector_expression< LHS, RHS, OP> const & proxy) 02315 { 02316 viennacl::vector<typename viennacl::result_of::cpu_value_type<RHS>::type> result = proxy; 02317 result *= val; 02318 return result; 02319 } 02320 02323 template <typename T, typename S1> 02324 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02325 vector_expression< const vector_base<T>, const S1, op_prod> >::type 02326 operator * (vector_base<T> const & v1, S1 const & s1) 02327 { 02328 return vector_expression< const vector_base<T>, const S1, op_prod>(v1, s1); 02329 } 02330 02331 // 02332 // operator / 02333 // 02334 02340 template <typename S1, typename LHS, typename RHS, typename OP> 02341 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02342 viennacl::vector<typename viennacl::result_of::cpu_value_type<RHS>::type> >::type 02343 operator / (vector_expression< LHS, RHS, OP> const & proxy, 02344 S1 const & val) 02345 { 02346 viennacl::vector<typename viennacl::result_of::cpu_value_type<RHS>::type> result = proxy; 02347 result /= val; 02348 return result; 02349 } 02350 02351 02354 template <typename T, typename S1> 02355 typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value, 02356 vector_expression< const vector_base<T>, const S1, op_div> >::type 02357 operator / (vector_base<T> const & v1, S1 const & s1) 02358 { 02359 return vector_expression< const vector_base<T>, const S1, op_div>(v1, s1); 02360 } 02361 02362 } 02363 02364 #endif
1.7.6.1