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