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