/*!
* \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