/*! * \brief Defines types for matrix decompositions * * \author O. Krause * \date 2016 * * * \par Copyright 1995-2015 Shark Development Team * *

* This file is part of Shark. * * * Shark is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Shark is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Shark. If not, see . * */ #ifndef REMORA_SOLVE_HPP #define REMORA_SOLVE_HPP #include "decompositions.hpp" namespace remora{ ////////////////////////////////////////////////////// ////////Expression Types for Solving and inverse ////////////////////////////////////////////////////// template class matrix_vector_solve: public vector_expression< matrix_vector_solve, typename MatA::device_type >{ public: typedef typename MatA::const_closure_type matrix_closure_type; typedef typename VecV::const_closure_type vector_closure_type; typedef decltype( typename MatA::value_type() * typename VecV::value_type() ) value_type; typedef typename MatA::size_type size_type; typedef value_type const_reference; typedef const_reference reference; typedef matrix_vector_solve const_closure_type; typedef const_closure_type closure_type; typedef unknown_storage storage_type; typedef unknown_storage const_storage_type; typedef blockwise evaluation_category; typedef typename MatA::device_type device_type; size_type size() const { return m_rhs.size(); } typename device_traits::queue_type& queue()const{ return m_matrix.queue(); } matrix_vector_solve( matrix_closure_type const& matrix, vector_closure_type const&rhs, SystemType system_type = SystemType() ):m_matrix(matrix), m_rhs(rhs), m_system_type(system_type){} matrix_closure_type const& lhs()const{ return m_matrix; } vector_closure_type const& rhs()const{ return m_rhs; } SystemType const& system_type()const{ return m_system_type; } typedef no_iterator iterator; typedef iterator const_iterator; //dispatcher to computation kernels template void assign_to(vector_expression& x, typename VecX::value_type alpha)const{ assign(x,m_rhs,alpha); solver alg(m_matrix, m_system_type); alg.solve(x,Side()); } template void plus_assign_to(vector_expression& x, typename VecX::value_type alpha)const{ typename vector_temporary::type temp(m_rhs); solver alg(m_matrix, m_system_type); alg.solve(temp,Side()); plus_assign(x,temp,alpha); } private: matrix_closure_type m_matrix; vector_closure_type m_rhs; SystemType m_system_type; }; template class matrix_matrix_solve: public matrix_expression< matrix_matrix_solve, typename MatA::device_type >{ public: typedef typename MatA::const_closure_type matrixA_closure_type; typedef typename MatB::const_closure_type matrixB_closure_type; typedef decltype( typename MatA::value_type() * typename MatB::value_type() ) value_type; typedef typename MatA::size_type size_type; typedef value_type const_reference; typedef const_reference reference; typedef matrix_matrix_solve const_closure_type; typedef const_closure_type closure_type; typedef unknown_storage storage_type; typedef unknown_storage const_storage_type; typedef blockwise evaluation_category; typedef typename MatA::device_type device_type; typedef unknown_orientation orientation; matrix_matrix_solve( matrixA_closure_type const& matrix, matrixB_closure_type const& rhs, SystemType const& system_type =SystemType() ):m_matrix(matrix), m_rhs(rhs), m_system_type(system_type){} size_type size1() const { return m_rhs.size1(); } size_type size2() const { return m_rhs.size2(); } typename device_traits::queue_type& queue()const{ return m_matrix.queue(); } matrixA_closure_type const& lhs()const{ return m_matrix; } matrixB_closure_type const& rhs()const{ return m_rhs; } SystemType const& system_type()const{ return m_system_type; } typedef no_iterator major_iterator; typedef major_iterator const_major_iterator; //dispatcher to computation kernels template void assign_to(matrix_expression& X, typename MatX::value_type alpha)const{ assign(X,m_rhs,alpha); solver alg(m_matrix,m_system_type); alg.solve(X,Side()); } template void plus_assign_to(matrix_expression& X, typename MatX::value_type alpha)const{ typename matrix_temporary::type temp(m_rhs); solver alg(m_matrix,m_system_type); alg.solve(temp,Side()); plus_assign(X,temp,alpha); } private: matrixA_closure_type m_matrix; matrixB_closure_type m_rhs; SystemType m_system_type; }; template class matrix_inverse: public matrix_expression< matrix_inverse, typename MatA::device_type >{ public: typedef typename MatA::const_closure_type matrix_closure_type; typedef typename MatA::value_type value_type; typedef typename MatA::size_type size_type; typedef value_type const_reference; typedef const_reference reference; typedef matrix_inverse const_closure_type; typedef const_closure_type closure_type; typedef unknown_storage storage_type; typedef unknown_storage const_storage_type; typedef blockwise evaluation_category; typedef typename MatA::device_type device_type; typedef typename MatA::orientation orientation; matrix_inverse(matrix_closure_type const& matrix, SystemType system_type) :m_matrix(matrix), m_system_type(system_type){} size_type size1() const { return m_matrix.size1(); } size_type size2() const { return m_matrix.size1(); } typename device_traits::queue_type& queue()const{ return m_matrix.queue(); } matrix_closure_type const& matrix()const{ return m_matrix; } SystemType const& system_type()const{ return m_system_type; } typedef no_iterator major_iterator; typedef major_iterator const_major_iterator; //dispatcher to computation kernels template void assign_to(matrix_expression& X, typename MatX::value_type alpha)const{ typedef scalar_vector diag_vec; assign(X,diagonal_matrix(diag_vec(size1(),value_type(1))),alpha); solver alg(m_matrix,m_system_type); alg.solve(X,left()); } template void plus_assign_to(matrix_expression& X, typename MatX::value_type alpha)const{ typedef scalar_vector diag_vec; typename matrix_temporary::type temp = diagonal_matrix(diag_vec(size1(),value_type(1)),alpha); solver alg(m_matrix,m_system_type); alg.solve(temp,left()); plus_assign(X,temp,alpha); } private: matrix_closure_type m_matrix; SystemType m_system_type; }; ////////////////////////////////////////////////////// ////////Expression Optimizations ////////////////////////////////////////////////////// namespace detail{ //////////////////////////////////// //// Vector Solve //////////////////////////////////// template struct matrix_vector_solve_optimizer{ typedef matrix_vector_solve type; static type create( typename M::const_closure_type const& m, typename V::const_closure_type const& v, Tag t ){ return type(m,v,t); } }; //////////////////////////////////// //// Matrix Solve //////////////////////////////////// template struct matrix_matrix_solve_optimizer{ typedef matrix_matrix_solve type; static type create( typename M1::const_closure_type const& lhs, typename M2::const_closure_type const& rhs, Tag t ){ return type(lhs,rhs,t); } }; //////////////////////////////////// //// Matrix Inverse //////////////////////////////////// template struct matrix_inverse_optimizer{ typedef matrix_inverse type; static type create(typename M::const_closure_type const& m, Tag t){ return type(m,t); } }; ////////////////////////////////// /////Interactions with other expressions ////////////////////////////////// //small helper needed for transpose template struct solve_tag_transpose_helper{ static T transpose(T t){return t;} }; template struct solve_tag_transpose_helper >{ static triangular_tag transpose(triangular_tag){return triangular_tag();} }; //trans(solve(A,B,left)) = solve(trans(A),trans(B),right) //trans(solve(A,B,right)) = solve(trans(A),trans(B),left) template struct matrix_transpose_optimizer > >{ typedef matrix_transpose_optimizer lhs_opt; typedef matrix_transpose_optimizer rhs_opt; typedef matrix_matrix_solve_optimizer< typename lhs_opt::type,typename rhs_opt::type, typename Tag::transposed_tag, system_tag > opt; typedef typename opt::type type; static type create(matrix_matrix_solve > const& m){ return opt::create( lhs_opt::create(m.rhs()),rhs_opt::create(m.lhs()), solve_tag_transpose_helper::transpose(m.system_type()) ); } }; template struct matrix_transpose_optimizer >{ typedef matrix_transpose_optimizer mat_opt; typedef matrix_inverse_optimizer< typename mat_opt::type, typename Tag::transposed_orientation > opt; typedef typename opt::type type; static type create(matrix_inverse const& m){ return opt::create( mat_opt::create(m.matrix()), solve_tag_transpose_helper::transpose(m.system_type()) ); } }; //prod(inv(A),b) = solve(A,b,left) template struct matrix_vector_prod_optimizer, V>{ typedef matrix_vector_solve_optimizer opt; typedef typename opt::type type; static type create(matrix_inverse const& inv, typename V::const_closure_type const& v){ return opt::create(inv.matrix(),v,inv.system_type()); } }; //prod(solve(A,B,left),c) = solve(A, prod(B,c),right) template struct matrix_vector_prod_optimizer, V >{ typedef matrix_vector_prod_optimizer prod_opt; typedef matrix_vector_solve_optimizer opt; typedef typename opt::type type; static type create(matrix_matrix_solve const& m, typename V::const_closure_type const& v){ return opt::create( m.lhs(), prod_opt::create(m.rhs(),v), m.system_type() ); } }; //prod(solve(A,B,right),c) = prod(B,solve(A,c, left)) template struct matrix_vector_prod_optimizer, V >{ typedef matrix_vector_solve_optimizer solve_opt; typedef matrix_vector_prod_optimizer opt; typedef typename opt::type type; static type create(matrix_matrix_solve const& m, typename V::const_closure_type const& v){ return opt::create( m.rhs(), solve_opt::create(m.lhs(),v,m.system_type()) ); } }; //row(solve(A,B,left),i) = prod(solve(A,e_i,right),B) = prod(trans(B),solve(A,e_i,right)) template struct matrix_row_optimizer >{ typedef matrix_transpose_optimizer rhs_opt; typedef unit_vector unit; typedef matrix_vector_solve_optimizer solve_opt; typedef matrix_vector_prod_optimizer opt; typedef typename opt::type type; static type create(matrix_matrix_solve const& m, std::size_t i){ return opt::create( rhs_opt::create(m.rhs()), solve_opt::create(m.lhs(),unit(m.lhs().size2(),i), m.system_type()) ); } }; //row(solve(A,B,right),i) = solve(A,row(B,i),right) template struct matrix_row_optimizer >{ typedef matrix_row_optimizer rhs_opt; typedef matrix_vector_solve_optimizer opt; typedef typename opt::type type; static type create(matrix_matrix_solve const& m, std::size_t i){ return opt::create(m.lhs(),rhs_opt::create(m.rhs(),i), m.system_type()); } }; //row(inv(A),i) = solve(A,e_1,right) template struct matrix_row_optimizer >{ typedef unit_vector unit; typedef matrix_vector_solve_optimizer opt; typedef typename opt::type type; static type create(matrix_inverse const& m, std::size_t i){ return opt::create(m.matrix(), unit(m.lhs().size2(),i), m.system_type()); } }; //prod(inv(A),B) = solve(A,B,left) template struct matrix_matrix_prod_optimizer, M2>{ typedef matrix_matrix_solve_optimizer opt; typedef typename opt::type type; static type create(matrix_inverse const& inv, typename M2::const_closure_type const& m){ return opt::create(inv.matrix(),m,inv.system_type()); } }; //prod(B,inv(A)) = solve(A,B,right) template struct matrix_matrix_prod_optimizer >{ typedef matrix_matrix_solve_optimizer opt; typedef typename opt::type type; static type create(typename M1::const_closure_type const& m, matrix_inverse const& inv){ return opt::create(inv.matrix(),m,inv.system_type()); } }; } //solvers for vector rhs template typename detail::matrix_vector_solve_optimizer >::type solve( matrix_expression const& A, vector_expression const& b, SystemType t, system_tag ){ REMORA_SIZE_CHECK(A().size1() == A().size2()); REMORA_SIZE_CHECK(A().size1() == b().size()); typedef detail::matrix_vector_solve_optimizer > opt; return opt::create(A(),b(), t); } //solvers for matrix rhs template typename detail::matrix_matrix_solve_optimizer >::type solve( matrix_expression const& A, matrix_expression const& B, SystemType t, system_tag ){ REMORA_SIZE_CHECK(A().size1() == A().size2()); typedef detail::matrix_matrix_solve_optimizer > opt; return opt::create(A(),B(), t); } //matrix inverses template typename detail::matrix_inverse_optimizer::type inv( matrix_expression const& A, SystemType t ){ REMORA_SIZE_CHECK(A().size1() == A().size2()); typedef detail::matrix_inverse_optimizer opt; return opt::create(A(), t); } } #endif