Ticket #7411: matrix_vector.hpp

File matrix_vector.hpp, 7.4 KB (added by Joaquim Duran Comas <jduran.gm@…>, 9 years ago)
Line 
1#ifndef BOOST_UBLAS_MATRIX_VECTOR_HPP
2#define BOOST_UBLAS_MATRIX_VECTOR_HPP
3
4#include <boost/numeric/ublas/matrix_proxy.hpp>//for matrix_row, matrix_column and matrix_expression
5#include <boost/numeric/ublas/vector.hpp>
6#include <boost/iterator/iterator_facade.hpp>
7#include <boost/range/iterator_range.hpp>
8#include <boost/type_traits/is_convertible.hpp>
9#include <boost/utility/enable_if.hpp>
10
11namespace boost { namespace numeric { namespace ublas {
12
13namespace detail{
14/// \brief Iterator which represents a matrix as a range of row/column-vectors
15///
16/// The second argument is the reference to a matrix_row/matrix_column.
17/// Whatever type used, it must offer a constructor Reference(sequence,i)
18/// which constructs a reference to the i-th proxy-element
19/// This iterator is invalidated when the underlying matrix is resized.
20template<class Matrix, class Reference>
21struct matrix_vector_iterator: public boost::iterator_facade<
22 matrix_vector_iterator<Matrix,Reference>,
23 typename vector_temporary_traits<Reference>::type,
24 boost::random_access_traversal_tag,
25 Reference
26>{
27public:
28 matrix_vector_iterator(){}
29
30 ///\brief constructs a matrix_vector_iterator as pointing to the i-th proxy
31 matrix_vector_iterator(Matrix& matrix, std::size_t position)
32 : matrix_(&matrix),position_(position) {}
33
34 template<class M, class R>
35 matrix_vector_iterator(matrix_vector_iterator<M,R> const& other)
36 : matrix_(other.matrix_),position_(other.position_) {}
37
38private:
39 friend class boost::iterator_core_access;
40 template <class M,class R> friend class matrix_vector_iterator;
41
42 void increment() {
43 ++position_;
44 }
45 void decrement() {
46 --position_;
47 }
48
49 void advance(std::ptrdiff_t n){
50 position_ += n;
51 }
52
53 template<class M,class R>
54 std::ptrdiff_t distance_to(matrix_vector_iterator<M,R> const& other) const{
55 BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ());
56 return (std::ptrdiff_t)other.position_ - (std::ptrdiff_t)position_;
57 }
58
59 template<class M,class R>
60 bool equal(matrix_vector_iterator<M,R> const& other) const{
61 BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ());
62 return (position_ == other.position_);
63 }
64 Reference dereference() const {
65 return Reference(*matrix_,position_);
66 }
67
68 Matrix* matrix_;//no matrix_closure here to ensure easy usage
69 std::size_t position_;
70};
71
72}
73
74///\brief Represents a Matrix as a vector of rows.
75template<class Matrix>
76class matrix_row_vector {
77public:
78 typedef ublas::matrix_row<Matrix> value_type;
79 typedef ublas::matrix_row<Matrix> reference;
80 typedef ublas::matrix_row<Matrix const> const_reference;
81
82 typedef ublas::detail::matrix_vector_iterator<Matrix, ublas::matrix_row<Matrix> > iterator;
83 typedef ublas::detail::matrix_vector_iterator<Matrix const, ublas::matrix_row<Matrix const> const> const_iterator;
84 typedef boost::reverse_iterator<iterator> reverse_iterator;
85 typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
86
87 typedef typename boost::iterator_difference<iterator>::type difference_type;
88 typedef typename Matrix::size_type size_type;
89
90 matrix_row_vector(Matrix& matrix) :
91 m_matrix(matrix) {
92 }
93
94
95 iterator begin(){
96 return iterator(m_matrix, 0);
97 }
98
99 const_iterator begin() const {
100 return const_iterator(m_matrix, 0);
101 }
102
103 iterator end() {
104 return iterator(m_matrix, m_matrix.size1());
105 }
106
107 const_iterator end() const {
108 return const_iterator(m_matrix, m_matrix.size1());
109 }
110
111 reverse_iterator rbegin() {
112 return reverse_iterator(end());
113 }
114
115 const_reverse_iterator rbegin() const {
116 return const_reverse_iterator(end());
117 }
118
119 reverse_iterator rend() {
120 return reverse_iterator(begin());
121 }
122
123 const_reverse_iterator rend() const {
124 return const_reverse_iterator(begin());
125 }
126
127
128 value_type operator()(difference_type index) const {
129 return value_type(m_matrix, index);
130 }
131
132 reference operator[](difference_type index){
133 return reference(m_matrix, index);
134 }
135
136 const_reference operator[](difference_type index) const {
137 return const_reference(m_matrix, index);
138 }
139
140 size_type size() const {
141 return m_matrix.size1();
142 }
143
144 void resize(size_type size, bool preserve = true) {
145 m_matrix.resize(size, m_matrix.size2(), preserve);
146 }
147
148private:
149 Matrix& m_matrix;
150};
151
152
153///\brief convenience function to create matrix_row_vector.
154template<class Matrix>
155matrix_row_vector<Matrix> make_row_vector(matrix_expression<Matrix>& matrix){
156 return matrix_row_vector<Matrix>(matrix());
157}
158
159
160///\brief convenience function to create matrix_row_vector.
161template<class Matrix>
162matrix_row_vector<Matrix const> make_row_vector(matrix_expression<Matrix> const& matrix){
163 return matrix_row_vector<Matrix const>(matrix());
164}
165
166
167///\brief Represents a Matrix as a vector of rows.
168template<class Matrix>
169class matrix_column_vector
170{
171public:
172 typedef ublas::matrix_column<Matrix> value_type;
173 typedef ublas::matrix_column<Matrix> reference;
174 typedef const ublas::matrix_column<Matrix const> const_reference;
175
176 typedef ublas::detail::matrix_vector_iterator<Matrix, ublas::matrix_column<Matrix> > iterator;
177 typedef ublas::detail::matrix_vector_iterator<Matrix const, ublas::matrix_column<Matrix const> const > const_iterator;
178 typedef boost::reverse_iterator<iterator> reverse_iterator;
179 typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
180
181 typedef typename boost::iterator_difference<iterator>::type difference_type;
182 typedef typename Matrix::size_type size_type;
183
184 matrix_column_vector(Matrix& matrix) :
185 m_matrix(matrix){
186 }
187
188 iterator begin() {
189 return iterator(m_matrix, 0);
190 }
191
192 const_iterator begin() const {
193 return const_iterator(m_matrix, 0);
194 }
195
196 iterator end() {
197 return iterator(m_matrix, m_matrix.size2());
198 }
199
200 const_iterator end() const {
201 return const_iterator(m_matrix, m_matrix.size2());
202 }
203
204 reverse_iterator rbegin() {
205 return reverse_iterator(end());
206 }
207
208 const_reverse_iterator rbegin() const {
209 return const_reverse_iterator(end());
210 }
211
212 reverse_iterator rend() {
213 return reverse_iterator(begin());
214 }
215
216 const_reverse_iterator rend() const {
217 return const_reverse_iterator(begin());
218 }
219
220 value_type operator()(difference_type index) const
221 {
222 return value_type(m_matrix, index);
223 }
224
225 reference operator[](difference_type index) {
226 return reference(m_matrix, index);
227 }
228
229 const_reference operator[](difference_type index) const {
230 return const_reference(m_matrix, index);
231 }
232
233 size_type size() const {
234 return m_matrix.size2();
235 }
236
237 void resize(size_type size, bool preserve = true) {
238 m_matrix.resize(m_matrix.size1(), size, preserve);
239 }
240
241private:
242 Matrix& m_matrix;
243};
244
245
246///\brief convenience function to create matrix_column_vector.
247template<class Matrix>
248matrix_column_vector<Matrix> make_column_vector(matrix_expression<Matrix>& matrix){
249 return matrix_column_vector<Matrix>(matrix());
250}
251
252
253///\brief convenience function to create matrix_column_vector.
254template<class Matrix>
255matrix_column_vector<Matrix const> make_column_vector(matrix_expression<Matrix> const& matrix){
256 return matrix_column_vector<Matrix const>(matrix());
257}
258
259}}}
260
261#endif