solve.hpp
Go to the documentation of this file.
1 /*!
2  * \brief Defines types for matrix decompositions
3  *
4  * \author O. Krause
5  * \date 2016
6  *
7  *
8  * \par Copyright 1995-2015 Shark Development Team
9  *
10  * <BR><HR>
11  * This file is part of Shark.
12  * <http://image.diku.dk/shark/>
13  *
14  * Shark is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License as published
16  * by the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * Shark is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
26  *
27  */
28 #ifndef REMORA_SOLVE_HPP
29 #define REMORA_SOLVE_HPP
30 
31 #include "decompositions.hpp"
32 
33 namespace remora{
34 
35 
36 //////////////////////////////////////////////////////
37 ////////Expression Types for Solving and inverse
38 //////////////////////////////////////////////////////
39 
40 template<class MatA, class VecV, class SystemType, class Side>
41 class matrix_vector_solve: public vector_expression<
42  matrix_vector_solve<MatA, VecV,SystemType, Side>,
43  typename MatA::device_type
44 >{
45 public:
46  typedef typename MatA::const_closure_type matrix_closure_type;
47  typedef typename VecV::const_closure_type vector_closure_type;
48  typedef decltype(
49  typename MatA::value_type() * typename VecV::value_type()
50  ) value_type;
51  typedef typename MatA::size_type size_type;
52  typedef value_type const_reference;
53  typedef const_reference reference;
54 
55  typedef matrix_vector_solve const_closure_type;
56  typedef const_closure_type closure_type;
57  typedef unknown_storage storage_type;
58  typedef unknown_storage const_storage_type;
59  typedef blockwise<dense_tag> evaluation_category;
60  typedef typename MatA::device_type device_type;
61 
62  size_type size() const {
63  return m_rhs.size();
64  }
65  typename device_traits<device_type>::queue_type& queue()const{
66  return m_matrix.queue();
67  }
68  matrix_vector_solve(
69  matrix_closure_type const& matrix, vector_closure_type const&rhs,
70  SystemType system_type = SystemType()
71  ):m_matrix(matrix), m_rhs(rhs), m_system_type(system_type){}
72 
73  matrix_closure_type const& lhs()const{
74  return m_matrix;
75  }
76 
77  vector_closure_type const& rhs()const{
78  return m_rhs;
79  }
80 
81  SystemType const& system_type()const{
82  return m_system_type;
83  }
84 
85  typedef typename MatA::const_row_iterator iterator;
86  typedef iterator const_iterator;
87 
88  //dispatcher to computation kernels
89  template<class VecX>
90  void assign_to(vector_expression<VecX, device_type>& x, value_type alpha)const{
91  assign(x,m_rhs,alpha);
92  solver<MatA,SystemType> alg(m_matrix, m_system_type);
93  alg.solve(x,Side());
94  }
95  template<class VecX>
96  void plus_assign_to(vector_expression<VecX, device_type>& x, value_type alpha)const{
97  typename vector_temporary<VecX>::type temp(m_rhs);
98  solver<MatA,SystemType> alg(m_matrix, m_system_type);
99  alg.solve(temp,Side());
100  plus_assign(x,temp,alpha);
101  }
102 private:
103  matrix_closure_type m_matrix;
104  vector_closure_type m_rhs;
105  SystemType m_system_type;
106 };
107 
108 
109 template<class MatA, class MatB, class SystemType, class Side>
110 class matrix_matrix_solve: public matrix_expression<
111  matrix_matrix_solve<MatA, MatB, SystemType, Side>,
112  typename MatA::device_type
113 >{
114 public:
115  typedef typename MatA::const_closure_type matrixA_closure_type;
116  typedef typename MatB::const_closure_type matrixB_closure_type;
117  typedef decltype(
118  typename MatA::value_type() * typename MatB::value_type()
119  ) value_type;
120  typedef typename MatA::size_type size_type;
121  typedef value_type const_reference;
122  typedef const_reference reference;
123 
124  typedef matrix_matrix_solve const_closure_type;
125  typedef const_closure_type closure_type;
126  typedef unknown_storage storage_type;
127  typedef unknown_storage const_storage_type;
128  typedef blockwise<dense_tag> evaluation_category;
129  typedef typename MatA::device_type device_type;
130  typedef unknown_orientation orientation;
131 
132  matrix_matrix_solve(
133  matrixA_closure_type const& matrix, matrixB_closure_type const& rhs,
134  SystemType const& system_type =SystemType()
135  ):m_matrix(matrix), m_rhs(rhs), m_system_type(system_type){}
136 
137  size_type size1() const {
138  return m_rhs.size1();
139  }
140  size_type size2() const {
141  return m_rhs.size2();
142  }
143  typename device_traits<device_type>::queue_type& queue()const{
144  return m_matrix.queue();
145  }
146 
147  matrixA_closure_type const& lhs()const{
148  return m_matrix;
149  }
150 
151  matrixB_closure_type const& rhs()const{
152  return m_rhs;
153  }
154 
155  SystemType const& system_type()const{
156  return m_system_type;
157  }
158 
159  typedef typename MatA::const_row_iterator row_iterator;
160  typedef row_iterator const_row_iterator;
161  typedef typename MatA::const_column_iterator column_iterator;
162  typedef column_iterator const_column_iterator;
163 
164  //dispatcher to computation kernels
165  template<class MatX>
166  void assign_to(matrix_expression<MatX, device_type>& X, value_type alpha)const{
167  assign(X,m_rhs,alpha);
168  solver<MatA,SystemType> alg(m_matrix,m_system_type);
169  alg.solve(X,Side());
170  }
171  template<class MatX>
172  void plus_assign_to(matrix_expression<MatX, device_type>& X, value_type alpha)const{
173  typename matrix_temporary<MatX>::type temp(m_rhs);
174  solver<MatA,SystemType> alg(m_matrix,m_system_type);
175  alg.solve(temp,Side());
176  plus_assign(X,temp,alpha);
177  }
178 private:
179  matrixA_closure_type m_matrix;
180  matrixB_closure_type m_rhs;
181  SystemType m_system_type;
182 };
183 
184 template<class MatA, class SystemType>
185 class matrix_inverse: public matrix_expression<
186  matrix_inverse<MatA, SystemType>,
187  typename MatA::device_type
188 >{
189 public:
190  typedef typename MatA::const_closure_type matrix_closure_type;
191  typedef typename MatA::value_type value_type;
192  typedef typename MatA::size_type size_type;
193  typedef value_type const_reference;
194  typedef const_reference reference;
195 
196  typedef matrix_inverse const_closure_type;
197  typedef const_closure_type closure_type;
198  typedef unknown_storage storage_type;
199  typedef unknown_storage const_storage_type;
200  typedef blockwise<dense_tag> evaluation_category;
201  typedef typename MatA::device_type device_type;
202  typedef typename MatA::orientation orientation;
203 
204  matrix_inverse(matrix_closure_type const& matrix, SystemType system_type)
205  :m_matrix(matrix), m_system_type(system_type){}
206 
207  size_type size1() const {
208  return m_matrix.size1();
209  }
210  size_type size2() const {
211  return m_matrix.size1();
212  }
213 
214  typename device_traits<device_type>::queue_type& queue()const{
215  return m_matrix.queue();
216  }
217 
218  matrix_closure_type const& matrix()const{
219  return m_matrix;
220  }
221 
222  SystemType const& system_type()const{
223  return m_system_type;
224  }
225 
226  typedef typename MatA::const_row_iterator row_iterator;
227  typedef row_iterator const_row_iterator;
228  typedef typename MatA::const_column_iterator column_iterator;
229  typedef column_iterator const_column_iterator;
230 
231  //dispatcher to computation kernels
232  template<class MatX>
233  void assign_to(matrix_expression<MatX, device_type>& X, value_type alpha)const{
234  typedef scalar_vector<value_type, device_type> diag_vec;
235  assign(X,diagonal_matrix<diag_vec>(diag_vec(size1(),value_type(1))),alpha);
236  solver<MatA,SystemType> alg(m_matrix,m_system_type);
237  alg.solve(X,left());
238  }
239  template<class MatX>
240  void plus_assign_to(matrix_expression<MatX, device_type>& X, value_type alpha)const{
241  typedef scalar_vector<value_type, device_type> diag_vec;
242  typename matrix_temporary<MatX>::type temp = diagonal_matrix<diag_vec>(diag_vec(size1(),value_type(1)),alpha);
243  solver<MatA,SystemType> alg(m_matrix,m_system_type);
244  alg.solve(temp,left());
245  plus_assign(X,temp,alpha);
246  }
247 private:
248  matrix_closure_type m_matrix;
249  SystemType m_system_type;
250 };
251 
252 //////////////////////////////////////////////////////
253 ////////Expression Optimizations
254 //////////////////////////////////////////////////////
255 
256 namespace detail{
257 
258 ////////////////////////////////////
259 //// Vector Solve
260 ////////////////////////////////////
261 template<class M, class V, class Tag, class Side>
262 struct matrix_vector_solve_optimizer{
263  typedef matrix_vector_solve<M,V, Tag, Side> type;
264 
265  static type create(
266  typename M::const_closure_type const& m,
267  typename V::const_closure_type const& v,
268  Tag t
269  ){
270  return type(m,v,t);
271  }
272 };
273 
274 ////////////////////////////////////
275 //// Matrix Solve
276 ////////////////////////////////////
277 template<class M1, class M2, class Tag, class Side>
278 struct matrix_matrix_solve_optimizer{
279  typedef matrix_matrix_solve<M1,M2, Tag, Side> type;
280 
281  static type create(
282  typename M1::const_closure_type const& lhs,
283  typename M2::const_closure_type const& rhs,
284  Tag t
285  ){
286  return type(lhs,rhs,t);
287  }
288 };
289 
290 ////////////////////////////////////
291 //// Matrix Inverse
292 ////////////////////////////////////
293 template<class M, class Tag>
294 struct matrix_inverse_optimizer{
295  typedef matrix_inverse<M, Tag> type;
296 
297  static type create(typename M::const_closure_type const& m, Tag t){
298  return type(m,t);
299  }
300 };
301 
302 //////////////////////////////////
303 /////Interactions with other expressions
304 //////////////////////////////////
305 
306 //small helper needed for transpose
307 template<class T>
308 struct solve_tag_transpose_helper{
309  static T transpose(T t){return t;}
310 };
311 template<bool Upper, bool Unit>
312 struct solve_tag_transpose_helper<triangular_tag<Upper,Unit> >{
313  static triangular_tag<!Upper,Unit> transpose(triangular_tag<Upper,Unit>){return triangular_tag<!Upper,Unit>();}
314 };
315 
316 //trans(solve(A,B,left)) = solve(trans(A),trans(B),right)
317 //trans(solve(A,B,right)) = solve(trans(A),trans(B),left)
318 template<class M1, class M2, bool Left, class Tag>
319 struct matrix_transpose_optimizer<matrix_matrix_solve<M1,M2, Tag, system_tag<Left> > >{
320  typedef matrix_transpose_optimizer<typename const_expression<M2>::type> lhs_opt;
321  typedef matrix_transpose_optimizer<typename const_expression<M1>::type> rhs_opt;
322  typedef matrix_matrix_solve_optimizer<
323  typename lhs_opt::type,typename rhs_opt::type,
324  typename Tag::transposed_tag, system_tag<!Left>
325  > opt;
326  typedef typename opt::type type;
327 
328  static type create(matrix_matrix_solve<M1,M2, Tag, system_tag<Left> > const& m){
329  return opt::create(
330  lhs_opt::create(m.rhs()),rhs_opt::create(m.lhs()),
331  solve_tag_transpose_helper<Tag>::transpose(m.system_type())
332  );
333  }
334 };
335 
336 
337 template<class M, class Tag>
338 struct matrix_transpose_optimizer<matrix_inverse<M, Tag> >{
339  typedef matrix_transpose_optimizer<typename const_expression<M>::type> mat_opt;
340  typedef matrix_inverse_optimizer<
341  typename mat_opt::type, typename Tag::transposed_orientation
342  > opt;
343  typedef typename opt::type type;
344 
345  static type create(matrix_inverse<M, Tag> const& m){
346  return opt::create(
347  mat_opt::create(m.matrix()),
348  solve_tag_transpose_helper<Tag>::transpose(m.system_type())
349  );
350  }
351 };
352 
353 
354 
355 //prod(inv(A),b) = solve(A,b,left)
356 template<class M, class V, class Tag>
357 struct matrix_vector_prod_optimizer<matrix_inverse<M,Tag>, V>{
358  typedef matrix_vector_solve_optimizer<M,V, Tag, left> opt;
359  typedef typename opt::type type;
360 
361  static type create(matrix_inverse<M,Tag> const& inv, typename V::const_closure_type const& v){
362  return opt::create(inv.matrix(),v,inv.system_type());
363  }
364 };
365 
366 //prod(solve(A,B,left),c) = solve(A, prod(B,c),right)
367 template<class M1, class M2,class V, class Tag>
368 struct matrix_vector_prod_optimizer<matrix_matrix_solve<M1,M2, Tag, left >, V >{
369  typedef matrix_vector_prod_optimizer<M2,V> prod_opt;
370  typedef matrix_vector_solve_optimizer<M1, typename prod_opt::type, Tag, left> opt;
371  typedef typename opt::type type;
372 
373  static type create(matrix_matrix_solve<M1,M2, Tag, left> const& m, typename V::const_closure_type const& v){
374  return opt::create(
375  m.lhs(), prod_opt::create(m.rhs(),v), m.system_type()
376  );
377  }
378 };
379 
380 //prod(solve(A,B,right),c) = prod(B,solve(A,c, left))
381 template<class M1, class M2, class V, class Tag>
382 struct matrix_vector_prod_optimizer<matrix_matrix_solve<M1,M2, Tag, right >, V >{
383  typedef matrix_vector_solve_optimizer<M1, V, Tag, left> solve_opt;
384  typedef matrix_vector_prod_optimizer<M2,typename solve_opt::type> opt;
385  typedef typename opt::type type;
386  static type create(matrix_matrix_solve<M1,M2, Tag, right> const& m, typename V::const_closure_type const& v){
387  return opt::create(
388  m.rhs(), solve_opt::create(m.lhs(),v,m.system_type())
389  );
390  }
391 };
392 
393 //row(solve(A,B,left),i) = prod(solve(A,e_i,right),B) = prod(trans(B),solve(A,e_i,right))
394 template<class M1, class M2,class Tag>
395 struct matrix_row_optimizer<matrix_matrix_solve<M1,M2, Tag, left > >{
396  typedef matrix_transpose_optimizer<typename const_expression<M2>::type> rhs_opt;
397  typedef unit_vector<typename M1::value_type, typename M1::device_type> unit;
398  typedef matrix_vector_solve_optimizer<M1, unit, Tag, right> solve_opt;
399  typedef matrix_vector_prod_optimizer<typename rhs_opt::type,typename solve_opt::type> opt;
400  typedef typename opt::type type;
401 
402  static type create(matrix_matrix_solve<M1,M2, Tag, left> const& m, std::size_t i){
403  return opt::create(
404  rhs_opt::create(m.rhs()),
405  solve_opt::create(m.lhs(),unit(m.lhs().size2(),i), m.system_type())
406  );
407  }
408 };
409 
410 //row(solve(A,B,right),i) = solve(A,row(B,i),right)
411 template<class M1, class M2, class Tag>
412 struct matrix_row_optimizer<matrix_matrix_solve<M1,M2, Tag, right > >{
413  typedef matrix_row_optimizer<typename const_expression<M2>::type> rhs_opt;
414  typedef matrix_vector_solve_optimizer<M1, typename rhs_opt::type, Tag, right> opt;
415  typedef typename opt::type type;
416 
417  static type create(matrix_matrix_solve<M1,M2, Tag, right> const& m, std::size_t i){
418  return opt::create(m.lhs(),rhs_opt::create(m.rhs(),i), m.system_type());
419  }
420 };
421 
422 //row(inv(A),i) = solve(A,e_1,right)
423 template<class M, class Tag>
424 struct matrix_row_optimizer<matrix_inverse<M, Tag > >{
425  typedef unit_vector<typename M::value_type, typename M::device_type> unit;
426  typedef matrix_vector_solve_optimizer<M, unit, Tag, right> opt;
427  typedef typename opt::type type;
428 
429  static type create(matrix_inverse<M, Tag > const& m, std::size_t i){
430  return opt::create(m.matrix(), unit(m.lhs().size2(),i), m.system_type());
431  }
432 };
433 
434 //prod(inv(A),B) = solve(A,B,left)
435 template<class M1, class M2, class Tag>
436 struct matrix_matrix_prod_optimizer<matrix_inverse<M1,Tag>, M2>{
437  typedef matrix_matrix_solve_optimizer<M1,M2, Tag, left> opt;
438  typedef typename opt::type type;
439 
440  static type create(matrix_inverse<M1,Tag> const& inv, typename M2::const_closure_type const& m){
441  return opt::create(inv.matrix(),m,inv.system_type());
442  }
443 };
444 
445 //prod(B,inv(A)) = solve(A,B,right)
446 template<class M1, class M2, class Tag>
447 struct matrix_matrix_prod_optimizer<M1, matrix_inverse<M2,Tag> >{
448  typedef matrix_matrix_solve_optimizer<M2,M1, Tag, right> opt;
449  typedef typename opt::type type;
450 
451  static type create(typename M1::const_closure_type const& m, matrix_inverse<M2,Tag> const& inv){
452  return opt::create(inv.matrix(),m,inv.system_type());
453  }
454 };
455 
456 
457 }
458 
459 
460 //solvers for vector rhs
461 template<class MatA, class VecB, bool Left, class Device, class SystemType>
462 typename detail::matrix_vector_solve_optimizer<MatA,VecB, SystemType, system_tag<Left> >::type
463 solve(
464  matrix_expression<MatA, Device> const& A,
465  vector_expression<VecB, Device> const& b,
466  SystemType t, system_tag<Left>
467 ){
468  REMORA_SIZE_CHECK(A().size1() == A().size2());
469  REMORA_SIZE_CHECK(A().size1() == b().size());
470  typedef detail::matrix_vector_solve_optimizer<MatA,VecB, SystemType, system_tag<Left> > opt;
471  return opt::create(A(),b(), t);
472 }
473 //solvers for matrix rhs
474 template<class MatA, class MatB, bool Left, class Device, class SystemType>
475 typename detail::matrix_matrix_solve_optimizer<MatA,MatB, SystemType, system_tag<Left> >::type
476 solve(
477  matrix_expression<MatA, Device> const& A,
478  matrix_expression<MatB, Device> const& B,
479  SystemType t, system_tag<Left>
480 ){
481  REMORA_SIZE_CHECK(A().size1() == A().size2());
482  typedef detail::matrix_matrix_solve_optimizer<MatA,MatB, SystemType, system_tag<Left> > opt;
483  return opt::create(A(),B(), t);
484 }
485 
486 //matrix inverses
487 template<class MatA, class Device, class SystemType>
488 typename detail::matrix_inverse_optimizer<MatA, SystemType>::type
489 inv(
490  matrix_expression<MatA, Device> const& A, SystemType t
491 ){
492  REMORA_SIZE_CHECK(A().size1() == A().size2());
493  typedef detail::matrix_inverse_optimizer<MatA,SystemType> opt;
494  return opt::create(A(), t);
495 }
496 
497 
498 }
499 #endif