28#ifndef REMORA_MATRIX_EXPRESSION_HPP
29#define REMORA_MATRIX_EXPRESSION_HPP
31#include "detail/expression_optimizers.hpp"
54template<
class VecV,
class Device>
55vector_repeater<VecV> repeat(vector_expression<VecV, Device>
const& vector, std::size_t rows){
56 return vector_repeater<VecV>(vector(),rows);
66typename std::enable_if<std::is_arithmetic<T>::value, scalar_matrix<T,cpu_tag, row_major> >::type
67repeat(T scalar, std::size_t rows, std::size_t columns){
68 return scalar_matrix<T,cpu_tag, row_major>(rows, columns, scalar);
75class identity_matrix:
public diagonal_matrix<scalar_vector<T, cpu_tag> > {
76 typedef diagonal_matrix<scalar_vector<T, cpu_tag> > base_type;
79 identity_matrix(std::size_t size):base_type(scalar_vector<T, cpu_tag>(size,T(1))){}
85template<
class MatA,
class Device>
86diagonal_matrix<MatA> to_diagonal(vector_expression<MatA, Device>
const& v){
87 return diagonal_matrix<MatA>(v());
98template<
class MatA,
class Device>
99typename detail::matrix_scalar_multiply_optimizer<MatA>::type
100operator-(matrix_expression<MatA, Device>
const& A){
101 return detail::matrix_scalar_multiply_optimizer<MatA>::create(A(),
typename MatA::value_type(-1));
104#define REMORA_UNARY_MATRIX_TRANSFORMATION(name, F)\
105template<class MatA, class Device>\
106typename detail::matrix_unary_optimizer<MatA,typename device_traits<Device>:: template F<typename MatA::value_type> >::type \
107name(matrix_expression<MatA, Device> const& m){\
108 typedef typename device_traits<Device>:: template F<typename MatA::value_type> functor_type;\
109 return detail::matrix_unary_optimizer<MatA, functor_type >::create(m(), functor_type());\
130#undef REMORA_UNARY_MATRIX_TRANSFORMATION
132#define REMORA_UNARY_VECTOR_SET_TRANSFORMATION(name)\
133template<class S, class Device>\
134auto name(vector_set_expression<S, Device> const& set)\
135-> decltype(as_set(name( set().expression()), typename S::point_orientation())){\
136 return as_set(name( set().expression()), typename S::point_orientation());\
157#undef REMORA_UNARY_VECTOR_SET_TRANSFORMATION
167template<
class MatA,
class T,
class Device>
168typename std::enable_if<
169 std::is_convertible<T, typename MatA::value_type >::value,
170 typename detail::matrix_scalar_multiply_optimizer<MatA>::type
172operator* (matrix_expression<MatA, Device>
const& A, T scalar){
173 return detail::matrix_scalar_multiply_optimizer<MatA>::create(A(),
typename MatA::value_type(scalar));
179template<
class T,
class MatA,
class Device>
180typename std::enable_if<
181 std::is_convertible<T, typename MatA::value_type >::value,
182 typename detail::matrix_scalar_multiply_optimizer<MatA>::type
184operator* (T scalar, matrix_expression<MatA, Device>
const& A){
185 return detail::matrix_scalar_multiply_optimizer<MatA>::create(A(),
typename MatA::value_type(scalar));
190template<
class MatA,
class T,
class Device>
191typename std::enable_if<
192 std::is_convertible<T, typename MatA::value_type>::value,
193 matrix_addition<MatA, scalar_matrix<T,Device, typename MatA::orientation> >
195 matrix_expression<MatA, Device>
const& A,
198 return A + scalar_matrix<T,Device, typename MatA::orientation>(A().size1(),A().size2(),t);
202template<
class T,
class MatA,
class Device>
203typename std::enable_if<
204 std::is_convertible<T, typename MatA::value_type>::value,
205 matrix_addition<MatA, scalar_matrix<T,Device, typename MatA::orientation> >
208 matrix_expression<MatA, Device>
const& A
210 return A + scalar_matrix<T,Device, typename MatA::orientation>(A().size1(),A().size2(),t);
214template<
class MatA,
class T,
class Device>
215typename std::enable_if<
216 std::is_convertible<T, typename MatA::value_type>::value ,
217 decltype(std::declval<MatA const&>() + T())
219 matrix_expression<MatA, Device>
const& A,
226template<
class MatA,
class T,
class Device>
227typename std::enable_if<
228 std::is_convertible<T, typename MatA::value_type>::value,
229 decltype(T() + (-std::declval<MatA const&>()))
232 matrix_expression<MatA, Device>
const& A
237#define REMORA_MATRIX_SCALAR_TRANSFORMATION(name, F)\
238template<class T, class MatA, class Device> \
239typename std::enable_if< \
240 std::is_convertible<T, typename MatA::value_type >::value,\
241 matrix_binary<MatA, scalar_matrix<typename MatA::value_type,Device, typename MatA::orientation>,typename device_traits<Device>:: template F<typename MatA::value_type> > \
243name (matrix_expression<MatA, Device> const& m, T t){ \
244 typedef typename MatA::value_type type;\
245 typedef typename device_traits<Device>:: template F<type> functor_type;\
246 typedef scalar_matrix<type,Device, typename MatA::orientation> mat_type;\
247 return matrix_binary<MatA, mat_type, functor_type >(m(), mat_type(m().size1(), m().size2(), t) ,functor_type()); \
259#undef REMORA_MATRIX_SCALAR_TRANSFORMATION
262#define REMORA_MATRIX_SCALAR_TRANSFORMATION_2(name, F)\
263template<class T, class MatA, class Device> \
264typename std::enable_if< \
265 std::is_convertible<T, typename MatA::value_type >::value,\
266 matrix_binary<scalar_matrix< typename MatA::value_type,Device, typename MatA::orientation>, MatA, typename device_traits<Device>:: template F< typename MatA::value_type> > \
268name (T t, matrix_expression<MatA, Device> const& m){ \
269 typedef typename MatA::value_type type;\
270 typedef typename device_traits<Device>:: template F<type> functor_type;\
271 typedef scalar_matrix<type,Device, typename MatA::orientation> mat_type;\
272 return matrix_binary<mat_type, MatA, functor_type >(mat_type(m().size1(), m().size2(), t), m(), functor_type()); \
276#undef REMORA_MATRIX_SCALAR_TRANSFORMATION_2
285template<
class MatA,
class MatB,
class Device>
286matrix_addition<MatA, MatB > operator+ (
287 matrix_expression<MatA, Device>
const& A,
288 matrix_expression<MatB, Device>
const& B
290 REMORA_SIZE_CHECK(A().size1() == B().size1());
291 REMORA_SIZE_CHECK(A().size2() == B().size2());
292 return matrix_addition<MatA, MatB>(A(),B());
296template<
class MatA,
class MatB,
class Device>
298 matrix_expression<MatA, Device>
const& A,
299 matrix_expression<MatB, Device>
const& B
300) ->
decltype(A() + (-B)){
301 REMORA_SIZE_CHECK(A().size1() == B().size1());
302 REMORA_SIZE_CHECK(A().size2() == B().size2());
306template<
class MatA,
class MatB,
class Device>
307matrix_binary<MatA, MatB,
308 typename device_traits<Device>:: template safe_divide<typename common_value_type<MatA,MatB>::type>
311 matrix_expression<MatA, Device>
const& A,
312 matrix_expression<MatB, Device>
const& B,
313 typename common_value_type<MatA,MatB>::type defaultValue
315 REMORA_SIZE_CHECK(A().size1() == B().size1());
316 REMORA_SIZE_CHECK(A().size2() == B().size2());
317 typedef typename common_value_type<MatA,MatB>::type result_type;
318 typedef typename device_traits<Device>:: template safe_divide<result_type> functor_type;
319 return matrix_binary<MatA, MatB, functor_type>(A(),B(), functor_type(defaultValue));
323#define REMORA_BINARY_MATRIX_EXPRESSION(name, F)\
324template<class MatA, class MatB, class Device>\
325matrix_binary<MatA, MatB, typename device_traits<Device>:: template F<typename common_value_type<MatA,MatB>::type> >\
326name(matrix_expression<MatA, Device> const& m1, matrix_expression<MatB, Device> const& m2){\
327 REMORA_SIZE_CHECK(m1().size1() == m2().size1());\
328 REMORA_SIZE_CHECK(m1().size2() == m2().size2());\
329 typedef typename common_value_type<MatA,MatB>::type type;\
330 typedef typename device_traits<Device>:: template F<type> functor_type;\
331 return matrix_binary<MatA, MatB, functor_type >(m1(),m2(), functor_type());\
340#undef REMORA_BINARY_MATRIX_EXPRESSION
351template<
class VecA,
class VecB,
class Device>
352outer_product<VecA, VecB >
354 vector_expression<VecA, Device>
const& v1,
355 vector_expression<VecB, Device>
const& v2
357 return outer_product<VecA, VecB>(v1(), v2());
366template<
class MatA,
class VecV,
class Device>
367typename detail::matrix_vector_prod_optimizer<MatA,VecV>::type prod(
368 matrix_expression<MatA, Device>
const& A,vector_expression<VecV, Device>
const& v
370 REMORA_SIZE_CHECK(A().size2() == v().size());
371 return detail::matrix_vector_prod_optimizer<MatA,VecV>::create(A(),v());
381template<
class MatA,
class VecV,
class Device>
382auto prod(vector_expression<VecV, Device>
const& v,matrix_expression<MatA, Device>
const& A) ->
decltype(prod(trans(A),v)){
383 REMORA_SIZE_CHECK(A().size1() == v().size());
384 return prod(trans(A),v);
390template<
class MatA,
class VecV,
class Device>
391auto operator%(vector_expression<VecV, Device>
const& v,matrix_expression<MatA, Device>
const& A) ->
decltype(prod(trans(A),v)){
392 REMORA_SIZE_CHECK(A().size1() == v().size());
393 return prod(trans(A),v);
399template<
class MatA,
class VecV,
class Device>
400auto operator%(matrix_expression<MatA, Device>
const& A,vector_expression<VecV, Device>
const& v) ->
decltype(prod(A,v)){
401 REMORA_SIZE_CHECK(A().size2() == v().size());
412template<
class TriangularType,
class MatA,
class VecV,
class Device>
414 matrix_expression<MatA, Device>
const& A,
415 vector_expression<VecV, Device>& v
416) ->
decltype(prod(to_triangular(A, TriangularType()), v)){
417 REMORA_SIZE_CHECK(A().size2() == v().size());
418 return prod(to_triangular(A, TriangularType()), v);
422template<
class MatA,
class MatB,
class Device>
423typename detail::matrix_matrix_prod_optimizer<MatA,MatB>::type prod(
424 matrix_expression<MatA, Device>
const& A,
425 matrix_expression<MatB, Device>
const& B
427 REMORA_SIZE_CHECK(A().size2() == B().size1());
428 return detail::matrix_matrix_prod_optimizer<MatA,MatB>::create(A(),B());
434template<
class MatA,
class MatB,
class Device>
436 matrix_expression<MatA, Device>
const& A,
437 matrix_expression<MatB, Device>
const& B
438) ->
decltype(prod(A,B)){
439 REMORA_SIZE_CHECK(A().size2() == B().size1());
451template<
class TriangularType,
class MatA,
class MatB,
class Device>
453 matrix_expression<MatA, Device>
const& A,
454 matrix_expression<MatB, Device>
const& B
455) ->
decltype(prod(to_triangular(A, TriangularType()), B)){
456 REMORA_SIZE_CHECK(A().size2() == B().size1());
457 return prod(to_triangular(A, TriangularType()), B);
509template<
class S,
class Device>
510typename detail::fold_vector_set_optimizer<
511 S,
typename device_traits<Device>:: template add<typename S::value_type>
512 ,
typename device_traits<Device>:: template identity<typename S::value_type>
514sum(vector_set_expression<S, Device>
const& set) {
515 typedef typename device_traits<Device>:: template add<typename S::value_type> Add;
516 typedef typename device_traits<Device>:: template identity<typename S::value_type> Identity;
517 return detail::fold_vector_set_optimizer<S, Add, Identity>::create(set(), Add(), Identity());
523template<
class S,
class Device>
524typename detail::fold_vector_set_optimizer<
525 S,
typename device_traits<Device>:: template max<typename S::value_type>
526 ,
typename device_traits<Device>:: template identity<typename S::value_type>
528max(vector_set_expression<S, Device>
const& set) {
529 typedef typename device_traits<Device>:: template max<typename S::value_type> Max;
530 typedef typename device_traits<Device>:: template identity<typename S::value_type> Identity;
531 return detail::fold_vector_set_optimizer<S, Max, Identity>::create(set(), Max(), Identity());
537template<
class S,
class Device>
538typename detail::fold_vector_set_optimizer<
539 S,
typename device_traits<Device>:: template min<typename S::value_type>
540 ,
typename device_traits<Device>:: template identity<typename S::value_type>
542min(vector_set_expression<S, Device>
const& set) {
543 typedef typename device_traits<Device>:: template min<typename S::value_type> Min;
544 typedef typename device_traits<Device>:: template identity<typename S::value_type> Identity;
545 return detail::fold_vector_set_optimizer<S, Min, Identity>::create(set(), Min(), Identity());
563template<
class S,
class Device>
564auto norm_1(vector_set_expression<S, Device>
const& set) ->decltype(sum(abs(set))) {
565 return sum(abs(set));
571template<
class S,
class Device>
572auto norm_sqr(vector_set_expression<S, Device>
const& set) ->decltype(sum(
sqr(set))){
573 return sum(
sqr(set));
579template<
class S,
class Device>
580auto norm_2(vector_set_expression<S, Device>
const& set) ->decltype(sqrt(norm_sqr(set))){
581 return sqrt(norm_sqr(set));
587template<
class S,
class Device>
588auto norm_inf(vector_set_expression<S, Device>
const& set) ->decltype(max(abs(set))){
589 return max(abs(set));
600template<
class MatA,
class Device>
601typename MatA::value_type sum(matrix_expression<MatA, Device>
const& A){
602 typedef typename MatA::value_type value_type;
603 typedef typename device_traits<Device>:: template add<value_type> functor_type;
604 auto const& elem_result = eval_block(A);
605 value_type result = 0;
606 kernels::matrix_fold<functor_type>(elem_result,result);
615template<
class MatA,
class Device>
616typename MatA::value_type max(matrix_expression<MatA, Device>
const& A){
617 typedef typename MatA::value_type value_type;
618 typedef typename device_traits<Device>:: template max<value_type> functor_type;
619 auto const& elem_result = eval_block(A);
620 value_type result = 0;
621 kernels::matrix_fold<functor_type>(elem_result,result);
628template<
class MatA,
class Device>
629typename MatA::value_type min(matrix_expression<MatA, Device>
const& A){
630 typedef typename MatA::value_type value_type;
631 typedef typename device_traits<Device>:: template min<value_type> functor_type;
632 auto const& elem_result = eval_block(A);
633 value_type result = 0;
634 kernels::matrix_fold<functor_type>(elem_result,result);
642template<
class MatA,
class MatB,
class Device>
643decltype(
typename MatA::value_type() *
typename MatB::value_type())
645 matrix_expression<MatA, Device>
const& A,
646 matrix_expression<MatB, Device>
const& B
648 REMORA_SIZE_CHECK(A().size1() == B().size1());
649 REMORA_SIZE_CHECK(A().size2() == B().size2());
650 return sum(eval_block(A*B));
656template<
class MatA,
class Device>
657typename real_traits<typename MatA::value_type>::type
658norm_1(matrix_expression<MatA, Device>
const& A) {
659 return max(norm_1(as_columns(A)));
665template<
class MatA,
class Device>
666typename real_traits<typename MatA::value_type>::type
667norm_frobenius(matrix_expression<MatA, Device>
const& A) {
669 return sqrt(sum(
sqr(eval_block(A))));
675template<
class MatA,
class Device>
676typename real_traits<typename MatA::value_type>::type
677norm_inf(matrix_expression<MatA, Device>
const& A) {
678 return max(norm_1(as_rows(A)));
688template <
class MatA,
class Device>
689typename MatA::value_type trace(matrix_expression<MatA, Device>
const& A){
690 REMORA_SIZE_CHECK(A().size1() == A().size2());
699template<
class MatA,
class MatB,
class Device>
700matrix_concat<MatA, MatB, true> operator|(
701 matrix_expression<MatA, Device>
const& A,
702 matrix_expression<MatB, Device>
const& B
704 return matrix_concat<MatA, MatB, true>(A(),B());
708template<
class MatA,
class VecV,
class Device>
710 matrix_expression<MatA, Device>
const& A,
711 vector_expression<VecV, Device>
const& v
712) ->
decltype(A | trans(repeat(v,1))){
713 return A | trans(repeat(v,1));
717template<
class MatA,
class VecV,
class Device>
719 vector_expression<VecV, Device>
const& v,
720 matrix_expression<MatA, Device>
const& A
721) ->
decltype(trans(repeat(v,1)) | A){
722 return trans(repeat(v,1)) | A;
728template<
class MatA,
class T,
class Device>
729typename std::enable_if<
730 std::is_convertible<T, typename MatA::value_type>::value,
731 matrix_concat<MatA, scalar_matrix<T, Device, row_major>,
true >
733 matrix_expression<MatA, Device>
const& A,
736 return A | repeat(t,A().size1(), 1);
742template<
class MatA,
class T,
class Device>
743typename std::enable_if<
744 std::is_convertible<T, typename MatA::value_type>::value,
745 matrix_concat<scalar_matrix<T, Device, row_major>, MatA,
true >
748 matrix_expression<MatA, Device>
const& A
750 return repeat(t,A().size1(), 1) | A;
754template<
class MatA,
class MatB,
class Device>
755matrix_concat<MatA, MatB, false> operator&(
756 matrix_expression<MatA, Device>
const& A,
757 matrix_expression<MatB, Device>
const& B
759 return matrix_concat<MatA, MatB, false>(A(),B());
763template<
class MatA,
class VecV,
class Device>
765 matrix_expression<MatA, Device>
const& A,
766 vector_expression<VecV, Device>
const& v
767) ->
decltype(A & repeat(v,1)){
768 return A & repeat(v,1);
772template<
class MatA,
class VecV,
class Device>
774 vector_expression<VecV, Device>
const& v,
775 matrix_expression<MatA, Device>
const& A
776) ->
decltype(repeat(v,1) & A){
777 return repeat(v,1) & A;
783template<
class MatA,
class T,
class Device>
784typename std::enable_if<
785 std::is_convertible<T, typename MatA::value_type>::value,
786 matrix_concat<MatA, scalar_matrix<T, Device, row_major>,
false >
788 matrix_expression<MatA, Device>
const& A,
791 return A & repeat(t, 1, A().size2());
797template<
class MatA,
class T,
class Device>
798typename std::enable_if<
799 std::is_convertible<T, typename MatA::value_type>::value,
800 matrix_concat<scalar_matrix<T, Device, row_major>, MatA,
false >
803 matrix_expression<MatA, Device>
const& A
805 return repeat(t,1, A().size2()) & A;