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