1 //  Copyright (c) 2012 Oswin Krause
2 //  Copyright (c) 2013 Joaquim Duran
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See
5 //  accompanying file LICENSE_1_0.txt or copy at
6 //  http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
9 #ifndef BOOST_UBLAS_MATRIX_VECTOR_HPP
10 #define BOOST_UBLAS_MATRIX_VECTOR_HPP
11 
12 #include <boost/numeric/ublas/matrix_proxy.hpp> //for matrix_row, matrix_column and matrix_expression
13 #include <boost/numeric/ublas/vector.hpp>
14 #include <boost/iterator/iterator_facade.hpp>
15 #include <boost/range/iterator_range.hpp>
16 #include <boost/type_traits/is_convertible.hpp>
17 #include <boost/utility/enable_if.hpp>
18 
19 namespace boost { namespace numeric { namespace ublas {
20 
21 namespace detail{
22 
23 /** \brief Iterator used in the represention of a matrix as a vector of rows or columns
24  *
25  * Iterator used in the represention of a matrix as a vector of rows/columns. It refers
26  * to the i-th element of the matrix, a column or a row depending of Reference type.
27  *
28  * The type of Reference should provide a constructor Reference(matrix, i)
29  *
30  * This iterator is invalidated when the underlying matrix is resized.
31  *
32  * \tparameter Matrix type of matrix that is represented as a vector of row/column
33  * \tparameter Reference Matrix row or matrix column type.
34  */
35 template<class Matrix, class Reference>
36 class matrix_vector_iterator: public boost::iterator_facade<
37     matrix_vector_iterator<Matrix,Reference>,
38     typename vector_temporary_traits<Reference>::type,
39     boost::random_access_traversal_tag,
40     Reference
41 >{
42 public:
matrix_vector_iterator()43     matrix_vector_iterator(){}
44 
45     ///\brief constructs a matrix_vector_iterator as pointing to the i-th proxy
46     BOOST_UBLAS_INLINE
matrix_vector_iterator(Matrix & matrix,std::size_t position)47     matrix_vector_iterator(Matrix& matrix, std::size_t position)
48     : matrix_(&matrix),position_(position) {}
49 
50     template<class M, class R>
51     BOOST_UBLAS_INLINE
matrix_vector_iterator(matrix_vector_iterator<M,R> const & other)52     matrix_vector_iterator(matrix_vector_iterator<M,R> const& other)
53     : matrix_(other.matrix_),position_(other.position_) {}
54 
55 private:
56     friend class boost::iterator_core_access;
57     template <class M,class R> friend class matrix_vector_iterator;
58 
59     BOOST_UBLAS_INLINE
increment()60     void increment() {
61         ++position_;
62     }
63 
64     BOOST_UBLAS_INLINE
decrement()65     void decrement() {
66         --position_;
67     }
68 
69     BOOST_UBLAS_INLINE
advance(std::ptrdiff_t n)70     void advance(std::ptrdiff_t n){
71         position_ += n;
72     }
73 
74     template<class M,class R>
75     BOOST_UBLAS_INLINE
distance_to(matrix_vector_iterator<M,R> const & other) const76     std::ptrdiff_t distance_to(matrix_vector_iterator<M,R> const& other) const{
77         BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ());
78         return (std::ptrdiff_t)other.position_ - (std::ptrdiff_t)position_;
79     }
80 
81     template<class M,class R>
82     BOOST_UBLAS_INLINE
equal(matrix_vector_iterator<M,R> const & other) const83     bool equal(matrix_vector_iterator<M,R> const& other) const{
84         BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ());
85         return (position_ == other.position_);
86     }
87 
88     BOOST_UBLAS_INLINE
dereference() const89     Reference dereference() const {
90         return Reference(*matrix_,position_);
91     }
92 
93     Matrix* matrix_;//no matrix_closure here to ensure easy usage
94     std::size_t position_;
95 };
96 
97 }
98 
99 /** \brief Represents a \c Matrix as a vector of rows.
100  *
101  * Implements an interface to Matrix that the underlaying matrix is represented as a
102  * vector of rows.
103  *
104  * The vector could be resized which causes the resize of the number of rows of
105  * the underlaying matrix.
106  */
107 template<class Matrix>
108 class matrix_row_vector {
109 public:
110     typedef ublas::matrix_row<Matrix> value_type;
111     typedef ublas::matrix_row<Matrix> reference;
112     typedef ublas::matrix_row<Matrix const> const_reference;
113 
114     typedef ublas::detail::matrix_vector_iterator<Matrix, ublas::matrix_row<Matrix> > iterator;
115     typedef ublas::detail::matrix_vector_iterator<Matrix const, ublas::matrix_row<Matrix const> const> const_iterator;
116     typedef boost::reverse_iterator<iterator> reverse_iterator;
117     typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
118 
119     typedef typename boost::iterator_difference<iterator>::type difference_type;
120     typedef typename Matrix::size_type size_type;
121 
122     BOOST_UBLAS_INLINE
matrix_row_vector(Matrix & matrix)123     explicit matrix_row_vector(Matrix& matrix) :
124         matrix_(&matrix) {
125     }
126 
127     BOOST_UBLAS_INLINE
begin()128     iterator begin(){
129         return iterator(*matrix_, 0);
130     }
131 
132     BOOST_UBLAS_INLINE
begin() const133     const_iterator begin() const {
134         return const_iterator(*matrix_, 0);
135     }
136 
137     BOOST_UBLAS_INLINE
cbegin() const138     const_iterator cbegin() const {
139         return begin();
140     }
141 
142     BOOST_UBLAS_INLINE
end()143     iterator end() {
144         return iterator(*matrix_, matrix_->size1());
145     }
146 
147     BOOST_UBLAS_INLINE
end() const148     const_iterator end() const {
149         return const_iterator(*matrix_, matrix_->size1());
150     }
151 
152     BOOST_UBLAS_INLINE
cend() const153     const_iterator cend() const {
154         return end();
155     }
156 
157     BOOST_UBLAS_INLINE
rbegin()158     reverse_iterator rbegin() {
159         return reverse_iterator(end());
160     }
161 
162     BOOST_UBLAS_INLINE
rbegin() const163     const_reverse_iterator rbegin() const {
164         return const_reverse_iterator(end());
165     }
166 
167     BOOST_UBLAS_INLINE
crbegin() const168     const_reverse_iterator crbegin() const {
169         return rbegin();
170     }
171 
172     BOOST_UBLAS_INLINE
rend()173     reverse_iterator rend() {
174         return reverse_iterator(begin());
175     }
176 
177     BOOST_UBLAS_INLINE
rend() const178     const_reverse_iterator rend() const {
179         return const_reverse_iterator(begin());
180     }
181 
182     BOOST_UBLAS_INLINE
crend() const183     const_reverse_iterator crend() const {
184         return end();
185     }
186 
187     BOOST_UBLAS_INLINE
operator ()(size_type index)188     value_type operator()(size_type index) {
189         return value_type(*matrix_, index);
190     }
191 
192     BOOST_UBLAS_INLINE
operator ()(size_type index) const193     value_type operator()(size_type index) const {
194         return value_type(*matrix_, index);
195     }
196 
197     BOOST_UBLAS_INLINE
operator [](size_type index)198     reference operator[](size_type index){
199         return (*this) (index);
200     }
201 
202     BOOST_UBLAS_INLINE
operator [](size_type index) const203     const_reference operator[](size_type index) const {
204         return (*this) (index);
205     }
206 
207     BOOST_UBLAS_INLINE
size() const208     size_type size() const {
209         return matrix_->size1();
210     }
211 
212     BOOST_UBLAS_INLINE
resize(size_type size,bool preserve=true)213     void resize(size_type size, bool preserve = true) {
214         matrix_->resize(size, matrix_->size2(), preserve);
215     }
216 
217 private:
218     Matrix* matrix_;
219 };
220 
221 
222 /** \brief Convenience function to create \c matrix_row_vector.
223  *
224  * Function to create \c matrix_row_vector objects.
225  * \param matrix the \c matrix_expression that generates the matrix that \c matrix_row_vector is referring.
226  * \return Created \c matrix_row_vector object.
227  *
228  * \tparam Matrix the type of matrix that \c matrix_row_vector is referring.
229  */
230 template<class Matrix>
231 BOOST_UBLAS_INLINE
make_row_vector(matrix_expression<Matrix> & matrix)232 matrix_row_vector<Matrix> make_row_vector(matrix_expression<Matrix>& matrix){
233     return matrix_row_vector<Matrix>(matrix());
234 }
235 
236 
237 /** \brief Convenience function to create \c matrix_row_vector.
238  *
239  * Function to create \c matrix_row_vector objects.
240  * \param matrix the \c matrix_expression that generates the matrix that \c matrix_row_vector is referring.
241  * \return Created \c matrix_row_vector object.
242  *
243  * \tparam Matrix the type of matrix that \c matrix_row_vector is referring.
244  */
245 template<class Matrix>
246 BOOST_UBLAS_INLINE
make_row_vector(matrix_expression<Matrix> const & matrix)247 matrix_row_vector<Matrix const> make_row_vector(matrix_expression<Matrix> const& matrix){
248     return matrix_row_vector<Matrix const>(matrix());
249 }
250 
251 
252 /** \brief Represents a \c Matrix as a vector of columns.
253  *
254  * Implements an interface to Matrix that the underlaying matrix is represented as a
255  * vector of columns.
256  *
257  * The vector could be resized which causes the resize of the number of columns of
258  * the underlaying matrix.
259  */
260 template<class Matrix>
261 class matrix_column_vector {
262 public:
263     typedef ublas::matrix_column<Matrix> value_type;
264     typedef ublas::matrix_column<Matrix> reference;
265     typedef const ublas::matrix_column<Matrix const> const_reference;
266 
267     typedef ublas::detail::matrix_vector_iterator<Matrix, ublas::matrix_column<Matrix> > iterator;
268     typedef ublas::detail::matrix_vector_iterator<Matrix const, ublas::matrix_column<Matrix const> const > const_iterator;
269     typedef boost::reverse_iterator<iterator> reverse_iterator;
270     typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
271 
272     typedef typename boost::iterator_difference<iterator>::type difference_type;
273     typedef typename Matrix::size_type size_type;
274 
275     BOOST_UBLAS_INLINE
matrix_column_vector(Matrix & matrix)276     explicit matrix_column_vector(Matrix& matrix) :
277         matrix_(&matrix){
278     }
279 
280     BOOST_UBLAS_INLINE
begin()281     iterator begin() {
282         return iterator(*matrix_, 0);
283     }
284 
285     BOOST_UBLAS_INLINE
begin() const286     const_iterator begin() const {
287         return const_iterator(*matrix_, 0);
288     }
289 
290     BOOST_UBLAS_INLINE
cbegin() const291     const_iterator cbegin() const {
292         return begin();
293     }
294 
295     BOOST_UBLAS_INLINE
end()296     iterator end() {
297         return iterator(*matrix_, matrix_->size2());
298     }
299 
300     BOOST_UBLAS_INLINE
end() const301     const_iterator end() const {
302         return const_iterator(*matrix_, matrix_->size2());
303     }
304 
305     BOOST_UBLAS_INLINE
cend() const306     const_iterator cend() const {
307         return end();
308     }
309 
310     BOOST_UBLAS_INLINE
rbegin()311     reverse_iterator rbegin() {
312         return reverse_iterator(end());
313     }
314 
315     BOOST_UBLAS_INLINE
rbegin() const316     const_reverse_iterator rbegin() const {
317         return const_reverse_iterator(end());
318     }
319 
320     BOOST_UBLAS_INLINE
crbegin() const321     const_reverse_iterator crbegin() const {
322         return rbegin();
323     }
324 
325     BOOST_UBLAS_INLINE
rend()326     reverse_iterator rend() {
327         return reverse_iterator(begin());
328     }
329 
330     BOOST_UBLAS_INLINE
rend() const331     const_reverse_iterator rend() const {
332         return const_reverse_iterator(begin());
333     }
334 
335     BOOST_UBLAS_INLINE
crend() const336     const_reverse_iterator crend() const {
337         return rend();
338     }
339 
340     BOOST_UBLAS_INLINE
operator ()(size_type index)341     value_type operator()(size_type index) {
342         return value_type(*matrix_, index);
343     }
344 
345     BOOST_UBLAS_INLINE
operator ()(size_type index) const346     value_type operator()(size_type index) const {
347         return value_type(*matrix_, index);
348     }
349 
350     BOOST_UBLAS_INLINE
operator [](size_type index)351     reference operator[](size_type index) {
352         return (*this) (index);
353     }
354 
355     BOOST_UBLAS_INLINE
operator [](size_type index) const356     const_reference operator[](size_type index) const {
357         return (*this) (index);
358     }
359 
360     BOOST_UBLAS_INLINE
size() const361     size_type size() const {
362         return matrix_->size2();
363     }
364 
365     BOOST_UBLAS_INLINE
resize(size_type size,bool preserve=true)366     void resize(size_type size, bool preserve = true) {
367         matrix_->resize(matrix_->size1(), size, preserve);
368     }
369 
370 private:
371     Matrix* matrix_;
372 };
373 
374 
375 /** \brief Convenience function to create \c matrix_column_vector.
376  *
377  * Function to create \c matrix_column_vector objects.
378  * \param matrix the \c matrix_expression that generates the matrix that \c matrix_column_vector is referring.
379  * \return Created \c matrix_column_vector object.
380  *
381  * \tparam Matrix the type of matrix that \c matrix_column_vector is referring.
382  */
383 template<class Matrix>
384 BOOST_UBLAS_INLINE
make_column_vector(matrix_expression<Matrix> & matrix)385 matrix_column_vector<Matrix> make_column_vector(matrix_expression<Matrix>& matrix){
386     return matrix_column_vector<Matrix>(matrix());
387 }
388 
389 
390 /** \brief Convenience function to create \c matrix_column_vector.
391  *
392  * Function to create \c matrix_column_vector objects.
393  * \param matrix the \c matrix_expression that generates the matrix that \c matrix_column_vector is referring.
394  * \return Created \c matrix_column_vector object.
395  *
396  * \tparam Matrix the type of matrix that \c matrix_column_vector is referring.
397  */
398 template<class Matrix>
399 BOOST_UBLAS_INLINE
make_column_vector(matrix_expression<Matrix> const & matrix)400 matrix_column_vector<Matrix const> make_column_vector(matrix_expression<Matrix> const& matrix){
401     return matrix_column_vector<Matrix const>(matrix());
402 }
403 
404 }}}
405 
406 #endif
407