1 //
2 //  Copyright (c) 2018-2019, Cem Bassoy, [email protected]
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See
5 //  accompanying file LICENSE_1_0.txt or copy at
6 //  http://www.boost.org/LICENSE_1_0.txt)
7 //
8 //  The authors gratefully acknowledge the support of
9 //  Fraunhofer IOSB, Ettlingen, Germany
10 //
11 
12 #ifndef BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP
13 #define BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP
14 
15 #include <cstddef>
16 #include <boost/numeric/ublas/expression_types.hpp>
17 
18 
19 namespace boost   {
20 namespace numeric {
21 namespace ublas   {
22 
23 
24 template<class element_type, class storage_format, class storage_type>
25 class tensor;
26 
27 template<class size_type>
28 class basic_extents;
29 
30 
31 //TODO: put in fwd.hpp
32 struct tensor_tag {};
33 
34 }
35 }
36 }
37 
38 namespace boost   {
39 namespace numeric {
40 namespace ublas   {
41 namespace detail  {
42 
43 /** @\brief base class for tensor expressions
44  *
45  * \note implements crtp - no use of virtual function calls
46  *
47  * \tparam T type of the tensor
48  * \tparam E type of the derived expression (crtp)
49  *
50  **/
51 template<class T, class E>
52 struct tensor_expression
53     : public ublas_expression<E>
54 {
55 	//	static const unsigned complexity = 0;
56 	using expression_type = E;
57 	using type_category = tensor_tag;
58 	using tensor_type = T;
59 
60 	BOOST_UBLAS_INLINE
operator ()boost::numeric::ublas::detail::tensor_expression61 	auto const& operator()() const { return *static_cast<const expression_type*> (this); }
62 
63 protected :
64 	explicit tensor_expression() = default;
65 	tensor_expression(const tensor_expression&) = delete;
66 	tensor_expression& operator=(const tensor_expression&) = delete;
67 };
68 
69 
70 template<class T, class EL, class ER, class OP>
71 struct binary_tensor_expression
72     : public tensor_expression <T, binary_tensor_expression<T,EL,ER,OP>>
73 {
74 	using self_type = binary_tensor_expression<T,EL,ER,OP>;
75 	using tensor_type  = T;
76 	using binary_operation = OP;
77 	using expression_type_left  = EL;
78 	using expression_type_right = ER;
79 	using derived_type =  tensor_expression <tensor_type,self_type>;
80 
81 	using size_type = typename tensor_type::size_type;
82 
binary_tensor_expressionboost::numeric::ublas::detail::binary_tensor_expression83 	explicit binary_tensor_expression(expression_type_left  const& l, expression_type_right const& r, binary_operation o)
84 	  : el(l) , er(r) , op(o) {}
85 	binary_tensor_expression() = delete;
86 	binary_tensor_expression(const binary_tensor_expression& l) = delete;
binary_tensor_expressionboost::numeric::ublas::detail::binary_tensor_expression87 	binary_tensor_expression(binary_tensor_expression&& l)
88 	  : el(l.el), er(l.er), op(l.op) {}
89 
90 	BOOST_UBLAS_INLINE
operator ()boost::numeric::ublas::detail::binary_tensor_expression91 	decltype(auto)  operator()(size_type i) const { return op(el(i), er(i)); }
92 
93 	expression_type_left const& el;
94 	expression_type_right const& er;
95 	binary_operation op;
96 };
97 
98 /// @brief helper function to simply instantiation of lambda proxy class
99 template<class T, class EL, class ER, class OP>
make_binary_tensor_expression(tensor_expression<T,EL> const & el,tensor_expression<T,ER> const & er,OP op)100 auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, tensor_expression<T,ER> const& er, OP op)
101 {
102 	return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
103 }
104 
105 template<class T, class EL, class ER, class OP>
make_binary_tensor_expression(matrix_expression<EL> const & el,tensor_expression<T,ER> const & er,OP op)106 auto make_binary_tensor_expression( matrix_expression<EL> const& el, tensor_expression<T,ER> const& er, OP op)
107 {
108 	return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
109 }
110 
111 template<class T, class EL, class ER, class OP>
make_binary_tensor_expression(tensor_expression<T,EL> const & el,matrix_expression<ER> const & er,OP op)112 auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, matrix_expression<ER> const& er, OP op)
113 {
114 	return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
115 }
116 
117 template<class T, class EL, class ER, class OP>
make_binary_tensor_expression(vector_expression<EL> const & el,tensor_expression<T,ER> const & er,OP op)118 auto make_binary_tensor_expression( vector_expression<EL> const& el, tensor_expression<T,ER> const& er, OP op)
119 {
120 	return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
121 }
122 
123 template<class T, class EL, class ER, class OP>
make_binary_tensor_expression(tensor_expression<T,EL> const & el,vector_expression<ER> const & er,OP op)124 auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, vector_expression<ER> const& er, OP op)
125 {
126 	return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
127 }
128 
129 
130 
131 template<class T, class E, class OP>
132 struct unary_tensor_expression
133     : public tensor_expression <T, unary_tensor_expression<T,E,OP>>
134 {
135 
136 	using self_type = unary_tensor_expression<T,E,OP>;
137 	using tensor_type  = T;
138 	using expression_type = E;
139 
140 	using derived_type = tensor_expression <T, unary_tensor_expression<T,E,OP>>;
141 
142 	using size_type = typename tensor_type::size_type;
143 
unary_tensor_expressionboost::numeric::ublas::detail::unary_tensor_expression144 	explicit unary_tensor_expression(E const& ee, OP o) : e(ee) , op(o) {}
145 	unary_tensor_expression() = delete;
146 	unary_tensor_expression(const unary_tensor_expression& l) = delete;
unary_tensor_expressionboost::numeric::ublas::detail::unary_tensor_expression147 	unary_tensor_expression(unary_tensor_expression&& l)
148 	  : e(l.e), op(op.l) {}
149 
150 	BOOST_UBLAS_INLINE
operator ()boost::numeric::ublas::detail::unary_tensor_expression151 	decltype(auto) operator()(size_type i) const { return op(e(i)); }
152 
153 	E const& e;
154 	OP op;
155 };
156 
157 // \brief helper function to simply instantiation of lambda proxy class
158 template<class T, class E, class OP>
make_unary_tensor_expression(tensor_expression<T,E> const & e,OP op)159 auto make_unary_tensor_expression( tensor_expression<T,E> const& e, OP op)
160 {
161 	return unary_tensor_expression<T,E,OP>( e() , op);
162 }
163 
164 template<class T, class E, class OP>
make_unary_tensor_expression(matrix_expression<E> const & e,OP op)165 auto make_unary_tensor_expression( matrix_expression<E> const& e, OP op)
166 {
167 	return unary_tensor_expression<T,E,OP>( e() , op);
168 }
169 
170 template<class T, class E, class OP>
make_unary_tensor_expression(vector_expression<E> const & e,OP op)171 auto make_unary_tensor_expression( vector_expression<E> const& e, OP op)
172 {
173 	return unary_tensor_expression<T,E,OP>( e() , op);
174 }
175 
176 
177 }
178 }
179 }
180 }
181 #endif
182