proxy_expressions.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/proxy_optimizers_fwd.hpp"
37#include "detail/vector_set.hpp"
38#include "expression_types.hpp"
39#include "detail/traits.hpp"
40#include "detail/check.hpp"
41namespace remora{
42
43
44// ------------------
45// Vector subrange
46// ------------------
47
48/// \brief Return a subrange of a specified vector, forming a vector for the specified indices between start and stop index.
49///
50/// The vector starts with first index being 0 for the element that is indexed with start in the original vector.
51template<class V, class Device>
52typename detail::vector_range_optimizer<typename V::closure_type >::type
53subrange(vector_expression<V, Device>& v, std::size_t start, std::size_t stop){
54 return detail::vector_range_optimizer<typename V::closure_type>::create(v(), start, stop);
55}
56
57template<class V, class Device>
58typename detail::vector_range_optimizer<typename V::const_closure_type>::type
59subrange(vector_expression<V, Device> const& v, std::size_t start, std::size_t stop){
60 return detail::vector_range_optimizer<typename V::const_closure_type>::create(v(), start, stop);
61}
62
63template<class V, class Device>
64typename detail::vector_range_optimizer<typename V::closure_type>::type
65subrange(vector_expression<V,Device>&& v, std::size_t start, std::size_t stop){
66 static_assert(!std::is_base_of<vector_container<V, Device>,V>::value, "It is unsafe to create a proxy from a temporary container");
67 return subrange(v(),start,stop);
68}
69
70
71////////////////////////////////////
72//// Matrix Transpose
73////////////////////////////////////
74
75/// \brief Returns a proxy which transposes the matrix
76///
77/// given a matrix
78/// A = (1 2 3)
79/// (4 5 6)
80/// (7 8 9)
81///
82/// the trans(A) operation results in
83/// trans(A) = (1 4 7)
84/// (2 5 8)
85/// (3 6 9)
86template<class M, class Device>
87typename detail::matrix_transpose_optimizer<typename M::closure_type>::type
88trans(matrix_expression<M, Device> & m){
89 return detail::matrix_transpose_optimizer<typename M::closure_type>::create(m());
90}
91template<class M, class Device>
92typename detail::matrix_transpose_optimizer<typename M::const_closure_type>::type
93trans(matrix_expression<M, Device> const& m){
94 return detail::matrix_transpose_optimizer<typename M::const_closure_type>::create(m());
95}
96
97template<class M, class Device>
98typename detail::matrix_transpose_optimizer<typename M::closure_type>::type
99trans(matrix_expression<M, Device> && m){
100 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
101 return trans(m());
102}
103
104////////////////////////////////////
105//// Matrix Row and Column
106////////////////////////////////////
107
108/// \brief Returns a vector-proxy representing the i-th row of the Matrix
109///
110/// given a matrix
111/// A = (1 2 3)
112/// (4 5 6)
113/// (7 8 9)
114///
115/// the row(A,1) operation results in
116/// row(A,1) = (4,5,6)
117template<class M, class Device>
118typename detail::matrix_row_optimizer<typename M::closure_type>::type
119row(matrix_expression<M, Device>& m, typename M::size_type i){
120 return detail::matrix_row_optimizer<typename M::closure_type>::create(m(), i);
121}
122template<class M, class Device>
123typename detail::matrix_row_optimizer<typename M::const_closure_type>::type
124row(matrix_expression<M, Device> const& m, typename M::size_type i){
125 return detail::matrix_row_optimizer<typename M::const_closure_type>::create(m(), i);
126}
127
128template<class M, class Device>
129typename detail::matrix_row_optimizer<typename M::closure_type>::type
130row(matrix_expression<M, Device> && m, typename M::size_type i){
131 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
132 return row(m,i);
133}
134
135/// \brief Returns a vector-proxy representing the j-th column of the Matrix
136///
137/// given a matrix
138/// A = (1 2 3)
139/// (4 5 6)
140/// (7 8 9)
141///
142/// the column(A,1) operation results in
143/// column(A,1) = (2,5,8)
144template<class M, class Device>
145auto column(matrix_expression<M, Device>& m, typename M::size_type j) -> decltype(row(trans(m),j)){
146 return row(trans(m),j);
147}
148template<class M, class Device>
149auto column(matrix_expression<M, Device> const& m, typename M::size_type j) -> decltype(row(trans(m),j)){
150 return row(trans(m),j);
151}
152
153template<class M, class Device>
154auto column(matrix_expression<M, Device> && m, typename M::size_type j) -> decltype(row(trans(m),j)){
155 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
156 return column(m());
157}
158
159////////////////////////////////////
160//// Matrix Diagonal
161////////////////////////////////////
162
163///\brief Returns the diagonal of a constant square matrix as vector.
164///
165/// given a matrix
166/// A = (1 2 3)
167/// (4 5 6)
168/// (7 8 9)
169///
170/// the diag operation results in
171/// diag(A) = (1,5,9)
172template<class M, class Device>
173typename detail::matrix_diagonal_optimizer<typename M::closure_type>::type
174diag(matrix_expression<M, Device>& mat){
175 REMORA_SIZE_CHECK(mat().size1() == mat().size2());
176 return detail::matrix_diagonal_optimizer<typename M::closure_type>::create(mat());
177}
178
179template<class M, class Device>
180typename detail::matrix_diagonal_optimizer<typename M::const_closure_type>::type
181diag(matrix_expression<M, Device> const& mat){
182 REMORA_SIZE_CHECK(mat().size1() == mat().size2());
183 return detail::matrix_diagonal_optimizer<typename M::const_closure_type>::create(mat());
184}
185
186
187template<class M, class Device>
188typename detail::matrix_diagonal_optimizer<typename M::closure_type>::type
189diag(matrix_expression<M, Device> && m){
190 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
191 return diag(m());
192}
193
194////////////////////////////////////
195//// Matrix Subranges
196////////////////////////////////////
197
198
199///\brief Returns a submatrix of a given matrix.
200///
201/// given a matrix
202/// A = (1 2 3)
203/// (4 5 6)
204/// (7 8 9)
205///
206/// the subrange(A,0,2,1,3) operation results in
207/// subrange(A,0,2,1,3) = (4 5)
208/// (7 8)
209template<class M, class Device>
210typename detail::matrix_range_optimizer<typename M::closure_type>::type subrange(
211 matrix_expression<M, Device>& m,
212 std::size_t start1, std::size_t stop1,
213 std::size_t start2, std::size_t stop2
214){
215 REMORA_RANGE_CHECK(start1 <= stop1);
216 REMORA_RANGE_CHECK(start2 <= stop2);
217 REMORA_SIZE_CHECK(stop1 <= m().size1());
218 REMORA_SIZE_CHECK(stop2 <= m().size2());
219 return detail::matrix_range_optimizer<typename M::closure_type>::create(m(), start1, stop1, start2, stop2);
220}
221template<class M, class Device>
222typename detail::matrix_range_optimizer<typename M::const_closure_type>::type subrange(
223 matrix_expression<M, Device> const& m,
224 std::size_t start1, std::size_t stop1,
225 std::size_t start2, std::size_t stop2
226){
227 REMORA_RANGE_CHECK(start1 <= stop1);
228 REMORA_RANGE_CHECK(start2 <= stop2);
229 REMORA_SIZE_CHECK(stop1 <= m().size1());
230 REMORA_SIZE_CHECK(stop2 <= m().size2());
231 return detail::matrix_range_optimizer<typename M::const_closure_type>::create(m(), start1, stop1, start2, stop2);
232}
233
234template<class M, class Device>
235typename detail::matrix_range_optimizer<typename M::closure_type>::type subrange(
236 matrix_expression<M, Device> && m,
237 std::size_t start1, std::size_t stop1,
238 std::size_t start2, std::size_t stop2
239){
240 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
241 return subrange(m(),start1,stop1,start2,stop2);
242}
243
244template<class M, class Device>
245typename detail::matrix_rows_optimizer<typename M::closure_type>::type rows(
246 matrix_expression<M, Device>& m,
247 std::size_t start, std::size_t stop
248){
249 REMORA_RANGE_CHECK(start <= stop);
250 REMORA_SIZE_CHECK(stop <= m().size1());
251 return detail::matrix_rows_optimizer<typename M::closure_type>::create(m(),start,stop);
252}
253
254template<class M, class Device>
255typename detail::matrix_rows_optimizer<typename M::const_closure_type >::type rows(
256 matrix_expression<M, Device> const& m,
257 std::size_t start, std::size_t stop
258){
259 REMORA_RANGE_CHECK(start <= stop);
260 REMORA_SIZE_CHECK(stop <= m().size1());
261 return detail::matrix_rows_optimizer<typename M::const_closure_type >::create(m(),start,stop);
262}
263
264template<class M, class Device>
265typename detail::matrix_rows_optimizer<typename M::closure_type >::type rows(
266 matrix_expression<M, Device> && m,
267 std::size_t start, std::size_t stop
268) {
269 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
270 return detail::matrix_rows_optimizer<typename M::closure_type>::create(m(),start,stop);
271}
272
273template<class M, class Device>
274auto columns(
275 matrix_expression<M, Device>& m,
276 typename M::size_type start, typename M::size_type stop
277) -> decltype(trans(rows(trans(m),start,stop))){
278 REMORA_RANGE_CHECK(start <= stop);
279 REMORA_SIZE_CHECK(stop <= m().size2());
280 return trans(rows(trans(m),start,stop));
281}
282
283template<class M, class Device>
284auto columns(
285 matrix_expression<M, Device> const& m,
286 typename M::size_type start, typename M::size_type stop
287) -> decltype(trans(rows(trans(m),start,stop))){
288 REMORA_RANGE_CHECK(start <= stop);
289 REMORA_SIZE_CHECK(stop <= m().size2());
290 return trans(rows(trans(m),start,stop));
291}
292
293template<class M, class Device>
294auto columns(
295 matrix_expression<M, Device> && m,
296 std::size_t start, std::size_t stop
297) -> decltype(trans(rows(trans(m),start,stop))){
298 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
299 return columns(m(),start,stop);
300}
301
302////////////////////////////////////
303//// Matrix to Vector
304////////////////////////////////////
305
306/// \brief Converts a dense matrix to a vector
307///
308/// The matrix is linearized along its fast index as indicated by the orientation.
309/// m.g. a row-major matrix is lienarized by concatenating its rows to one large vector.
310template<class M, class Device>
311typename detail::linearized_matrix_optimizer<typename M::closure_type>::type
312to_vector(matrix_expression<M, Device>& m){
313 return detail::linearized_matrix_optimizer<typename M::closure_type>::create(m());
314}
315
316template<class M, class Device>
317typename detail::linearized_matrix_optimizer<typename M::const_closure_type>::type
318to_vector(matrix_expression<M, Device> const& m){
319 return detail::linearized_matrix_optimizer<typename M::const_closure_type>::create(m());
320}
321
322template<class M, class Device>
323typename detail::linearized_matrix_optimizer<typename M::closure_type>::type
324to_vector(matrix_expression<M, Device> && m){
325 static_assert(!std::is_base_of<vector_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
326 return to_vector(m());
327}
328
329
330////////////////////////////////////////////////
331//// Matrix to Triangular Matrix
332////////////////////////////////////////////////
333
334template <class M, class Device, class Tag>
335typename detail::triangular_proxy_optimizer<typename M::closure_type, Tag>::type
336to_triangular(matrix_expression<M, Device>& m, Tag){
337 return detail::triangular_proxy_optimizer<typename M::closure_type, Tag>::create(m());
338}
339
340template <class M, class Device, class Tag>
341typename detail::triangular_proxy_optimizer<typename M::const_closure_type, Tag>::type
342to_triangular(matrix_expression<M, Device> const& m, Tag){
343 return detail::triangular_proxy_optimizer<typename M::const_closure_type, Tag>::create(m());
344}
345
346template <class M, class Device, class Tag>
347typename detail::triangular_proxy_optimizer<typename M::closure_type, Tag>::type
348to_triangular(matrix_expression<M, Device>&& m, Tag){
349 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
350 return detail::triangular_proxy_optimizer<typename M::closure_type, Tag>::create(m());
351}
352
353////////////////////////////////////
354//// Matrix Adaptor
355////////////////////////////////////
356
357/// \brief Converts a dense vector to a matrix of a given size
358template <class V, class Device>
359typename detail::vector_to_matrix_optimizer<typename V::const_closure_type, row_major >::type to_matrix(
360 vector_expression<V, Device> const& v,std::size_t size1, std::size_t size2
361){
362 REMORA_SIZE_CHECK(size1 * size2 == v().size());
363 return detail::vector_to_matrix_optimizer<typename V::const_closure_type, row_major >::create(v(), size1, size2);
364}
365
366/// \brief Converts a dense vector to a matrix of a given size
367template <class V, class Device>
368typename detail::vector_to_matrix_optimizer<typename V::closure_type, row_major >::type to_matrix(
369 vector_expression<V, Device>& v,std::size_t size1, std::size_t size2
370){
371 REMORA_SIZE_CHECK(size1 * size2 == v().size());
372 return detail::vector_to_matrix_optimizer<typename V::closure_type, row_major >::create(v(), size1, size2);
373}
374
375template <class V, class Device>
376typename detail::vector_to_matrix_optimizer<typename V::closure_type, row_major >::type to_matrix(
377 vector_expression<V,Device> && v,std::size_t size1, std::size_t size2
378){
379 static_assert(!std::is_base_of<vector_container<V, Device>,V>::value, "It is unsafe to create a proxy from a temporary container");
380 return to_matrix(v, size1, size2);
381}
382
383////////////////////////////////////
384//// Matrix to vector set
385////////////////////////////////////
386
387template <class O, class M, class Device>
388vector_set<typename M::const_closure_type, O >
389as_set(matrix_expression<M, Device> const& m, O){
390 return vector_set<typename M::const_closure_type, O >(m());
391}
392
393template <class O, class M, class Device>
394vector_set<typename M::closure_type, O >
395as_set(matrix_expression<M, Device>& m, O){
396 return vector_set<typename M::closure_type, O >(m());
397}
398
399template <class O, class M, class Device>
400vector_set<typename M::closure_type, O >
401as_set(matrix_expression<M, Device>&& m, O){
402 static_assert(!std::is_base_of<matrix_container<M, Device>,M>::value, "It is unsafe to create a proxy from a temporary container");
403 return vector_set<typename M::closure_type, O >(m());
404}
405
406/// \brief Transforms the matrix m to a set of points where each point is one row of m
407template <class M>
408auto as_rows(M&& m)-> decltype(as_set(std::forward<M>(m), row_major())){
409 return as_set(std::forward<M>(m), row_major());
410}
411
412/// \brief Transforms the matrix m to a set of points where each point is one column of m
413template <class M>
414auto as_columns(M&& m)-> decltype(as_set(std::forward<M>(m), column_major())){
415 return as_set(std::forward<M>(m), column_major());
416}
417
418}
419
420#endif