matrix_proxy.hpp
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Matrix proxy expressions
5  *
6  *
7  *
8  * \author O. Krause
9  * \date 2016
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 #ifndef REMORA_MATRIX_PROXY_HPP
34 #define REMORA_MATRIX_PROXY_HPP
35 
36 #include "detail/expression_optimizers.hpp"
37 #include <type_traits>
38 namespace remora{
39 
40 
41 ////////////////////////////////////
42 //// Matrix Transpose
43 ////////////////////////////////////
44 
45 /// \brief Returns a proxy which transposes the matrix
46 ///
47 /// given a matrix
48 /// A = (1 2 3)
49 /// (4 5 6)
50 /// (7 8 9)
51 ///
52 /// the trans(A) operation results in
53 /// trans(A) = (1 4 7)
54 /// (2 5 8)
55 /// (3 6 9)
56 template<class M, class Device>
57 temporary_proxy<typename detail::matrix_transpose_optimizer<M>::type>
58 trans(matrix_expression<M, Device> & m){
59  return detail::matrix_transpose_optimizer<M>::create(m());
60 }
61 template<class M, class Device>
62 typename detail::matrix_transpose_optimizer<typename const_expression<M>::type >::type
63 trans(matrix_expression<M, Device> const& m){
64  typedef typename const_expression<M>::type closure_type;
65  return detail::matrix_transpose_optimizer<closure_type>::create(m());
66 }
67 
68 template<class M>
69 temporary_proxy<typename detail::matrix_transpose_optimizer<M>::type>
70 trans(temporary_proxy<M> m){
71  return trans(static_cast<M&>(m));
72 }
73 
74 ////////////////////////////////////
75 //// Matrix Row and Column
76 ////////////////////////////////////
77 
78 /// \brief Returns a vector-proxy representing the i-th row of the Matrix
79 ///
80 /// given a matrix
81 /// A = (1 2 3)
82 /// (4 5 6)
83 /// (7 8 9)
84 ///
85 /// the row(A,1) operation results in
86 /// row(A,1) = (4,5,6)
87 template<class M, class Device>
88 temporary_proxy<typename detail::matrix_row_optimizer<M>::type>
89 row(matrix_expression<M, Device>& expression, typename M::size_type i){
90  return detail::matrix_row_optimizer<M>::create(expression(), i);
91 }
92 template<class M, class Device>
93 typename detail::matrix_row_optimizer<typename const_expression<M>::type>::type
94 row(matrix_expression<M, Device> const& expression, typename M::size_type i){
95  return detail::matrix_row_optimizer<typename const_expression<M>::type>::create(expression(), i);
96 }
97 
98 template<class M>
99 temporary_proxy<typename detail::matrix_row_optimizer<M>::type>
100 row(temporary_proxy<M> expression, typename M::size_type i){
101  return row(static_cast<M&>(expression), i);
102 }
103 
104 /// \brief Returns a vector-proxy representing the j-th column of the Matrix
105 ///
106 /// given a matrix
107 /// A = (1 2 3)
108 /// (4 5 6)
109 /// (7 8 9)
110 ///
111 /// the column(A,1) operation results in
112 /// column(A,1) = (2,5,8)
113 template<class M, class Device>
114 auto column(matrix_expression<M, Device>& expression, typename M::size_type j) -> decltype(row(trans(expression),j)){
115  return row(trans(expression),j);
116 }
117 template<class M, class Device>
118 auto column(matrix_expression<M, Device> const& expression, typename M::size_type j) -> decltype(row(trans(expression),j)){
119  return row(trans(expression),j);
120 }
121 
122 template<class M, class Device>
123 auto column(temporary_proxy<M> expression, typename M::size_type j) -> decltype(row(trans(expression),j)){
124  return row(trans(static_cast<M&>(expression)),j);
125 }
126 
127 ////////////////////////////////////
128 //// Matrix Diagonal
129 ////////////////////////////////////
130 
131 ///\brief Returns the diagonal of a constant square matrix as vector.
132 ///
133 /// given a matrix
134 /// A = (1 2 3)
135 /// (4 5 6)
136 /// (7 8 9)
137 ///
138 /// the diag operation results in
139 /// diag(A) = (1,5,9)
140 template<class M, class Device>
141 matrix_vector_range<typename const_expression<M>::type > diag(matrix_expression<M, Device> const& mat){
142  REMORA_SIZE_CHECK(mat().size1() == mat().size2());
143  matrix_vector_range<typename const_expression<M>::type > diagonal(mat(),0,mat().size1(),0,mat().size1());
144  return diagonal;
145 }
146 
147 template<class M, class Device>
148 temporary_proxy< matrix_vector_range<M> > diag(matrix_expression<M, Device>& mat){
149  REMORA_SIZE_CHECK(mat().size1() == mat().size2());
150  matrix_vector_range<M> diagonal(mat(),0,mat().size1(),0,mat().size1());
151  return diagonal;
152 }
153 
154 template<class M>
155 temporary_proxy< matrix_vector_range<M> > diag(temporary_proxy<M> mat){
156  return diag(static_cast<M&>(mat));
157 }
158 
159 
160 ////////////////////////////////////
161 //// Matrix Subranges
162 ////////////////////////////////////
163 
164 
165 ///\brief Returns a submatrix of a given matrix.
166 ///
167 /// given a matrix
168 /// A = (1 2 3)
169 /// (4 5 6)
170 /// (7 8 9)
171 ///
172 /// the subrange(A,0,2,1,3) operation results in
173 /// subrange(A,0,2,1,3) = (4 5)
174 /// (7 8)
175 template<class M, class Device>
176 temporary_proxy< typename detail::matrix_range_optimizer<M>::type > subrange(
177  matrix_expression<M, Device>& expression,
178  std::size_t start1, std::size_t stop1,
179  std::size_t start2, std::size_t stop2
180 ){
181  REMORA_RANGE_CHECK(start1 <= stop1);
182  REMORA_RANGE_CHECK(start2 <= stop2);
183  REMORA_SIZE_CHECK(stop1 <= expression().size1());
184  REMORA_SIZE_CHECK(stop2 <= expression().size2());
185  return detail::matrix_range_optimizer<M>::create(expression(), start1, stop1, start2, stop2);
186 }
187 template<class M, class Device>
188 typename detail::matrix_range_optimizer<typename const_expression<M>::type>::type subrange(
189  matrix_expression<M, Device> const& expression,
190  std::size_t start1, std::size_t stop1,
191  std::size_t start2, std::size_t stop2
192 ){
193  REMORA_RANGE_CHECK(start1 <= stop1);
194  REMORA_RANGE_CHECK(start2 <= stop2);
195  REMORA_SIZE_CHECK(stop1 <= expression().size1());
196  REMORA_SIZE_CHECK(stop2 <= expression().size2());
197  return detail::matrix_range_optimizer<typename const_expression<M>::type>::create(expression(), start1, stop1, start2, stop2);
198 }
199 
200 template<class M, class Device>
201 auto subrange(
202  temporary_proxy<M> expression,
203  std::size_t start1, std::size_t stop1,
204  std::size_t start2, std::size_t stop2
205 ) -> decltype(subrange(static_cast<M&>(expression),start1,stop1,start2,stop2)){
206  return subrange(static_cast<M&>(expression),start1,stop1,start2,stop2);
207 }
208 
209 template<class M, class Device>
210 auto rows(
211  matrix_expression<M, Device>& expression,
212  std::size_t start, std::size_t stop
213 ) -> decltype(subrange(expression, start, stop, 0,expression().size2())){
214  REMORA_RANGE_CHECK(start <= stop);
215  REMORA_SIZE_CHECK(stop <= expression().size1());
216  return subrange(expression, start, stop, 0,expression().size2());
217 }
218 
219 template<class M, class Device>
220 auto rows(
221  matrix_expression<M, Device> const& expression,
222  std::size_t start, std::size_t stop
223 ) -> decltype(subrange(expression, start, stop, 0,expression().size2())){
224  REMORA_RANGE_CHECK(start <= stop);
225  REMORA_SIZE_CHECK(stop <= expression().size1());
226  return subrange(expression, start, stop, 0,expression().size2());
227 }
228 
229 template<class M>
230 auto rows(
231  temporary_proxy<M> expression,
232  std::size_t start, std::size_t stop
233 ) -> decltype( rows(static_cast<M&>(expression),start,stop)){
234  return rows(static_cast<M&>(expression),start,stop);
235 }
236 
237 template<class M, class Device>
238 auto columns(
239  matrix_expression<M, Device>& expression,
240  typename M::size_type start, typename M::size_type stop
241 ) -> decltype(subrange(expression, 0,expression().size1(), start, stop)){
242  REMORA_RANGE_CHECK(start <= stop);
243  REMORA_SIZE_CHECK(stop <= expression().size2());
244  return subrange(expression, 0,expression().size1(), start, stop);
245 }
246 
247 template<class M, class Device>
248 auto columns(
249  matrix_expression<M, Device> const& expression,
250  typename M::size_type start, typename M::size_type stop
251 ) -> decltype(subrange(expression, 0,expression().size1(), start, stop)){
252  REMORA_RANGE_CHECK(start <= stop);
253  REMORA_SIZE_CHECK(stop <= expression().size2());
254  return subrange(expression, 0,expression().size1(), start, stop);
255 }
256 
257 template<class M>
258 auto columns(
259  temporary_proxy<M> expression,
260  std::size_t start, std::size_t stop
261 ) -> decltype(columns(static_cast<M&>(expression),start,stop)){
262  return columns(static_cast<M&>(expression),start,stop);
263 }
264 
265 ////////////////////////////////////
266 //// Matrix Adaptor
267 ////////////////////////////////////
268 
269 /// \brief Converts a chunk of memory into a matrix of given size.
270 template <class T>
271 temporary_proxy< dense_matrix_adaptor<T> > adapt_matrix(std::size_t size1, std::size_t size2, T* data){
272  return dense_matrix_adaptor<T>(data,size1, size2);
273 }
274 
275 /// \brief Converts a 2D C-style array into a matrix of given size.
276 template <class T, std::size_t M, std::size_t N>
277 temporary_proxy<dense_matrix_adaptor<T> > adapt_matrix(T (&array)[M][N]){
278  return dense_matrix_adaptor<T>(&(array[0][0]),M,N);
279 }
280 
281 /// \brief Converts a dense vector to a matrix of a given size
282 template <class V, class Tag>
283 typename std::enable_if<
284  std::is_same<typename V::storage_type::storage_tag,continuous_dense_tag>::value,
285  temporary_proxy< dense_matrix_adaptor<
286  typename std::remove_reference<typename V::reference>::type,row_major, Tag
287  > >
288 >::type
289 to_matrix(
290  vector_expression<V, Tag>& v,
291  std::size_t size1, std::size_t size2
292 ){
293  REMORA_SIZE_CHECK(size1 * size2 == v().size());
294  typedef typename std::remove_reference<typename V::reference>::type ElementType;
295  return dense_matrix_adaptor<ElementType, row_major, Tag>(v, size1, size2);
296 }
297 
298 /// \brief Converts a dense vector to a matrix of a given size
299 template <class V, class Tag>
300 typename std::enable_if<
301  std::is_same<typename V::storage_type::storage_tag,continuous_dense_tag>::value,
302  temporary_proxy< dense_matrix_adaptor<typename V::value_type const,row_major, Tag> >
303 >::type
304 to_matrix(
305  vector_expression<V, Tag> const& v,
306  std::size_t size1, std::size_t size2
307 ){
308  REMORA_SIZE_CHECK(size1 * size2 == v().size());
309  return dense_matrix_adaptor<typename V::value_type const, row_major, Tag>(v, size1, size2);
310 }
311 
312 template<class E>
313 auto to_matrix(temporary_proxy<E> e, std::size_t size1, std::size_t size2)->decltype(to_matrix(static_cast<E&>(e),size1, size2)){
314  return to_matrix(static_cast<E&>(e), size1, size2);
315 }
316 
317 /// \brief Converts a dense matrix to a vector
318 ///
319 /// The matrix is linearized along its fast index as indicated by the orientation.
320 /// e.g. a row-major matrix is lienarized by concatenating its rows to one large vector.
321 template<class E, class Device>
322 typename std::enable_if<
323  std::is_same<typename E::evaluation_category::tag,dense_tag>::value,
324  temporary_proxy< linearized_matrix<typename const_expression<E>::type> >
325 >::type
326 to_vector(matrix_expression<E, Device> const& e){
327  return linearized_matrix<typename const_expression<E>::type>(e());
328 }
329 
330 template<class E, class Device>
331 typename std::enable_if<
332  std::is_same<typename E::evaluation_category::tag,dense_tag>::value,
333  temporary_proxy< linearized_matrix<E> >
334 >::type
335 to_vector(matrix_expression<E,Device>& e){
336  return linearized_matrix<E>(e());
337 }
338 
339 template<class E>
340 auto to_vector(temporary_proxy<E> e)->decltype(to_vector(static_cast<E&>(e))){
341  return to_vector(static_cast<E&>(e));
342 }
343 
344 }
345 
346 #endif