ViennaCL - The Vienna Computing Library  1.5.1
viennacl/vector.hpp
Go to the documentation of this file.
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 
00753       template <typename LHS, typename RHS, typename OP>
00754       self_type & operator += (const vector_expression<const LHS, const RHS, OP> & proxy)
00755       {
00756         assert( (viennacl::traits::size(proxy) == size()) && bool("Incompatible vector sizes!"));
00757         assert( (size() > 0) && bool("Vector not yet initialized!") );
00758 
00759         linalg::detail::op_executor<self_type, op_inplace_add, vector_expression<const LHS, const RHS, OP> >::apply(*this, proxy);
00760 
00761         return *this;
00762       }
00763 
00764       template <typename LHS, typename RHS, typename OP>
00765       self_type & operator -= (const vector_expression<const LHS, const RHS, OP> & proxy)
00766       {
00767         assert( (viennacl::traits::size(proxy) == size()) && bool("Incompatible vector sizes!"));
00768         assert( (size() > 0) && bool("Vector not yet initialized!") );
00769 
00770         linalg::detail::op_executor<self_type, op_inplace_sub, vector_expression<const LHS, const RHS, OP> >::apply(*this, proxy);
00771 
00772         return *this;
00773       }
00774 
00777       self_type & operator *= (SCALARTYPE val)
00778       {
00779         if (size() > 0)
00780           viennacl::linalg::av(*this,
00781                                 *this, val, 1, false, false);
00782         return *this;
00783       }
00784 
00787       self_type & operator /= (SCALARTYPE val)
00788       {
00789         if (size() > 0)
00790           viennacl::linalg::av(*this,
00791                                *this, val, 1, true, false);
00792         return *this;
00793       }
00794 
00795 
00798       vector_expression< const self_type, const SCALARTYPE, op_mult>
00799       operator * (SCALARTYPE value) const
00800       {
00801         return vector_expression< const self_type, const SCALARTYPE, op_mult>(*this, value);
00802       }
00803 
00804 
00807       vector_expression< const self_type, const SCALARTYPE, op_div>
00808       operator / (SCALARTYPE value) const
00809       {
00810         return vector_expression< const self_type, const SCALARTYPE, op_div>(*this, value);
00811       }
00812 
00813 
00815       vector_expression<const self_type, const SCALARTYPE, op_mult> operator-() const
00816       {
00817         return vector_expression<const self_type, const SCALARTYPE, op_mult>(*this, SCALARTYPE(-1.0));
00818       }
00819 
00820       //
00822       //
00823 
00825       iterator begin()
00826       {
00827         return iterator(*this, 0, start_, stride_);
00828       }
00829 
00831       iterator end()
00832       {
00833         return iterator(*this, size(), start_, stride_);
00834       }
00835 
00837       const_iterator begin() const
00838       {
00839         return const_iterator(*this, 0, start_, stride_);
00840       }
00841 
00843       const_iterator end() const
00844       {
00845         return const_iterator(*this, size(), start_, stride_);
00846       }
00847 
00850       self_type & swap(self_type & other)
00851       {
00852         viennacl::linalg::vector_swap(*this, other);
00853         return *this;
00854       };
00855 
00856 
00859       size_type size() const { return size_; }
00860 
00863       size_type internal_size() const { return internal_size_; }
00864 
00867       size_type start() const { return start_; }
00868 
00871       size_type stride() const { return stride_; }
00872 
00873 
00875       bool empty() const { return size_ == 0; }
00876 
00878       const handle_type & handle() const { return elements_; }
00879 
00881       handle_type & handle() { return elements_; }
00882 
00885       void clear()
00886       {
00887         viennacl::linalg::vector_assign(*this, cpu_value_type(0.0), true);
00888       }
00889 
00890       viennacl::memory_types memory_domain() const
00891       {
00892         return elements_.get_active_handle_id();
00893       }
00894 
00895     protected:
00896 
00897       void set_handle(viennacl::backend::mem_handle const & h)
00898       {
00899         elements_ = h;
00900       }
00901 
00904       self_type & fast_swap(self_type & other)
00905       {
00906         assert(this->size_ == other.size_ && bool("Vector size mismatch"));
00907         this->elements_.swap(other.elements_);
00908         return *this;
00909       }
00910 
00912       void pad()
00913       {
00914         if (internal_size() != size())
00915         {
00916           std::vector<SCALARTYPE> pad(internal_size() - size());
00917           viennacl::backend::memory_write(elements_, sizeof(SCALARTYPE) * size(), sizeof(SCALARTYPE) * pad.size(), &(pad[0]));
00918         }
00919       }
00920 
00921       void switch_memory_context(viennacl::context new_ctx)
00922       {
00923         viennacl::backend::switch_memory_context<SCALARTYPE>(elements_, new_ctx);
00924       }
00925 
00926       //TODO: Think about implementing the following public member functions
00927       //void insert_element(unsigned int i, SCALARTYPE val){}
00928       //void erase_element(unsigned int i){}
00929 
00930       //enlarge or reduce allocated memory and set unused memory to zero
00936       void resize(size_type new_size, bool preserve = true)
00937       {
00938         resize_impl(new_size, viennacl::traits::context(*this), preserve);
00939       }
00940 
00947       void resize(size_type new_size, viennacl::context ctx, bool preserve = true)
00948       {
00949         resize_impl(new_size, ctx, preserve);
00950       }
00951 
00952     private:
00953 
00954       void resize_impl(size_type new_size, viennacl::context ctx, bool preserve = true)
00955       {
00956         assert(new_size > 0 && bool("Positive size required when resizing vector!"));
00957 
00958         if (new_size != size_)
00959         {
00960           vcl_size_t new_internal_size = viennacl::tools::align_to_multiple<vcl_size_t>(new_size, alignment);
00961 
00962           std::vector<SCALARTYPE> temp(size_);
00963           if (preserve && size_ > 0)
00964             fast_copy(*this, temp);
00965           temp.resize(new_size);  //drop all entries above new_size
00966           temp.resize(new_internal_size); //enlarge to fit new internal size
00967 
00968           if (new_internal_size != internal_size())
00969           {
00970             viennacl::backend::memory_create(elements_, sizeof(SCALARTYPE)*new_internal_size, ctx, NULL);
00971           }
00972 
00973           fast_copy(temp, *this);
00974           size_ = new_size;
00975           internal_size_ = viennacl::tools::align_to_multiple<size_type>(size_, alignment);
00976           pad();
00977         }
00978 
00979       }
00980 
00981       size_type       size_;
00982       size_type       start_;
00983       difference_type stride_;
00984       size_type       internal_size_;
00985       handle_type elements_;
00986   }; //vector_base
00987 
00988 
00989 
00990   // forward definition in forwards.h!
00999   template<class SCALARTYPE, unsigned int ALIGNMENT>
01000   class vector : public vector_base<SCALARTYPE>
01001   {
01002     typedef vector<SCALARTYPE, ALIGNMENT>         self_type;
01003     typedef vector_base<SCALARTYPE>               base_type;
01004 
01005   public:
01006     typedef typename base_type::size_type                  size_type;
01007     typedef typename base_type::difference_type            difference_type;
01008 
01011     explicit vector() : base_type() { /* Note: One must not call ::init() here because the vector might have been created globally before the backend has become available */ }
01012 
01017     explicit vector(size_type vec_size) : base_type(vec_size) {}
01018 
01019     explicit vector(size_type vec_size, viennacl::context ctx) : base_type(vec_size, ctx) {}
01020 
01021     explicit vector(SCALARTYPE * ptr_to_mem, viennacl::memory_types mem_type, size_type vec_size, size_type start = 0, difference_type stride = 1)
01022         : base_type(ptr_to_mem, mem_type, vec_size, start, stride) {}
01023 
01024 #ifdef VIENNACL_WITH_OPENCL
01025 
01033     explicit vector(cl_mem existing_mem, size_type vec_size, size_type start = 0, difference_type stride = 1) : base_type(existing_mem, vec_size, start, stride) {}
01034 
01040     explicit vector(size_type vec_size, viennacl::ocl::context const & ctx) : base_type(vec_size, ctx) {}
01041 #endif
01042 
01043     template <typename LHS, typename RHS, typename OP>
01044     vector(vector_expression<const LHS, const RHS, OP> const & proxy) : base_type(proxy) {}
01045 
01046     vector(const base_type & v) : base_type(v.size(), viennacl::traits::context(v))
01047     {
01048       if (v.size() > 0)
01049         base_type::operator=(v);
01050     }
01051 
01052     vector(const self_type & v) : base_type(v.size(), viennacl::traits::context(v))
01053     {
01054       if (v.size() > 0)
01055         base_type::operator=(v);
01056     }
01057 
01059     vector(unit_vector<SCALARTYPE> const & v) : base_type(v.size())
01060     {
01061       if (v.size() > 0)
01062         this->operator()(v.index()) = SCALARTYPE(1);;
01063     }
01064 
01066     vector(zero_vector<SCALARTYPE> const & v) : base_type(v.size(), v.context())
01067     {
01068       if (v.size() > 0)
01069         viennacl::linalg::vector_assign(*this, SCALARTYPE(0.0));
01070     }
01071 
01073     vector(scalar_vector<SCALARTYPE> const & v) : base_type(v.size(), v.context())
01074     {
01075       if (v.size() > 0)
01076         viennacl::linalg::vector_assign(*this, v[0]);
01077     }
01078 
01079     // the following is used to circumvent an issue with Clang 3.0 when 'using base_type::operator=;' directly
01080     template <typename T>
01081     self_type & operator=(T const & other)
01082     {
01083       base_type::operator=(other);
01084       return *this;
01085     }
01086 
01087     using base_type::operator+=;
01088     using base_type::operator-=;
01089 
01090     //enlarge or reduce allocated memory and set unused memory to zero
01096     void resize(size_type new_size, bool preserve = true)
01097     {
01098       base_type::resize(new_size, preserve);
01099     }
01100 
01101     void resize(size_type new_size, viennacl::context ctx, bool preserve = true)
01102     {
01103       base_type::resize(new_size, ctx, preserve);
01104     }
01105 
01108     self_type & fast_swap(self_type & other)
01109     {
01110       base_type::fast_swap(other);
01111       return *this;
01112     }
01113 
01114     void switch_memory_context(viennacl::context new_ctx)
01115     {
01116       base_type::switch_memory_context(new_ctx);
01117     }
01118 
01119   }; //vector
01120 
01122   template <typename ScalarT>
01123   class vector_tuple
01124   {
01125     typedef vector_base<ScalarT>   VectorType;
01126 
01127   public:
01128       // 2 vectors
01129 
01130       vector_tuple(VectorType const & v0, VectorType const & v1) : const_vectors_(2), non_const_vectors_()
01131       {
01132         const_vectors_[0] = &v0;
01133         const_vectors_[1] = &v1;
01134       }
01135       vector_tuple(VectorType       & v0, VectorType       & v1) : const_vectors_(2), non_const_vectors_(2)
01136       {
01137         const_vectors_[0] = &v0; non_const_vectors_[0] = &v0;
01138         const_vectors_[1] = &v1; non_const_vectors_[1] = &v1;
01139       }
01140 
01141       // 3 vectors
01142 
01143       vector_tuple(VectorType const & v0, VectorType const & v1, VectorType const & v2) : const_vectors_(3), non_const_vectors_()
01144       {
01145         const_vectors_[0] = &v0;
01146         const_vectors_[1] = &v1;
01147         const_vectors_[2] = &v2;
01148       }
01149       vector_tuple(VectorType       & v0, VectorType       & v1, VectorType       & v2) : const_vectors_(3), non_const_vectors_(3)
01150       {
01151         const_vectors_[0] = &v0; non_const_vectors_[0] = &v0;
01152         const_vectors_[1] = &v1; non_const_vectors_[1] = &v1;
01153         const_vectors_[2] = &v2; non_const_vectors_[2] = &v2;
01154       }
01155 
01156       // 4 vectors
01157 
01158       vector_tuple(VectorType const & v0, VectorType const & v1, VectorType const & v2, VectorType const & v3) : const_vectors_(4), non_const_vectors_()
01159       {
01160         const_vectors_[0] = &v0;
01161         const_vectors_[1] = &v1;
01162         const_vectors_[2] = &v2;
01163         const_vectors_[3] = &v3;
01164       }
01165       vector_tuple(VectorType       & v0, VectorType       & v1, VectorType       & v2, VectorType       & v3) : const_vectors_(4), non_const_vectors_(4)
01166       {
01167         const_vectors_[0] = &v0; non_const_vectors_[0] = &v0;
01168         const_vectors_[1] = &v1; non_const_vectors_[1] = &v1;
01169         const_vectors_[2] = &v2; non_const_vectors_[2] = &v2;
01170         const_vectors_[3] = &v3; non_const_vectors_[3] = &v3;
01171       }
01172 
01173       // add more overloads here
01174 
01175       // generic interface:
01176 
01177       vector_tuple(std::vector<VectorType const *> const & vecs) : const_vectors_(vecs.size()), non_const_vectors_()
01178       {
01179         for (vcl_size_t i=0; i<vecs.size(); ++i)
01180           const_vectors_[i] = vecs[i];
01181       }
01182 
01183       vector_tuple(std::vector<VectorType *> const & vecs) : const_vectors_(vecs.size()), non_const_vectors_(vecs.size())
01184       {
01185         for (vcl_size_t i=0; i<vecs.size(); ++i)
01186         {
01187               const_vectors_[i] = vecs[i];
01188           non_const_vectors_[i] = vecs[i];
01189         }
01190       }
01191 
01192       vcl_size_t size()       const { return non_const_vectors_.size(); }
01193       vcl_size_t const_size() const { return     const_vectors_.size(); }
01194 
01195       VectorType       &       at(vcl_size_t i) const { return *(non_const_vectors_.at(i)); }
01196       VectorType const & const_at(vcl_size_t i) const { return     *(const_vectors_.at(i)); }
01197 
01198   private:
01199     std::vector<VectorType const *>   const_vectors_;
01200     std::vector<VectorType *>         non_const_vectors_;
01201   };
01202 
01203   // 2 args
01204   template <typename ScalarT>
01205   vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1) { return vector_tuple<ScalarT>(v0, v1); }
01206 
01207   template <typename ScalarT>
01208   vector_tuple<ScalarT> tie(vector_base<ScalarT>       & v0, vector_base<ScalarT>       & v1) { return vector_tuple<ScalarT>(v0, v1); }
01209 
01210   // 3 args
01211   template <typename ScalarT>
01212   vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1, vector_base<ScalarT> const & v2) { return vector_tuple<ScalarT>(v0, v1, v2); }
01213 
01214   template <typename ScalarT>
01215   vector_tuple<ScalarT> tie(vector_base<ScalarT>       & v0, vector_base<ScalarT>       & v1, vector_base<ScalarT>       & v2) { return vector_tuple<ScalarT>(v0, v1, v2); }
01216 
01217   // 4 args
01218   template <typename ScalarT>
01219   vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0, vector_base<ScalarT> const & v1, vector_base<ScalarT> const & v2, vector_base<ScalarT> const & v3)
01220   {
01221     return vector_tuple<ScalarT>(v0, v1, v2, v3);
01222   }
01223 
01224   template <typename ScalarT>
01225   vector_tuple<ScalarT> tie(vector_base<ScalarT>       & v0, vector_base<ScalarT>       & v1, vector_base<ScalarT>       & v2, vector_base<ScalarT>       & v3)
01226   {
01227     return vector_tuple<ScalarT>(v0, v1, v2, v3);
01228   }
01229 
01230   // 5 args
01231   template <typename ScalarT>
01232   vector_tuple<ScalarT> tie(vector_base<ScalarT> const & v0,
01233                             vector_base<ScalarT> const & v1,
01234                             vector_base<ScalarT> const & v2,
01235                             vector_base<ScalarT> const & v3,
01236                             vector_base<ScalarT> const & v4)
01237   {
01238     typedef vector_base<ScalarT> const *       VectorPointerType;
01239     std::vector<VectorPointerType> vec(5);
01240     vec[0] = &v0;
01241     vec[1] = &v1;
01242     vec[2] = &v2;
01243     vec[3] = &v3;
01244     vec[4] = &v4;
01245     return vector_tuple<ScalarT>(vec);
01246   }
01247 
01248   template <typename ScalarT>
01249   vector_tuple<ScalarT> tie(vector_base<ScalarT> & v0,
01250                             vector_base<ScalarT> & v1,
01251                             vector_base<ScalarT> & v2,
01252                             vector_base<ScalarT> & v3,
01253                             vector_base<ScalarT> & v4)
01254   {
01255     typedef vector_base<ScalarT> *       VectorPointerType;
01256     std::vector<VectorPointerType> vec(5);
01257     vec[0] = &v0;
01258     vec[1] = &v1;
01259     vec[2] = &v2;
01260     vec[3] = &v3;
01261     vec[4] = &v4;
01262     return vector_tuple<ScalarT>(vec);
01263   }
01264 
01265   // TODO: Add more arguments to tie() here. Maybe use some preprocessor magic to accomplish this.
01266 
01267   //
01269   //
01270 
01271 
01283   template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR>
01284   void fast_copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin,
01285                   const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end,
01286                   CPU_ITERATOR cpu_begin )
01287   {
01288     if (gpu_begin != gpu_end)
01289     {
01290       if (gpu_begin.stride() == 1)
01291       {
01292         viennacl::backend::memory_read(gpu_begin.handle(),
01293                                       sizeof(SCALARTYPE)*gpu_begin.offset(),
01294                                       sizeof(SCALARTYPE)*gpu_begin.stride() * (gpu_end - gpu_begin),
01295                                       &(*cpu_begin));
01296       }
01297       else
01298       {
01299         vcl_size_t gpu_size = (gpu_end - gpu_begin);
01300         std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * gpu_size);
01301         viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0]));
01302 
01303         for (vcl_size_t i=0; i<gpu_size; ++i)
01304         {
01305           (&(*cpu_begin))[i] = temp_buffer[i * gpu_begin.stride()];
01306         }
01307       }
01308     }
01309   }
01310 
01316   template <typename NumericT, typename CPUVECTOR>
01317   void fast_copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec )
01318   {
01319     viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin());
01320   }
01321 
01322 
01333   template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR>
01334   void async_copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin,
01335                   const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end,
01336                   CPU_ITERATOR cpu_begin )
01337   {
01338     if (gpu_begin != gpu_end)
01339     {
01340       if (gpu_begin.stride() == 1)
01341       {
01342         viennacl::backend::memory_read(gpu_begin.handle(),
01343                                        sizeof(SCALARTYPE)*gpu_begin.offset(),
01344                                        sizeof(SCALARTYPE)*gpu_begin.stride() * (gpu_end - gpu_begin),
01345                                        &(*cpu_begin),
01346                                        true);
01347       }
01348       else // no async copy possible, so fall-back to fast_copy
01349         fast_copy(gpu_begin, gpu_end, cpu_begin);
01350     }
01351   }
01352 
01358   template <typename NumericT, typename CPUVECTOR>
01359   void async_copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec )
01360   {
01361     viennacl::async_copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin());
01362   }
01363 
01364 
01371   template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR>
01372   void copy(const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin,
01373             const const_vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end,
01374             CPU_ITERATOR cpu_begin )
01375   {
01376     assert(gpu_end - gpu_begin >= 0 && bool("Iterators incompatible"));
01377     if (gpu_end - gpu_begin != 0)
01378     {
01379       std::vector<SCALARTYPE> temp_buffer(gpu_end - gpu_begin);
01380       fast_copy(gpu_begin, gpu_end, temp_buffer.begin());
01381 
01382       //now copy entries to cpu_vec:
01383       std::copy(temp_buffer.begin(), temp_buffer.end(), cpu_begin);
01384     }
01385   }
01386 
01393   template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR>
01394   void copy(const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_begin,
01395             const vector_iterator<SCALARTYPE, ALIGNMENT> & gpu_end,
01396             CPU_ITERATOR cpu_begin )
01397 
01398   {
01399     viennacl::copy(const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_begin),
01400                     const_vector_iterator<SCALARTYPE, ALIGNMENT>(gpu_end),
01401                     cpu_begin);
01402   }
01403 
01409   template <typename NumericT, typename CPUVECTOR>
01410   void copy(vector_base<NumericT> const & gpu_vec, CPUVECTOR & cpu_vec )
01411   {
01412     viennacl::copy(gpu_vec.begin(), gpu_vec.end(), cpu_vec.begin());
01413   }
01414 
01415 
01416 
01417   #ifdef VIENNACL_WITH_EIGEN
01418   template <unsigned int ALIGNMENT>
01419   void copy(vector<float, ALIGNMENT> const & gpu_vec,
01420             Eigen::VectorXf & eigen_vec)
01421   {
01422     viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0]));
01423   }
01424 
01425   template <unsigned int ALIGNMENT>
01426   void copy(vector<double, ALIGNMENT> & gpu_vec,
01427             Eigen::VectorXd & eigen_vec)
01428   {
01429     viennacl::fast_copy(gpu_vec.begin(), gpu_vec.end(), &(eigen_vec[0]));
01430   }
01431   #endif
01432 
01433 
01434   //
01436   //
01437 
01449   template <typename CPU_ITERATOR, typename SCALARTYPE, unsigned int ALIGNMENT>
01450   void fast_copy(CPU_ITERATOR const & cpu_begin,
01451                   CPU_ITERATOR const & cpu_end,
01452                   vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin)
01453   {
01454     if (cpu_end - cpu_begin > 0)
01455     {
01456       if (gpu_begin.stride() == 1)
01457       {
01458         viennacl::backend::memory_write(gpu_begin.handle(),
01459                                         sizeof(SCALARTYPE)*gpu_begin.offset(),
01460                                         sizeof(SCALARTYPE)*gpu_begin.stride() * (cpu_end - cpu_begin), &(*cpu_begin));
01461       }
01462       else //writing to slice:
01463       {
01464         vcl_size_t cpu_size = (cpu_end - cpu_begin);
01465         std::vector<SCALARTYPE> temp_buffer(gpu_begin.stride() * cpu_size);
01466 
01467         viennacl::backend::memory_read(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0]));
01468 
01469         for (vcl_size_t i=0; i<cpu_size; ++i)
01470           temp_buffer[i * gpu_begin.stride()] = (&(*cpu_begin))[i];
01471 
01472         viennacl::backend::memory_write(gpu_begin.handle(), sizeof(SCALARTYPE)*gpu_begin.offset(), sizeof(SCALARTYPE)*temp_buffer.size(), &(temp_buffer[0]));
01473       }
01474     }
01475   }
01476 
01477 
01483   template <typename CPUVECTOR, typename NumericT>
01484   void fast_copy(const CPUVECTOR & cpu_vec, vector_base<NumericT> & gpu_vec)
01485   {
01486     viennacl::fast_copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin());
01487   }
01488 
01499   template <typename CPU_ITERATOR, typename SCALARTYPE, unsigned int ALIGNMENT>
01500   void async_copy(CPU_ITERATOR const & cpu_begin,
01501                   CPU_ITERATOR const & cpu_end,
01502                   vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin)
01503   {
01504     if (cpu_end - cpu_begin > 0)
01505     {
01506       if (gpu_begin.stride() == 1)
01507       {
01508         viennacl::backend::memory_write(gpu_begin.handle(),
01509                                         sizeof(SCALARTYPE)*gpu_begin.offset(),
01510                                         sizeof(SCALARTYPE)*gpu_begin.stride() * (cpu_end - cpu_begin), &(*cpu_begin),
01511                                         true);
01512       }
01513       else // fallback to blocking copy. There's nothing we can do to prevent this
01514         fast_copy(cpu_begin, cpu_end, gpu_begin);
01515     }
01516   }
01517 
01518 
01524   template <typename CPUVECTOR, typename NumericT>
01525   void async_copy(const CPUVECTOR & cpu_vec, vector_base<NumericT> & gpu_vec)
01526   {
01527     viennacl::async_copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin());
01528   }
01529 
01530   //from cpu to gpu. Safe assumption: cpu_vector does not necessarily occupy a linear memory segment, but is not larger than the allocated memory on the GPU
01537   template <typename SCALARTYPE, unsigned int ALIGNMENT, typename CPU_ITERATOR>
01538   void copy(CPU_ITERATOR const & cpu_begin,
01539             CPU_ITERATOR const & cpu_end,
01540             vector_iterator<SCALARTYPE, ALIGNMENT> gpu_begin)
01541   {
01542     assert(cpu_end - cpu_begin > 0 && bool("Iterators incompatible"));
01543     if (cpu_begin != cpu_end)
01544     {
01545       //we require that the size of the gpu_vector is larger or equal to the cpu-size
01546       std::vector<SCALARTYPE> temp_buffer(cpu_end - cpu_begin);
01547       std::copy(cpu_begin, cpu_end, temp_buffer.begin());
01548       viennacl::fast_copy(temp_buffer.begin(), temp_buffer.end(), gpu_begin);
01549     }
01550   }
01551 
01552   // for things like copy(std_vec.begin(), std_vec.end(), vcl_vec.begin() + 1);
01553 
01559   template <typename CPUVECTOR, typename T>
01560   void copy(const CPUVECTOR & cpu_vec, vector_base<T> & gpu_vec)
01561   {
01562     viennacl::copy(cpu_vec.begin(), cpu_vec.end(), gpu_vec.begin());
01563   }
01564 
01565 
01566   #ifdef VIENNACL_WITH_EIGEN
01567   template <unsigned int ALIGNMENT>
01568   void copy(Eigen::VectorXf const & eigen_vec,
01569             vector<float, ALIGNMENT> & gpu_vec)
01570   {
01571     std::vector<float> entries(eigen_vec.size());
01572     for (vcl_size_t i = 0; i<entries.size(); ++i)
01573       entries[i] = eigen_vec(i);
01574     viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin());
01575   }
01576 
01577   template <unsigned int ALIGNMENT>
01578   void copy(Eigen::VectorXd const & eigen_vec,
01579             vector<double, ALIGNMENT> & gpu_vec)
01580   {
01581     std::vector<double> entries(eigen_vec.size());
01582     for (vcl_size_t i = 0; i<entries.size(); ++i)
01583       entries[i] = eigen_vec(i);
01584     viennacl::fast_copy(entries.begin(), entries.end(), gpu_vec.begin());
01585   }
01586   #endif
01587 
01588 
01589 
01590   //
01592   //
01599   template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST>
01600   void copy(const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin,
01601             const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end,
01602             vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin)
01603   {
01604     assert(gpu_src_end - gpu_src_begin >= 0);
01605     assert(gpu_src_begin.stride() == 1 && bool("ViennaCL ERROR: copy() for GPU->GPU not implemented for slices! Use operator= instead for the moment."));
01606 
01607     if (gpu_src_begin.stride() == 1 && gpu_dest_begin.stride() == 1)
01608     {
01609       if (gpu_src_begin != gpu_src_end)
01610         viennacl::backend::memory_copy(gpu_src_begin.handle(), gpu_dest_begin.handle(),
01611                                         sizeof(SCALARTYPE) * gpu_src_begin.offset(),
01612                                         sizeof(SCALARTYPE) * gpu_dest_begin.offset(),
01613                                         sizeof(SCALARTYPE) * (gpu_src_end.offset() - gpu_src_begin.offset()));
01614     }
01615     else
01616     {
01617       assert( false && bool("not implemented yet"));
01618     }
01619   }
01620 
01627   template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST>
01628   void copy(vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_begin,
01629             vector_iterator<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_end,
01630             vector_iterator<SCALARTYPE, ALIGNMENT_DEST> gpu_dest_begin)
01631   {
01632     viennacl::copy(static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_begin),
01633                     static_cast<const_vector_iterator<SCALARTYPE, ALIGNMENT_SRC> >(gpu_src_end),
01634                     gpu_dest_begin);
01635   }
01636 
01642   template <typename SCALARTYPE, unsigned int ALIGNMENT_SRC, unsigned int ALIGNMENT_DEST>
01643   void copy(vector<SCALARTYPE, ALIGNMENT_SRC> const & gpu_src_vec,
01644             vector<SCALARTYPE, ALIGNMENT_DEST> & gpu_dest_vec )
01645   {
01646     viennacl::copy(gpu_src_vec.begin(), gpu_src_vec.end(), gpu_dest_vec.begin());
01647   }
01648 
01649 
01650 
01651 
01652 
01653 
01654   //global functions for handling vectors:
01659   template <typename T>
01660   std::ostream & operator<<(std::ostream & os, vector_base<T> const & val)
01661   {
01662     std::vector<T> tmp(val.size());
01663     viennacl::copy(val.begin(), val.end(), tmp.begin());
01664     os << "[" << val.size() << "](";
01665     for (typename std::vector<T>::size_type i=0; i<val.size(); ++i)
01666     {
01667       if (i > 0)
01668         os << ",";
01669       os << tmp[i];
01670     }
01671     os << ")";
01672     return os;
01673   }
01674 
01675   template <typename LHS, typename RHS, typename OP>
01676   std::ostream & operator<<(std::ostream & os, vector_expression<LHS, RHS, OP> const & proxy)
01677 
01678   {
01679     typedef typename viennacl::result_of::cpu_value_type<typename LHS::value_type>::type ScalarType;
01680     viennacl::vector<ScalarType> result = proxy;
01681     os << result;
01682     return os;
01683   }
01684 
01690   template <typename T>
01691   void swap(vector_base<T> & vec1, vector_base<T> & vec2)
01692   {
01693     viennacl::linalg::vector_swap(vec1, vec2);
01694   }
01695 
01701   template <typename SCALARTYPE, unsigned int ALIGNMENT>
01702   vector<SCALARTYPE, ALIGNMENT> & fast_swap(vector<SCALARTYPE, ALIGNMENT> & v1,
01703                                             vector<SCALARTYPE, ALIGNMENT> & v2)
01704   {
01705     return v1.fast_swap(v2);
01706   }
01707 
01708 
01709 
01710 
01711 
01712   //
01713   //
01715   //
01716   //
01717 
01718 
01719   //
01720   // operator *=
01721   //
01722 
01725   template <typename T, typename S1>
01726   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
01727                                 vector_base<T> &
01728                               >::type
01729   operator *= (vector_base<T> & v1, S1 const & gpu_val)
01730   {
01731     if (v1.size() > 0)
01732       viennacl::linalg::av(v1,
01733                            v1, gpu_val, 1, false, (viennacl::is_flip_sign_scalar<S1>::value ? true : false));
01734     return v1;
01735   }
01736 
01737 
01738   //
01739   // operator /=
01740   //
01741 
01742 
01745   template <typename T, typename S1>
01746   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
01747                                 vector_base<T> &
01748                               >::type
01749   operator /= (vector_base<T> & v1, S1 const & gpu_val)
01750   {
01751     if (v1.size() > 0)
01752       viennacl::linalg::av(v1,
01753                            v1, gpu_val, 1, true, (viennacl::is_flip_sign_scalar<S1>::value ? true : false));
01754     return v1;
01755   }
01756 
01757 
01758   //
01759   // operator +
01760   //
01761 
01762 
01768   template <typename LHS1, typename RHS1, typename OP1,
01769             typename LHS2, typename RHS2, typename OP2>
01770   vector_expression< const vector_expression< LHS1, RHS1, OP1>,
01771                      const vector_expression< LHS2, RHS2, OP2>,
01772                      viennacl::op_add>
01773   operator + (vector_expression<LHS1, RHS1, OP1> const & proxy1,
01774               vector_expression<LHS2, RHS2, OP2> const & proxy2)
01775   {
01776     assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!"));
01777     return   vector_expression< const vector_expression<LHS1, RHS1, OP1>,
01778                                 const vector_expression<LHS2, RHS2, OP2>,
01779                                 viennacl::op_add>(proxy1, proxy2);
01780   }
01781 
01787   template <typename LHS, typename RHS, typename OP, typename T>
01788   vector_expression< const vector_expression<LHS, RHS, OP>,
01789                      const vector_base<T>,
01790                      viennacl::op_add>
01791   operator + (vector_expression<LHS, RHS, OP> const & proxy,
01792               vector_base<T> const & vec)
01793   {
01794     assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!"));
01795     return vector_expression< const vector_expression<LHS, RHS, OP>,
01796                               const vector_base<T>,
01797                               viennacl::op_add>(proxy, vec);
01798   }
01799 
01805   template <typename T, typename LHS, typename RHS, typename OP>
01806   vector_expression< const vector_base<T>,
01807                      const vector_expression<LHS, RHS, OP>,
01808                      viennacl::op_add>
01809   operator + (vector_base<T> const & vec,
01810               vector_expression<LHS, RHS, OP> const & proxy)
01811   {
01812     assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!"));
01813     return vector_expression< const vector_base<T>,
01814                               const vector_expression<LHS, RHS, OP>,
01815                               viennacl::op_add>(vec, proxy);
01816   }
01817 
01820   template <typename T>
01821   vector_expression< const vector_base<T>, const vector_base<T>, op_add>
01822   operator + (const vector_base<T> & v1, const vector_base<T> & v2)
01823   {
01824     return vector_expression< const vector_base<T>, const vector_base<T>, op_add>(v1, v2);
01825   }
01826 
01827 
01828 
01829   //
01830   // operator -
01831   //
01832 
01838   template <typename LHS1, typename RHS1, typename OP1,
01839             typename LHS2, typename RHS2, typename OP2>
01840   vector_expression< const vector_expression< LHS1, RHS1, OP1>,
01841                      const vector_expression< LHS2, RHS2, OP2>,
01842                      viennacl::op_sub>
01843   operator - (vector_expression<LHS1, RHS1, OP1> const & proxy1,
01844               vector_expression<LHS2, RHS2, OP2> const & proxy2)
01845   {
01846     assert(proxy1.size() == proxy2.size() && bool("Incompatible vector sizes!"));
01847     return   vector_expression< const vector_expression<LHS1, RHS1, OP1>,
01848                                 const vector_expression<LHS2, RHS2, OP2>,
01849                                 viennacl::op_sub>(proxy1, proxy2);
01850   }
01851 
01852 
01858   template <typename LHS, typename RHS, typename OP, typename T>
01859   vector_expression< const vector_expression<LHS, RHS, OP>,
01860                      const vector_base<T>,
01861                      viennacl::op_sub>
01862   operator - (vector_expression<LHS, RHS, OP> const & proxy,
01863               vector_base<T> const & vec)
01864   {
01865     assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!"));
01866     return vector_expression< const vector_expression<LHS, RHS, OP>,
01867                               const vector_base<T>,
01868                               viennacl::op_sub>(proxy, vec);
01869   }
01870 
01876   template <typename T, typename LHS, typename RHS, typename OP>
01877   vector_expression< const vector_base<T>,
01878                      const vector_expression<LHS, RHS, OP>,
01879                      viennacl::op_sub>
01880   operator - (vector_base<T> const & vec,
01881               vector_expression<LHS, RHS, OP> const & proxy)
01882   {
01883     assert(proxy.size() == vec.size() && bool("Incompatible vector sizes!"));
01884     return vector_expression< const vector_base<T>,
01885                               const vector_expression<LHS, RHS, OP>,
01886                               viennacl::op_sub>(vec, proxy);
01887   }
01888 
01891   template <typename T>
01892   vector_expression< const vector_base<T>, const vector_base<T>, op_sub>
01893   operator - (const vector_base<T> & v1, const vector_base<T> & v2)
01894   {
01895     return vector_expression< const vector_base<T>, const vector_base<T>, op_sub>(v1, v2);
01896   }
01897 
01898 
01899   //
01900   // operator *
01901   //
01902 
01903 
01909   template <typename S1, typename T>
01910   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
01911                                 vector_expression< const vector_base<T>, const S1, op_mult> >::type
01912   operator * (S1 const & value, vector_base<T> const & vec)
01913   {
01914     return vector_expression< const vector_base<T>, const S1, op_mult>(vec, value);
01915   }
01916 
01922   template <typename T>
01923   vector_expression< const vector_base<T>, const T, op_mult>
01924   operator * (char value, vector_base<T> const & vec)
01925   {
01926     return vector_expression< const vector_base<T>, const T, op_mult>(vec, value);
01927   }
01928 
01934   template <typename T>
01935   vector_expression< const vector_base<T>, const T, op_mult>
01936   operator * (short value, vector_base<T> const & vec)
01937   {
01938     return vector_expression< const vector_base<T>, const T, op_mult>(vec, value);
01939   }
01940 
01946   template <typename T>
01947   vector_expression< const vector_base<T>, const T, op_mult>
01948   operator * (int value, vector_base<T> const & vec)
01949   {
01950     return vector_expression< const vector_base<T>, const T, op_mult>(vec, value);
01951   }
01952 
01958   template <typename T>
01959   vector_expression< const vector_base<T>, const T, op_mult>
01960   operator * (long value, vector_base<T> const & vec)
01961   {
01962     return vector_expression< const vector_base<T>, const T, op_mult>(vec, value);
01963   }
01964 
01965 
01966 
01967 
01973   template <typename LHS, typename RHS, typename OP, typename T>
01974   vector_expression< const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult>
01975   operator * (scalar_expression<LHS, RHS, OP> const & expr, vector_base<T> const & vec)
01976   {
01977     return vector_expression< const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult>(vec, expr);
01978   }
01979 
01982   template <typename T, typename S1>
01983   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
01984                                 vector_expression< const vector_base<T>, const S1, op_mult> >::type
01985   operator * (vector_base<T> const & vec, S1 const & value)
01986   {
01987     return vector_expression< const vector_base<T>, const S1, op_mult>(vec, value);
01988   }
01989 
01990   template <typename T>
01991   vector_expression< const vector_base<T>, const T, op_mult>
01992   operator * (vector_base<T> const & vec, T const & value)
01993   {
01994     return vector_expression< const vector_base<T>, const T, op_mult>(vec, value);
01995   }
01996 
02002   template <typename LHS, typename RHS, typename OP, typename S1>
02003   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
02004                                 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>  >::type
02005   operator * (vector_expression< LHS, RHS, OP> const & proxy,
02006               S1 const & val)
02007   {
02008     return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>(proxy, val);
02009   }
02010 
02016   template <typename S1, typename LHS, typename RHS, typename OP>
02017   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
02018                                 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>  >::type
02019   operator * (S1 const & val,
02020               vector_expression<LHS, RHS, OP> const & proxy)
02021   {
02022     return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_mult>(proxy, val);
02023   }
02024 
02025   //
02026   // operator /
02027   //
02028 
02034   template <typename S1, typename LHS, typename RHS, typename OP>
02035   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
02036                                 viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_div>  >::type
02037   operator / (vector_expression< LHS, RHS, OP> const & proxy,
02038               S1 const & val)
02039   {
02040     return viennacl::vector_expression<const vector_expression<LHS, RHS, OP>, const S1, op_div>(proxy, val);
02041   }
02042 
02043 
02046   template <typename T, typename S1>
02047   typename viennacl::enable_if< viennacl::is_any_scalar<S1>::value,
02048                                 vector_expression< const vector_base<T>, const S1, op_div> >::type
02049   operator / (vector_base<T> const & v1, S1 const & s1)
02050   {
02051     return vector_expression<const vector_base<T>, const S1, op_div>(v1, s1);
02052   }
02053 
02054 
02055 
02056   //
02057   // Specify available operations:
02058   //
02059 
02062   namespace linalg
02063   {
02064     namespace detail
02065     {
02066       // x = y
02067       template <typename T>
02068       struct op_executor<vector_base<T>, op_assign, vector_base<T> >
02069       {
02070         static void apply(vector_base<T> & lhs, vector_base<T> const & rhs)
02071         {
02072           viennacl::linalg::av(lhs, rhs, T(1), 1, false, false);
02073         }
02074       };
02075 
02076       // x = inner_prod(z, {y0, y1, ...})
02077       template <typename T>
02078       struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const vector_tuple<T>, op_inner_prod> >
02079       {
02080         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_tuple<T>, op_inner_prod> const & rhs)
02081         {
02082           viennacl::linalg::inner_prod_impl(rhs.lhs(), rhs.rhs(), lhs);
02083         }
02084       };
02085 
02086       // x += y
02087       template <typename T>
02088       struct op_executor<vector_base<T>, op_inplace_add, vector_base<T> >
02089       {
02090         static void apply(vector_base<T> & lhs, vector_base<T> const & rhs)
02091         {
02092           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, rhs, T(1), 1, false, false);
02093         }
02094       };
02095 
02096       // x -= y
02097       template <typename T>
02098       struct op_executor<vector_base<T>, op_inplace_sub, vector_base<T> >
02099       {
02100         static void apply(vector_base<T> & lhs, vector_base<T> const & rhs)
02101         {
02102           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, rhs, T(1), 1, false, true);
02103         }
02104       };
02105 
02107 
02108 
02109       // x = alpha * y
02110       template <typename T, typename ScalarType>
02111       struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const ScalarType, op_mult> >
02112       {
02113         // generic case: ScalarType is a scalar expression
02114         template <typename LHS, typename RHS, typename OP>
02115         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy)
02116         {
02117           T alpha = proxy.rhs();
02118           viennacl::linalg::av(lhs, proxy.lhs(), alpha, 1, false, false);
02119         }
02120 
02121         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy)
02122         {
02123           viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, false, false);
02124         }
02125 
02126         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy)
02127         {
02128           viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, false, false);
02129         }
02130       };
02131 
02132       // x += alpha * y
02133       template <typename T, typename ScalarType>
02134       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_base<T>, const ScalarType, op_mult> >
02135       {
02136         // generic case: ScalarType is a scalar expression
02137         template <typename LHS, typename RHS, typename OP>
02138         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy)
02139         {
02140           T alpha = proxy.rhs();
02141           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), alpha, 1, false, false);
02142         }
02143 
02144         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy)
02145         {
02146           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, false);
02147         }
02148 
02149         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy)
02150         {
02151           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, false);
02152         }
02153       };
02154 
02155       // x -= alpha * y
02156       template <typename T, typename ScalarType>
02157       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_base<T>, const ScalarType, op_mult> >
02158       {
02159         // generic case: ScalarType is a scalar expression
02160         template <typename LHS, typename RHS, typename OP>
02161         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar_expression<LHS, RHS, OP>, op_mult> const & proxy)
02162         {
02163           T alpha = proxy.rhs();
02164           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), alpha, 1, false, true);
02165         }
02166 
02167         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const scalar<T>, op_mult> const & proxy)
02168         {
02169           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, true);
02170         }
02171 
02172         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const T, op_mult> const & proxy)
02173         {
02174           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, false, true);
02175         }
02176       };
02177 
02178 
02180 
02181       // x = alpha * vec_expr
02182       template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType>
02183       struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> >
02184       {
02185           static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy)
02186           {
02187             vector<T> temp(proxy.lhs());
02188             lhs = temp * proxy.rhs();
02189           }
02190       };
02191 
02192       // x += alpha * vec_expr
02193       template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType>
02194       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> >
02195       {
02196           static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy)
02197           {
02198             vector<T> temp(proxy.lhs());
02199             lhs += temp * proxy.rhs();
02200           }
02201       };
02202 
02203       // x -= alpha * vec_expr
02204       template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType>
02205       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> >
02206       {
02207           static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_mult> const & proxy)
02208           {
02209             vector<T> temp(proxy.lhs());
02210             lhs -= temp * proxy.rhs();
02211           }
02212       };
02213 
02214 
02216 
02217       // x = y / alpha
02218       template <typename T, typename ScalarType>
02219       struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_base<T>, const ScalarType, op_div> >
02220       {
02221         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy)
02222         {
02223           viennacl::linalg::av(lhs, proxy.lhs(), proxy.rhs(), 1, true, false);
02224         }
02225       };
02226 
02227       // x += y / alpha
02228       template <typename T, typename ScalarType>
02229       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_base<T>, const ScalarType, op_div> >
02230       {
02231         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy)
02232         {
02233           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, true, false);
02234         }
02235       };
02236 
02237       // x -= y / alpha
02238       template <typename T, typename ScalarType>
02239       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_base<T>, const ScalarType, op_div> >
02240       {
02241         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const ScalarType, op_div> const & proxy)
02242         {
02243           viennacl::linalg::avbv(lhs, lhs, T(1), 1, false, false, proxy.lhs(), proxy.rhs(), 1, true, true);
02244         }
02245       };
02246 
02247 
02249 
02250       // x = vec_expr / alpha
02251       template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType>
02252       struct op_executor<vector_base<T>, op_assign, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> >
02253       {
02254           static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy)
02255           {
02256             vector<T> temp(proxy.lhs());
02257             lhs = temp / proxy.rhs();
02258           }
02259       };
02260 
02261       // x += vec_expr / alpha
02262       template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType>
02263       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> >
02264       {
02265           static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy)
02266           {
02267             vector<T> temp(proxy.lhs());
02268             lhs += temp / proxy.rhs();
02269           }
02270       };
02271 
02272       // x -= vec_expr / alpha
02273       template <typename T, typename LHS, typename RHS, typename OP, typename ScalarType>
02274       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> >
02275       {
02276           static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS, const RHS, OP>, const ScalarType, op_div> const & proxy)
02277           {
02278             vector<T> temp(proxy.lhs());
02279             lhs -= temp / proxy.rhs();
02280           }
02281       };
02282 
02283 
02284 
02285       // generic x = vec_expr1 + vec_expr2:
02286       template <typename T, typename LHS, typename RHS>
02287       struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_add> >
02288       {
02289         // generic x = vec_expr1 + vec_expr2:
02290         template <typename LHS1, typename RHS1>
02291         static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy)
02292         {
02293           bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs());
02294           bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs());
02295 
02296           if (op_aliasing_lhs || op_aliasing_rhs)
02297           {
02298             vector_base<T> temp(proxy.lhs());
02299             op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs());
02300             lhs = temp;
02301           }
02302           else
02303           {
02304             op_executor<vector_base<T>, op_assign, LHS>::apply(lhs, proxy.lhs());
02305             op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs());
02306           }
02307         }
02308 
02309         // x = y + z
02310         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy)
02311         {
02312           viennacl::linalg::avbv(lhs,
02313                                  proxy.lhs(), T(1), 1, false, false,
02314                                  proxy.rhs(), T(1), 1, false, false);
02315         }
02316 
02317         // x = alpha * y + z
02318         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>,
02319                                                                   const vector_base<T>,
02320                                                                   op_add> const & proxy)
02321         {
02322           viennacl::linalg::avbv(lhs,
02323                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02324                                  proxy.rhs(), T(1), 1, false, false);
02325         }
02326 
02327         // x = y / alpha + z
02328         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>,
02329                                                                   const vector_base<T>,
02330                                                                   op_add> const & proxy)
02331         {
02332           viennacl::linalg::avbv(lhs,
02333                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02334                                  proxy.rhs(), T(1), 1, false, false);
02335         }
02336 
02337         // x = y + beta * z
02338         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02339                                                                   const vector_expression<const vector_base<T>, const T, op_mult>,
02340                                                                   op_add> const & proxy)
02341         {
02342           viennacl::linalg::avbv(lhs,
02343                                  proxy.lhs(), T(1), 1, false, false,
02344                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02345         }
02346 
02347         // x = y + z / beta
02348         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02349                                                                   const vector_expression<const vector_base<T>, const T, op_div>,
02350                                                                   op_add> const & proxy)
02351         {
02352           viennacl::linalg::avbv(lhs,
02353                                  proxy.lhs(), T(1), 1, false, false,
02354                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02355         }
02356 
02357         // x = alpha * y + beta * z
02358         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>,
02359                                                                   const vector_expression<const vector_base<T>, const T, op_mult>,
02360                                                                   op_add> const & proxy)
02361         {
02362           viennacl::linalg::avbv(lhs,
02363                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02364                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02365         }
02366 
02367         // x = alpha * y + z / beta
02368         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_mult>,
02369                                                                   const vector_expression<const vector_base<T>, const T, op_div>,
02370                                                                   op_add> const & proxy)
02371         {
02372           viennacl::linalg::avbv(lhs,
02373                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02374                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02375         }
02376 
02377         // x = y / alpha + beta * z
02378         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>,
02379                                                                   const vector_expression<const vector_base<T>, const T, op_mult>,
02380                                                                   op_add> const & proxy)
02381         {
02382           viennacl::linalg::avbv(lhs,
02383                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02384                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02385         }
02386 
02387         // x = y / alpha + z / beta
02388         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const T, op_div>,
02389                                                                   const vector_expression<const vector_base<T>, const T, op_div>,
02390                                                                   op_add> const & proxy)
02391         {
02392           viennacl::linalg::avbv(lhs,
02393                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02394                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02395         }
02396       };
02397 
02398 
02399       // generic x += vec_expr1 + vec_expr2:
02400       template <typename T, typename LHS, typename RHS>
02401       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_add> >
02402       {
02403         // generic x += vec_expr1 + vec_expr2:
02404         template <typename LHS1, typename RHS1>
02405         static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy)
02406         {
02407           bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs());
02408           bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs());
02409 
02410           if (op_aliasing_lhs || op_aliasing_rhs)
02411           {
02412             vector_base<T> temp(proxy.lhs());
02413             op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs());
02414             lhs += temp;
02415           }
02416           else
02417           {
02418             op_executor<vector_base<T>, op_inplace_add, LHS>::apply(lhs, proxy.lhs());
02419             op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs());
02420           }
02421         }
02422 
02423         // x += y + z
02424         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy)
02425         {
02426           viennacl::linalg::avbv_v(lhs,
02427                                    proxy.lhs(), T(1), 1, false, false,
02428                                    proxy.rhs(), T(1), 1, false, false);
02429         }
02430 
02431         // x += alpha * y + z
02432         template <typename ScalarType>
02433         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02434                                                                   const vector_base<T>,
02435                                                                   op_add> const & proxy)
02436         {
02437           viennacl::linalg::avbv_v(lhs,
02438                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02439                                    proxy.rhs(), T(1), 1, false, false);
02440         }
02441 
02442         // x += y / alpha + z
02443         template <typename ScalarType>
02444         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02445                                                                   const vector_base<T>,
02446                                                                   op_add> const & proxy)
02447         {
02448           viennacl::linalg::avbv_v(lhs,
02449                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02450                                    proxy.rhs(), T(1), 1, false, false);
02451         }
02452 
02453         // x += y + beta * z
02454         template <typename ScalarType>
02455         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02456                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02457                                                                   op_add> const & proxy)
02458         {
02459           viennacl::linalg::avbv_v(lhs,
02460                                    proxy.lhs(), T(1), 1, false, false,
02461                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02462         }
02463 
02464         // x += y + z / beta
02465         template <typename ScalarType>
02466         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02467                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02468                                                                   op_add> const & proxy)
02469         {
02470           viennacl::linalg::avbv_v(lhs,
02471                                    proxy.lhs(), T(1), 1, false, false,
02472                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02473         }
02474 
02475         // x += alpha * y + beta * z
02476         template <typename ScalarType1, typename ScalarType2>
02477         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02478                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02479                                                                   op_add> const & proxy)
02480         {
02481           viennacl::linalg::avbv_v(lhs,
02482                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02483                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02484         }
02485 
02486         // x += alpha * y + z / beta
02487         template <typename ScalarType1, typename ScalarType2>
02488         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02489                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02490                                                                   op_add> const & proxy)
02491         {
02492           viennacl::linalg::avbv_v(lhs,
02493                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02494                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02495         }
02496 
02497         // x += y / alpha + beta * z
02498         template <typename ScalarType1, typename ScalarType2>
02499         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02500                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02501                                                                   op_add> const & proxy)
02502         {
02503           viennacl::linalg::avbv_v(lhs,
02504                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02505                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02506         }
02507 
02508         // x += y / alpha + z / beta
02509         template <typename ScalarType1, typename ScalarType2>
02510         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02511                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02512                                                                   op_add> const & proxy)
02513         {
02514           viennacl::linalg::avbv_v(lhs,
02515                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02516                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02517         }
02518       };
02519 
02520 
02521 
02522       // generic x -= vec_expr1 + vec_expr2:
02523       template <typename T, typename LHS, typename RHS>
02524       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_add> >
02525       {
02526         // generic x -= vec_expr1 + vec_expr2:
02527         template <typename LHS1, typename RHS1>
02528         static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_add> const & proxy)
02529         {
02530           bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs());
02531           bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs());
02532 
02533           if (op_aliasing_lhs || op_aliasing_rhs)
02534           {
02535             vector_base<T> temp(proxy.lhs());
02536             op_executor<vector_base<T>, op_inplace_add, RHS>::apply(temp, proxy.rhs());
02537             lhs -= temp;
02538           }
02539           else
02540           {
02541             op_executor<vector_base<T>, op_inplace_sub, LHS>::apply(lhs, proxy.lhs());
02542             op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs());
02543           }
02544         }
02545 
02546         // x -= y + z
02547         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_add> const & proxy)
02548         {
02549           viennacl::linalg::avbv_v(lhs,
02550                                    proxy.lhs(), T(1), 1, false, true,
02551                                    proxy.rhs(), T(1), 1, false, true);
02552         }
02553 
02554         // x -= alpha * y + z
02555         template <typename ScalarType>
02556         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02557                                                                   const vector_base<T>,
02558                                                                   op_add> const & proxy)
02559         {
02560           viennacl::linalg::avbv_v(lhs,
02561                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true,
02562                                    proxy.rhs(), T(1), 1, false, true);
02563         }
02564 
02565         // x -= y / alpha + z
02566         template <typename ScalarType>
02567         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02568                                                                   const vector_base<T>,
02569                                                                   op_add> const & proxy)
02570         {
02571           viennacl::linalg::avbv_v(lhs,
02572                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true,
02573                                    proxy.rhs(), T(1), 1, false, true);
02574         }
02575 
02576         // x -= y + beta * z
02577         template <typename ScalarType>
02578         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02579                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02580                                                                   op_add> const & proxy)
02581         {
02582           viennacl::linalg::avbv_v(lhs,
02583                                    proxy.lhs(), T(1), 1, false, true,
02584                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02585         }
02586 
02587         // x -= y + z / beta
02588         template <typename ScalarType>
02589         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02590                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02591                                                                   op_add> const & proxy)
02592         {
02593           viennacl::linalg::avbv_v(lhs,
02594                                    proxy.lhs(), T(1), 1, false, true,
02595                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02596         }
02597 
02598         // x -= alpha * y + beta * z
02599         template <typename ScalarType1, typename ScalarType2>
02600         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02601                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02602                                                                   op_add> const & proxy)
02603         {
02604           viennacl::linalg::avbv_v(lhs,
02605                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true,
02606                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02607         }
02608 
02609         // x -= alpha * y + z / beta
02610         template <typename ScalarType1, typename ScalarType2>
02611         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02612                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02613                                                                   op_add> const & proxy)
02614         {
02615           viennacl::linalg::avbv_v(lhs,
02616                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true,
02617                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02618         }
02619 
02620         // x -= y / alpha + beta * z
02621         template <typename ScalarType1, typename ScalarType2>
02622         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02623                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02624                                                                   op_add> const & proxy)
02625         {
02626           viennacl::linalg::avbv_v(lhs,
02627                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true,
02628                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02629         }
02630 
02631         // x -= y / alpha + z / beta
02632         template <typename ScalarType1, typename ScalarType2>
02633         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02634                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02635                                                                   op_add> const & proxy)
02636         {
02637           viennacl::linalg::avbv_v(lhs,
02638                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true,
02639                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02640         }
02641       };
02642 
02643 
02644 
02646 
02647 
02648 
02649       // generic x = vec_expr1 - vec_expr2:
02650       template <typename T, typename LHS, typename RHS>
02651       struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_sub> >
02652       {
02653         // generic x = vec_expr1 - vec_expr2:
02654         template <typename LHS1, typename RHS1>
02655         static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy)
02656         {
02657           bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs());
02658           bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs());
02659 
02660           if (op_aliasing_lhs || op_aliasing_rhs)
02661           {
02662             vector_base<T> temp(proxy.lhs());
02663             op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs());
02664             lhs = temp;
02665           }
02666           else
02667           {
02668             op_executor<vector_base<T>, op_assign, LHS>::apply(lhs, proxy.lhs());
02669             op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs());
02670           }
02671         }
02672 
02673         // x = y - z
02674         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy)
02675         {
02676           viennacl::linalg::avbv(lhs,
02677                                  proxy.lhs(), T(1), 1, false, false,
02678                                  proxy.rhs(), T(1), 1, false, true);
02679         }
02680 
02681         // x = alpha * y - z
02682         template <typename ScalarType>
02683         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02684                                                                   const vector_base<T>,
02685                                                                   op_sub> const & proxy)
02686         {
02687           viennacl::linalg::avbv(lhs,
02688                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02689                                  proxy.rhs(), T(1), 1, false, true);
02690         }
02691 
02692         // x = y / alpha - z
02693         template <typename ScalarType>
02694         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02695                                                                   const vector_base<T>,
02696                                                                   op_sub> const & proxy)
02697         {
02698           viennacl::linalg::avbv(lhs,
02699                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02700                                  proxy.rhs(), T(1), 1, false, true);
02701         }
02702 
02703         // x = y - beta * z
02704         template <typename ScalarType>
02705         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02706                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02707                                                                   op_sub> const & proxy)
02708         {
02709           viennacl::linalg::avbv(lhs,
02710                                  proxy.lhs(), T(1), 1, false, false,
02711                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02712         }
02713 
02714         // x = y - z / beta
02715         template <typename ScalarType>
02716         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02717                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02718                                                                   op_sub> const & proxy)
02719         {
02720           viennacl::linalg::avbv(lhs,
02721                                  proxy.lhs(), T(1), 1, false, false,
02722                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02723         }
02724 
02725         // x = alpha * y - beta * z
02726         template <typename ScalarType1, typename ScalarType2>
02727         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02728                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02729                                                                   op_sub> const & proxy)
02730         {
02731           viennacl::linalg::avbv(lhs,
02732                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02733                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02734         }
02735 
02736         // x = alpha * y - z / beta
02737         template <typename ScalarType1, typename ScalarType2>
02738         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02739                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02740                                                                   op_sub> const & proxy)
02741         {
02742           viennacl::linalg::avbv(lhs,
02743                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02744                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02745         }
02746 
02747         // x = y / alpha - beta * z
02748         template <typename ScalarType1, typename ScalarType2>
02749         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02750                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02751                                                                   op_sub> const & proxy)
02752         {
02753           viennacl::linalg::avbv(lhs,
02754                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02755                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02756         }
02757 
02758         // x = y / alpha - z / beta
02759         template <typename ScalarType1, typename ScalarType2>
02760         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02761                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02762                                                                   op_sub> const & proxy)
02763         {
02764           viennacl::linalg::avbv(lhs,
02765                                  proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02766                                  proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02767         }
02768       };
02769 
02770 
02771       // generic x += vec_expr1 - vec_expr2:
02772       template <typename T, typename LHS, typename RHS>
02773       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_sub> >
02774       {
02775         // generic x += vec_expr1 - vec_expr2:
02776         template <typename LHS1, typename RHS1>
02777         static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy)
02778         {
02779           bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs());
02780           bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs());
02781 
02782           if (op_aliasing_lhs || op_aliasing_rhs)
02783           {
02784             vector_base<T> temp(proxy.lhs());
02785             op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs());
02786             lhs += temp;
02787           }
02788           else
02789           {
02790             op_executor<vector_base<T>, op_inplace_add, LHS>::apply(lhs, proxy.lhs());
02791             op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(lhs, proxy.rhs());
02792           }
02793         }
02794 
02795         // x += y - z
02796         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy)
02797         {
02798           viennacl::linalg::avbv_v(lhs,
02799                                    proxy.lhs(), T(1), 1, false, false,
02800                                    proxy.rhs(), T(1), 1, false, true);
02801         }
02802 
02803         // x += alpha * y - z
02804         template <typename ScalarType>
02805         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02806                                                                   const vector_base<T>,
02807                                                                   op_sub> const & proxy)
02808         {
02809           viennacl::linalg::avbv_v(lhs,
02810                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02811                                    proxy.rhs(), T(1), 1, false, true);
02812         }
02813 
02814         // x += y / alpha - z
02815         template <typename ScalarType>
02816         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02817                                                                   const vector_base<T>,
02818                                                                   op_sub> const & proxy)
02819         {
02820           viennacl::linalg::avbv_v(lhs,
02821                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02822                                    proxy.rhs(), T(1), 1, false, true);
02823         }
02824 
02825         // x += y - beta * z
02826         template <typename ScalarType>
02827         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02828                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02829                                                                   op_sub> const & proxy)
02830         {
02831           viennacl::linalg::avbv_v(lhs,
02832                                    proxy.lhs(), T(1), 1, false, false,
02833                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02834         }
02835 
02836         // x += y - z / beta
02837         template <typename ScalarType>
02838         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02839                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02840                                                                   op_sub> const & proxy)
02841         {
02842           viennacl::linalg::avbv_v(lhs,
02843                                    proxy.lhs(), T(1), 1, false, false,
02844                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02845         }
02846 
02847         // x += alpha * y - beta * z
02848         template <typename ScalarType1, typename ScalarType2>
02849         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02850                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02851                                                                   op_sub> const & proxy)
02852         {
02853           viennacl::linalg::avbv_v(lhs,
02854                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02855                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02856         }
02857 
02858         // x += alpha * y - z / beta
02859         template <typename ScalarType1, typename ScalarType2>
02860         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02861                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02862                                                                   op_sub> const & proxy)
02863         {
02864           viennacl::linalg::avbv_v(lhs,
02865                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, false,
02866                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02867         }
02868 
02869         // x += y / alpha - beta * z
02870         template <typename ScalarType1, typename ScalarType2>
02871         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02872                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02873                                                                   op_sub> const & proxy)
02874         {
02875           viennacl::linalg::avbv_v(lhs,
02876                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02877                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, true);
02878         }
02879 
02880         // x += y / alpha - z / beta
02881         template <typename ScalarType1, typename ScalarType2>
02882         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02883                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02884                                                                   op_sub> const & proxy)
02885         {
02886           viennacl::linalg::avbv_v(lhs,
02887                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, false,
02888                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, true);
02889         }
02890       };
02891 
02892 
02893 
02894       // generic x -= vec_expr1 - vec_expr2:
02895       template <typename T, typename LHS, typename RHS>
02896       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_sub> >
02897       {
02898         // generic x -= vec_expr1 - vec_expr2:
02899         template <typename LHS1, typename RHS1>
02900         static void apply(vector_base<T> & lhs, vector_expression<const LHS1, const RHS1, op_sub> const & proxy)
02901         {
02902           bool op_aliasing_lhs = op_aliasing(lhs, proxy.lhs());
02903           bool op_aliasing_rhs = op_aliasing(lhs, proxy.rhs());
02904 
02905           if (op_aliasing_lhs || op_aliasing_rhs)
02906           {
02907             vector_base<T> temp(proxy.lhs());
02908             op_executor<vector_base<T>, op_inplace_sub, RHS>::apply(temp, proxy.rhs());
02909             lhs -= temp;
02910           }
02911           else
02912           {
02913             op_executor<vector_base<T>, op_inplace_sub, LHS>::apply(lhs, proxy.lhs());
02914             op_executor<vector_base<T>, op_inplace_add, RHS>::apply(lhs, proxy.rhs());
02915           }
02916         }
02917 
02918         // x -= y - z
02919         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_sub> const & proxy)
02920         {
02921           viennacl::linalg::avbv_v(lhs,
02922                                    proxy.lhs(), T(1), 1, false, true,
02923                                    proxy.rhs(), T(1), 1, false, false);
02924         }
02925 
02926         // x -= alpha * y - z
02927         template <typename ScalarType>
02928         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02929                                                                   const vector_base<T>,
02930                                                                   op_sub> const & proxy)
02931         {
02932           viennacl::linalg::avbv_v(lhs,
02933                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true,
02934                                    proxy.rhs(), T(1), 1, false, false);
02935         }
02936 
02937         // x -= y / alpha - z
02938         template <typename ScalarType>
02939         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02940                                                                   const vector_base<T>,
02941                                                                   op_sub> const & proxy)
02942         {
02943           viennacl::linalg::avbv_v(lhs,
02944                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true,
02945                                    proxy.rhs(), T(1), 1, false, false);
02946         }
02947 
02948         // x -= y - beta * z
02949         template <typename ScalarType>
02950         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02951                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_mult>,
02952                                                                   op_sub> const & proxy)
02953         {
02954           viennacl::linalg::avbv_v(lhs,
02955                                    proxy.lhs(), T(1), 1, false, true,
02956                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02957         }
02958 
02959         // x -= y - z / beta
02960         template <typename ScalarType>
02961         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>,
02962                                                                   const vector_expression<const vector_base<T>, const ScalarType, op_div>,
02963                                                                   op_sub> const & proxy)
02964         {
02965           viennacl::linalg::avbv_v(lhs,
02966                                    proxy.lhs(), T(1), 1, false, true,
02967                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02968         }
02969 
02970         // x -= alpha * y - beta * z
02971         template <typename ScalarType1, typename ScalarType2>
02972         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02973                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02974                                                                   op_sub> const & proxy)
02975         {
02976           viennacl::linalg::avbv_v(lhs,
02977                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true,
02978                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
02979         }
02980 
02981         // x -= alpha * y - z / beta
02982         template <typename ScalarType1, typename ScalarType2>
02983         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_mult>,
02984                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
02985                                                                   op_sub> const & proxy)
02986         {
02987           viennacl::linalg::avbv_v(lhs,
02988                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, false, true,
02989                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
02990         }
02991 
02992         // x -= y / alpha - beta * z
02993         template <typename ScalarType1, typename ScalarType2>
02994         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
02995                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_mult>,
02996                                                                   op_sub> const & proxy)
02997         {
02998           viennacl::linalg::avbv_v(lhs,
02999                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true,
03000                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, false, false);
03001         }
03002 
03003         // x -= y / alpha - z / beta
03004         template <typename ScalarType1, typename ScalarType2>
03005         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const vector_base<T>, const ScalarType1, op_div>,
03006                                                                   const vector_expression<const vector_base<T>, const ScalarType2, op_div>,
03007                                                                   op_sub> const & proxy)
03008         {
03009           viennacl::linalg::avbv_v(lhs,
03010                                    proxy.lhs().lhs(), proxy.lhs().rhs(), 1, true, true,
03011                                    proxy.rhs().lhs(), proxy.rhs().rhs(), 1, true, false);
03012         }
03013       };
03014 
03015 
03016 
03017 
03018 
03019 
03020 
03021 
03022 
03023 
03024 
03025 
03026 
03027 
03028 
03029 
03030 
03031 
03033 
03034       // generic x = vec_expr1 .* vec_expr2:
03035       template <typename T, typename LHS, typename RHS, typename OP>
03036       struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_element_binary<OP> > >
03037       {
03038         // x = y .* z  or  x = y ./ z
03039         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy)
03040         {
03041           viennacl::linalg::element_op(lhs, proxy);
03042         }
03043 
03044         // x = y .* vec_expr  or  x = y ./ vec_expr
03045         template <typename LHS2, typename RHS2, typename OP2>
03046         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_expression<const LHS2, const RHS2, OP2>, op_element_binary<OP> > const & proxy)
03047         {
03048           vector<T> temp(proxy.rhs());
03049           viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp));
03050         }
03051 
03052         // x = vec_expr .* z  or  x = vec_expr ./ z
03053         template <typename LHS1, typename RHS1, typename OP1>
03054         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, const vector_base<T>, op_element_binary<OP> > const & proxy)
03055         {
03056           vector<T> temp(proxy.lhs());
03057           viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs()));
03058         }
03059 
03060         // x = vec_expr .* vec_expr  or  z = vec_expr .* vec_expr
03061         template <typename LHS1, typename RHS1, typename OP1,
03062                   typename LHS2, typename RHS2, typename OP2>
03063         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>,
03064                                                                   const vector_expression<const LHS2, const RHS2, OP2>,
03065                                                                   op_element_binary<OP> > const & proxy)
03066         {
03067           vector<T> temp1(proxy.lhs());
03068           vector<T> temp2(proxy.rhs());
03069           viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2));
03070         }
03071       };
03072 
03073       // generic x += vec_expr1 .* vec_expr2:
03074       template <typename T, typename LHS, typename RHS, typename OP>
03075       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_element_binary<OP> > >
03076       {
03077         // x += y .* z  or  x += y ./ z
03078         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy)
03079         {
03080           viennacl::vector<T> temp(proxy);
03081           lhs += temp;
03082         }
03083 
03084         // x += y .* vec_expr  or  x += y ./ vec_expr
03085         template <typename LHS2, typename RHS2, typename OP2>
03086         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_expression<const LHS2, const RHS2, OP2>,  op_element_binary<OP> > const & proxy)
03087         {
03088           vector<T> temp(proxy.rhs());
03089           vector<T> temp2(temp.size());
03090           viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp));
03091           lhs += temp2;
03092         }
03093 
03094         // x += vec_expr .* z  or  x += vec_expr ./ z
03095         template <typename LHS1, typename RHS1, typename OP1>
03096         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, const vector_base<T>, op_element_binary<OP> > const & proxy)
03097         {
03098           vector<T> temp(proxy.lhs());
03099           vector<T> temp2(temp.size());
03100           viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs()));
03101           lhs += temp2;
03102         }
03103 
03104         // x += vec_expr .* vec_expr  or  x += vec_expr ./ vec_expr
03105         template <typename LHS1, typename RHS1, typename OP1,
03106                   typename LHS2, typename RHS2, typename OP2>
03107         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>,
03108                                                                   const vector_expression<const LHS2, const RHS2, OP2>,
03109                                                                   op_element_binary<OP> > const & proxy)
03110         {
03111           vector<T> temp1(proxy.lhs());
03112           vector<T> temp2(proxy.rhs());
03113           vector<T> temp3(temp1.size());
03114           viennacl::linalg::element_op(temp3, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2));
03115           lhs += temp3;
03116         }
03117       };
03118 
03119       // generic x -= vec_expr1 .* vec_expr2:
03120       template <typename T, typename LHS, typename RHS, typename OP>
03121       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_element_binary<OP> > >
03122       {
03123 
03124         // x -= y .* z  or  x -= y ./ z
03125         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> > const & proxy)
03126         {
03127           viennacl::vector<T> temp(proxy);
03128           lhs -= temp;
03129         }
03130 
03131         // x -= y .* vec_expr  or  x -= y ./ vec_expr
03132         template <typename LHS2, typename RHS2, typename OP2>
03133         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_expression<const LHS2, const RHS2, OP2>, op_element_binary<OP> > const & proxy)
03134         {
03135           vector<T> temp(proxy.rhs());
03136           vector<T> temp2(temp.size());
03137           viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(proxy.lhs(), temp));
03138           lhs -= temp2;
03139         }
03140 
03141         // x -= vec_expr .* z  or  x -= vec_expr ./ z
03142         template <typename LHS1, typename RHS1, typename OP1>
03143         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>, const vector_base<T>, op_element_binary<OP> > const & proxy)
03144         {
03145           vector<T> temp(proxy.lhs());
03146           vector<T> temp2(temp.size());
03147           viennacl::linalg::element_op(temp2, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp, proxy.rhs()));
03148           lhs -= temp2;
03149         }
03150 
03151         // x -= vec_expr .* vec_expr  or  x -= vec_expr ./ vec_expr
03152         template <typename LHS1, typename RHS1, typename OP1,
03153                   typename LHS2, typename RHS2, typename OP2>
03154         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS1, const RHS1, OP1>,
03155                                                                   const vector_expression<const LHS2, const RHS2, OP2>,
03156                                                                   op_element_binary<OP> > const & proxy)
03157         {
03158           vector<T> temp1(proxy.lhs());
03159           vector<T> temp2(proxy.rhs());
03160           vector<T> temp3(temp1.size());
03161           viennacl::linalg::element_op(temp3, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_binary<OP> >(temp1, temp2));
03162           lhs -= temp3;
03163         }
03164       };
03165 
03167 
03168       template <typename T, typename LHS, typename RHS, typename OP>
03169       struct op_executor<vector_base<T>, op_assign, vector_expression<const LHS, const RHS, op_element_unary<OP> > >
03170       {
03171         // x = OP(y)
03172         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy)
03173         {
03174           viennacl::linalg::element_op(lhs, proxy);
03175         }
03176 
03177         // x = OP(vec_expr)
03178         template <typename LHS2, typename RHS2, typename OP2>
03179         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>,
03180                                                                   const vector_expression<const LHS2, const RHS2, OP2>,
03181                                                                   op_element_unary<OP> > const & proxy)
03182         {
03183           vector<T> temp(proxy.rhs());
03184           viennacl::linalg::element_op(lhs, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> >(temp, temp));
03185         }
03186       };
03187 
03188       template <typename T, typename LHS, typename RHS, typename OP>
03189       struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const LHS, const RHS, op_element_unary<OP> > >
03190       {
03191         // x += OP(y)
03192         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy)
03193         {
03194           vector<T> temp(proxy);
03195           lhs += temp;
03196         }
03197 
03198         // x += OP(vec_expr)
03199         template <typename LHS2, typename RHS2, typename OP2>
03200         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>,
03201                                                                   const vector_expression<const LHS2, const RHS2, OP2>,
03202                                                                   op_element_unary<OP> > const & proxy)
03203         {
03204           vector<T> temp(proxy.rhs());
03205           viennacl::linalg::element_op(temp, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> >(temp, temp)); // inplace operation is safe here
03206           lhs += temp;
03207         }
03208       };
03209 
03210       template <typename T, typename LHS, typename RHS, typename OP>
03211       struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const LHS, const RHS, op_element_unary<OP> > >
03212       {
03213         // x -= OP(y)
03214         static void apply(vector_base<T> & lhs, vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> > const & proxy)
03215         {
03216           vector<T> temp(proxy);
03217           lhs -= temp;
03218         }
03219 
03220         // x -= OP(vec_expr)
03221         template <typename LHS2, typename RHS2, typename OP2>
03222         static void apply(vector_base<T> & lhs, vector_expression<const vector_expression<const LHS2, const RHS2, OP2>,
03223                                                                   const vector_expression<const LHS2, const RHS2, OP2>,
03224                                                                   op_element_unary<OP> > const & proxy)
03225         {
03226           vector<T> temp(proxy.rhs());
03227           viennacl::linalg::element_op(temp, viennacl::vector_expression<const vector_base<T>, const vector_base<T>, op_element_unary<OP> >(temp, temp)); // inplace operation is safe here
03228           lhs -= temp;
03229         }
03230       };
03231 
03232     } // namespace detail
03233 
03234   } // namespace linalg
03235 
03238 } // namespace viennacl
03239 
03240 #endif