vector_proxy.hpp
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Vector proxy classes.
5  *
6  *
7  *
8  * \author O. Krause
9  * \date 2013
10  *
11  *
12  * \par Copyright 1995-2015 Shark Development Team
13  *
14  * <BR><HR>
15  * This file is part of Shark.
16  * <http://image.diku.dk/shark/>
17  *
18  * Shark is free software: you can redistribute it and/or modify
19  * it under the terms of the GNU Lesser General Public License as published
20  * by the Free Software Foundation, either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * Shark is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU Lesser General Public License for more details.
27  *
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
30  *
31  */
32 
33 
34 #ifndef SHARK_LINALG_BLAS_VECTOR_PROXY_HPP
35 #define SHARK_LINALG_BLAS_VECTOR_PROXY_HPP
36 
37 #include "assignment.hpp"
38 #include "detail/iterator.hpp"
39 
40 namespace shark{
41 namespace blas{
42 
43 template<class V>
44 class vector_reference:public vector_expression<vector_reference<V> >{
45 public:
46  typedef typename V::size_type size_type;
47  typedef typename V::difference_type difference_type;
48  typedef typename V::value_type value_type;
49  typedef typename V::scalar_type scalar_type;
50  typedef typename V::const_reference const_reference;
51  typedef typename reference<V>::type reference;
52  typedef typename V::const_pointer const_pointer;
53  typedef typename pointer<V>::type pointer;
54 
55  typedef typename V::index_type index_type;
56  typedef typename V::const_index_pointer const_index_pointer;
58 
61  typedef typename V::storage_category storage_category;
62  typedef elementwise_tag evaluation_category;
63 
64  // Construction
65  vector_reference(V& v):m_expression(&v){}
66 
67  template<class E>
69  :m_expression(&other.expression()){}
70 
71  // Expression accessors
72  V& expression() const{
73  return *m_expression;
74  }
75 
76  /// \brief Return the size of the vector.
77  size_type size() const {
78  return expression().size();
79  }
80 
81  void clear(){
82  expression().clear();
83  }
84 
85  // ---------
86  // Dense low level interface
87  // ---------
88 
89  ///\brief Returns the pointer to the beginning of the vector storage
90  ///
91  /// Low-level access to the vectors internals. Elements storage()[i*stride()] for i=1,...,size()-1 are valid
92  pointer storage()const{
93  return expression().storage();
94  }
95 
96  ///\brief Returns th stride between the elements in storage()
97  ///
98  /// In general elements of dense storage entities are spaced like storage()[i*stride()] for i=1,...,size()-1
99  difference_type stride()const{
100  return expression().stride();
101  }
102 
103  // ---------
104  // Sparse low level interface
105  // ---------
106 
107  /// \brief Number of nonzero elements of the vector.
108  size_type nnz()const{
109  return expression().nnz();
110  }
111  /// \brief Array of values of the nonzero elements.
112  const_pointer values()const{
113  return expression().values();
114  }
115  /// \brief Array of indices of the nonzero elements.
116  index_pointer indices()const{
117  return expression().indices();
118  }
119 
120  // ---------
121  // High level interface
122  // ---------
123 
124  // Element access
125  reference operator()(index_type i) const{
126  return expression()(i);
127  }
128  reference operator [](index_type i) const{
129  return expression() [i];
130  }
131 
133  expression() = v.expression();
134  return *this;
135  }
136  template<class E>
138  expression() = e();
139  return *this;
140  }
141 
142  // Iterator types
143  typedef typename V::const_iterator const_iterator;
144  typedef typename boost::mpl::if_<boost::is_const<V>,
145  typename V::const_iterator,
146  typename V::iterator>::type iterator;
147 
148  // Iterator is the iterator of the referenced expression.
149  const_iterator begin() const{
150  return expression().begin();
151  }
152  const_iterator end() const{
153  return expression().end();
154  }
155  iterator begin(){
156  return expression().begin();
157  }
158  iterator end(){
159  return expression().end();
160  }
161 
162  //sparse interface
163  iterator set_element(iterator pos, index_type index, value_type value){
164  return expression().set_element(pos,index,value);
165  }
166 
167  iterator clear_element(iterator pos){
168  return expression().clear_element(pos);
169  }
170  iterator clear_range(iterator start, iterator end){
171  return expression().clear_range(start,end);
172  }
173 
174  void reserve(size_type non_zeros){
175  expression().reserve(non_zeros);
176  }
177 
178 private:
179  V* m_expression;
180 };
181 
182 /** \brief A vector referencing a continuous subvector of elements of vector \c v containing all elements specified by \c range.
183  *
184  * A vector range can be used as a normal vector in any expression.
185  * If the specified range falls outside that of the index range of the vector, then
186  * the \c vector_range is not a well formed \c vector_expression and access to an
187  * element outside of index range of the vector is \b undefined.
188  *
189  * \tparam V the type of vector referenced (for exaboost::mple \c vector<double>)
190  */
191 template<class V>
192 class vector_range:public vector_expression<vector_range<V> >{
193 public:
194  typedef typename V::size_type size_type;
195  typedef typename V::difference_type difference_type;
196  typedef typename V::value_type value_type;
197  typedef typename V::scalar_type scalar_type;
198  typedef typename V::const_reference const_reference;
199  typedef typename reference<V>::type reference;
200  typedef typename V::const_pointer const_pointer;
201  typedef typename pointer<V>::type pointer;
202 
203  typedef typename V::index_type index_type;
204  typedef typename V::const_index_pointer const_index_pointer;
206 
207  typedef typename closure<V>::type vector_closure_type;
210  typedef typename V::storage_category storage_category;
211  typedef elementwise_tag evaluation_category;
212 
213  // Construction and destruction
214  vector_range(vector_closure_type const& data, range const& r):
215  m_expression(data), m_range(r){
216  RANGE_CHECK(start() <= m_expression.size());
217  RANGE_CHECK(start() + size() <= m_expression.size());
218  }
219 
220  //non-const-> const conversion
221  template<class E>
223  vector_range<E> const& other,
224  typename boost::disable_if<
225  boost::is_same<E,vector_range>
226  >::type* dummy = 0
227  ):m_expression(other.expression())
228  , m_range(other.range()){}
229 
230  // ---------
231  // Internal Accessors
232  // ---------
233 
234  size_type start() const{
235  return m_range.start();
236  }
237 
238  vector_closure_type const& expression() const{
239  return m_expression;
240  }
241  vector_closure_type& expression(){
242  return m_expression;
243  }
244 
245  blas::range const& range()const{
246  return m_range;
247  }
248 
249  /// \brief Return the size of the vector.
250  size_type size() const {
251  return m_range.size();
252  }
253 
254  // ---------
255  // Dense low level interface
256  // ---------
257 
258  ///\brief Returns the pointer to the beginning of the vector storage
259  ///
260  /// Low-level access to the vectors internals. Elements storage()[i*stride()] for i=1,...,size()-1 are valid
261  pointer storage()const{
262  return expression().storage()+start()*stride();
263  }
264 
265  ///\brief Returns the stride between the elements in storage()
266  ///
267  /// In general elements of dense storage entities are spaced like storage()[i*stride()] for i=1,...,size()-1
268  difference_type stride()const{
269  return expression().stride();
270  }
271 
272  // ---------
273  // High level interface
274  // ---------
275 
276  // Element access
277  reference operator()(index_type i) const{
278  return m_expression(m_range(i));
279  }
280 
281  // Assignment operators
283  return assign(*this, typename vector_temporary<V>::type(vr));
284  }
285 
286  template<class E>
288  return assign(*this, typename vector_temporary<E>::type(e));
289  }
290 
291  typedef subrange_iterator< typename vector_closure_type::iterator> iterator;
292  typedef subrange_iterator< typename vector_closure_type::const_iterator> const_iterator;
293 
294  const_iterator begin() const{
295  return const_iterator(
296  m_expression.begin(),m_expression.end(),
297  start(),start()
298  );
299  }
300  iterator begin(){
301  return iterator(
302  m_expression.begin(),m_expression.end(),
303  start(),start()
304  );
305  }
306  const_iterator end() const{
307  return const_iterator(
308  m_expression.begin(),m_expression.end(),
309  start()+size(),start()
310  );
311  }
312  iterator end(){
313  return iterator(
314  m_expression.begin(),m_expression.end(),
315  start()+size(),start()
316  );
317  }
318 
319  void clear(){
320  clear_range(begin(),end());
321  }
322 
323  iterator set_element(iterator pos, index_type index, value_type value){
324  return iterator(m_expression.set_element(pos.inner(),index+start(),value),start());
325  }
326 
327  iterator clear_range(iterator first, iterator last){
328  return iterator(m_expression.clear_range(first.inner(),last.inner()),start());
329  }
330 
331  iterator clear_element(iterator pos){
332  return iterator(m_expression.clear_element(pos.inner()),start());
333  }
334 
335  void reserve(size_type non_zeros){
336  m_expression.reserve(non_zeros);
337  }
338 private:
339  vector_closure_type m_expression;
340  blas::range m_range;
341 };
342 
343 // ------------------
344 // Simple Projections
345 // ------------------
346 
347 /** \brief Return a \c vector_range on a specified vector, a start and stop index.
348  * Return a \c vector_range on a specified vector, a start and stop index. The resulting \c vector_range can be manipulated like a normal vector.
349  * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
350  * Vector Expression and access to an element outside of index range of the vector is \b undefined.
351  */
352 template<class V>
353 temporary_proxy<vector_range<V> > subrange(vector_expression<V>& data, typename V::size_type start, typename V::size_type stop){
354  return vector_range<V> (data(), range(start, stop));
355 }
356 
357 /** \brief Return a \c const \c vector_range on a specified vector, a start and stop index.
358  * Return a \c const \c vector_range on a specified vector, a start and stop index. The resulting \c const \c vector_range can be manipulated like a normal vector.
359  *If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
360  * Vector Expression and access to an element outside of index range of the vector is \b undefined.
361  */
362 template<class V>
364  vector_expression<V> const& data,
365  typename V::size_type start,
366  typename V::size_type stop
367 ){
368  return vector_range<typename const_expression<V>::type> (data(), range(start, stop));
369 }
370 
371 template<class V>
372 temporary_proxy<vector_range<V> > subrange(temporary_proxy<V> data, typename V::size_type start, typename V::size_type stop){
373  return subrange(static_cast<V&>(data), start, stop);
374 }
375 
376 /// \brief Represents a given chunk of memory as a dense vector of elements of type T.
377 ///
378 /// This adaptor is read/write if T is non-const and read-only if T is const.
379 template<class T>
380 class dense_vector_adaptor: public vector_expression<dense_vector_adaptor<T> > {
382 public:
383 
384  //std::container types
385  typedef std::size_t size_type;
386  typedef std::ptrdiff_t difference_type;
387  typedef typename boost::remove_const<T>::type value_type;
388  typedef value_type scalar_type;
389  typedef value_type const& const_reference;
390  typedef T& reference;
391  typedef T* pointer;
392  typedef value_type const* const_pointer;
393 
394  typedef std::size_t index_type;
395  typedef index_type const* const_index_pointer;
396  typedef index_type* index_pointer;
397 
400  typedef dense_tag storage_category;
401  typedef elementwise_tag evaluation_category;
402 
403  // Construction and destruction
404 
405  /// \brief Constructor of a self_type proxy from a Dense VectorExpression
406  ///
407  /// Be aware that the expression must live longer than the proxy!
408  /// \param expression The Expression from which to construct the Proxy
409  template<class E>
411  : m_values(expression().storage())
412  , m_size(expression().size())
413  , m_stride(expression().stride()){}
414 
415  /// \brief Constructor of a self_type proxy from a Dense VectorExpression
416  ///
417  /// Be aware that the expression must live longer than the proxy!
418  /// \param expression The Expression from which to construct the Proxy
419  template<class E>
421  : m_values(expression().storage())
422  , m_size(expression().size())
423  , m_stride(expression().stride()){}
424 
425  /// \brief Constructor of a self_type proxy from a block of memory
426  /// \param values the block of memory used
427  /// \param size size of the self_type
428  /// \param stride distance between elements of the self_type in memory
429  dense_vector_adaptor(pointer values, size_type size, difference_type stride = 1 ):
430  m_values(values),m_size(size),m_stride(stride){}
431 
432  /// \brief Copy-constructor of a self_type
433  /// \param v is the proxy to be copied
434  template<class U>
436  :m_values(v.storage()),m_size(v.size()),m_stride(v.stride())
437  {}
438 
439  // ---------
440  // Dense low level interface
441  // ---------
442 
443  /// \brief Return the size of the vector.
444  size_type size() const {
445  return m_size;
446  }
447 
448  ///\brief Returns the pointer to the beginning of the vector storage
449  ///
450  /// Low-level access to the vectors internals. Elements storage()[i*stride()] for i=1,...,size()-1 are valid
451  pointer storage()const{
452  return m_values;
453  }
454 
455  ///\brief Returns th stride between the elements in storage()
456  ///
457  /// In general elements of dense storage entities are spaced like storage()[i*stride()] for i=1,...,size()-1
458  difference_type stride()const{
459  return m_stride;
460  }
461 
462  // ---------
463  // High level interface
464  // ---------
465 
466  // --------------
467  // Element access
468  // --------------
469 
470  /// \brief Return a const reference to the element \f$i\f$
471  /// \param i index of the element
472  const_reference operator()(index_type i) const {
473  return m_values[i*m_stride];
474  }
475 
476  /// \brief Return a reference to the element \f$i\f$
477  /// \param i index of the element
478  reference operator()(index_type i) {
479  return m_values[i*m_stride];
480  }
481 
482  /// \brief Return a const reference to the element \f$i\f$
483  /// \param i index of the element
484  const_reference operator[](index_type i) const {
485  return m_values[i*m_stride];
486  }
487 
488  /// \brief Return a reference to the element \f$i\f$
489  /// \param i index of the element
490  reference operator[](index_type i) {
491  return m_values[i*m_stride];
492  }
493 
494  // ------------------
495  // Element assignment
496  // ------------------
497 
498  /// \brief Set element \f$i\f$ to the value \c t
499  /// \param i index of the element
500  /// \param t reference to the value to be set
501  reference insert_element(index_type i, const_reference t) {
502  return(*this)[i] = t;
503  }
504 
505  /// \brief Set element \f$i\f$ to the \e zero value
506  /// \param i index of the element
507  void erase_element(index_type i) {
508  (*this)[i] = value_type/*zero*/();
509  }
510 
511 
513  return assign(typename vector_temporary<self_type>::type(e));
514  }
515  template<class E>
517  return assign(typename vector_temporary<E>::type(e));
518  }
519 
520  // --------------
521  // ITERATORS
522  // --------------
523 
524 
525  typedef dense_storage_iterator<T> iterator;
526  typedef dense_storage_iterator<value_type const> const_iterator;
527 
528  /// \brief return an iterator on the first element of the vector
529  const_iterator begin() const {
530  return const_iterator(m_values,0);
531  }
532 
533  /// \brief return an iterator after the last element of the vector
534  const_iterator end() const {
535  return const_iterator(m_values+size()*stride(),size());
536  }
537 
538  /// \brief Return an iterator on the first element of the vector
539  iterator begin(){
540  return iterator(m_values,0);
541  }
542 
543  /// \brief Return an iterator at the end of the vector
544  iterator end(){
545  return iterator(m_values+size()*stride(),size());
546  }
547 
548  //insertion and erasing of elements
549  iterator set_element(iterator pos, index_type index, value_type value) {
550  SIZE_CHECK(pos.index() == index);
551  (*this)(index) = value;
552  return pos;
553  }
554 
555  iterator clear_element(iterator pos) {
556  SIZE_CHECK(pos != end());
557  v(pos.index()) = value_type();
558 
559  //return new iterator to the next element
560  return pos+1;
561  }
562 
563  iterator clear_range(iterator start, iterator end) {
564  RANGE_CHECK(start < end);
565  for(; start != end; ++start){
566  *start = value_type/*zero*/();
567  }
568  return end;
569  }
570 private:
571  pointer m_values;
572  std::size_t m_size;
573  std::ptrdiff_t m_stride;
574 };
575 
576 /// \brief Converts a chunk of memory into a vector of a given size.
577 template <class T>
579  return dense_vector_adaptor<T>(data,size);
580 }
581 
582 /// \brief Converts a C-style array into a vector.
583 template <class T, std::size_t N>
585  return dense_vector_adaptor<T>(array,N);
586 }
587 
588 template<class T,class I>
589 class sparse_vector_adaptor: public vector_expression<sparse_vector_adaptor<T,I> > {
591 public:
592 
593  //std::container types
594  typedef std::size_t size_type;
595  typedef std::ptrdiff_t difference_type;
596  typedef typename boost::remove_const<T>::type value_type;
597  typedef value_type scalar_type;
598  typedef value_type const& const_reference;
599  typedef const_reference reference;
600  typedef value_type const* const_pointer;
601  typedef const_pointer pointer;
602 
603  typedef typename boost::remove_const<I>::type index_type;
604  typedef index_type const* const_index_pointer;
605  typedef const_index_pointer index_pointer;
606 
607  typedef sparse_tag storage_category;
608  typedef elementwise_tag evaluation_category;
611 
612  // Construction and destruction
613 
614  /// \brief Constructor of a self_type proxy from a Dense VectorExpression
615  ///
616  /// Be aware that the expression must live longer than the proxy!
617  /// \param expression Expression from which to construct the Proxy
618  template<class E>
620  : m_nonZeros(expression().nnz())
621  , m_indices(expression().indices())
622  , m_values(expression().values())
623  , m_size(expression().size()){}
624 
625 
626  sparse_vector_adaptor():m_size(0){}
627 
628  /// \brief Constructor of a vector proxy from a block of memory
629  /// \param size the size of the vector represented by the memory
630  /// \param values the block of memory used to store the values
631  /// \param indices the block of memory used to store the indices
632  /// \param memoryLength length of the strip of memory
634  size_type size, const_pointer values,
635  const_index_pointer indices,
636  size_type memoryLength
637  ): m_nonZeros(memoryLength)
638  , m_indices(indices)
639  , m_values(values)
640  , m_size(size){}
641 
642  /// \brief Return the size of the vector
643  size_type size() const {
644  return m_size;
645  }
646 
647  // ---------
648  // Sparse low level interface
649  // ---------
650 
651  /// \brief Number of nonzero elements of the vector.
652  size_type nnz()const{
653  return m_nonZeros;
654  }
655  /// \brief Array of values of the nonzero elements.
656  const_pointer values()const{
657  return m_values;
658  }
659  /// \brief Array of indices of the nonzero elements.
660  index_pointer indices()const{
661  return m_indices;
662  }
663 
664  /// \brief Return a const reference to the element \f$i\f$
665  /// \param i index of the element
666  value_type operator()(index_type i) const {
667  SIZE_CHECK(i < m_size);
668  const_index_pointer pos = std::lower_bound(indices(),indices()+nnz(), i);
669  difference_type diff = pos-indices();
670  if(diff == (difference_type) nnz() || *pos != i)
671  return value_type();
672  return values()[diff];
673  }
674 
675  /// \brief Return a const reference to the element \f$i\f$
676  /// \param i index of the element
677  value_type operator[](index_type i) const {
678  return (*this)(i);
679  }
680 
681  // --------------
682  // ITERATORS
683  // --------------
684 
685  typedef compressed_storage_iterator<value_type const, index_type const> const_iterator;
686  typedef const_iterator iterator;
687 
688  /// \brief return an iterator behind the last non-zero element of the vector
689  const_iterator begin() const {
690  return const_iterator(values(),indices(),0);
691  }
692 
693  /// \brief return an iterator behind the last non-zero element of the vector
694  const_iterator end() const {
695  return const_iterator(values(),indices(),nnz());
696  }
697 private:
698  std::size_t m_nonZeros;
699  const_index_pointer m_indices;
700  const_pointer m_values;
701 
702  std::size_t m_size;
703 };
704 
705 
706 }
707 }
708 
709 #endif