1 | // Copyright (c) 2018-2019 Cem Bassoy |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See |
4 | // accompanying file LICENSE_1_0.txt or copy at |
5 | // http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // The authors gratefully acknowledge the support of |
8 | // Fraunhofer and Google in producing this work |
9 | // which started as a Google Summer of Code project. |
10 | // |
11 | |
12 | |
13 | |
14 | #include <boost/numeric/ublas/tensor/expression_evaluation.hpp> |
15 | #include <boost/numeric/ublas/tensor/expression.hpp> |
16 | #include <boost/numeric/ublas/tensor/tensor.hpp> |
17 | #include <boost/test/unit_test.hpp> |
18 | #include "utility.hpp" |
19 | |
20 | #include <functional> |
21 | |
22 | using test_types = zip<int,long,float,double,std::complex<float>>::with_t<boost::numeric::ublas::first_order, boost::numeric::ublas::last_order>; |
23 | |
24 | |
25 | struct fixture |
26 | { |
27 | using extents_type = boost::numeric::ublas::shape; |
28 | fixture() |
29 | : extents{ |
30 | extents_type{}, // 0 |
31 | |
32 | extents_type{1,1}, // 1 |
33 | extents_type{1,2}, // 2 |
34 | extents_type{2,1}, // 3 |
35 | |
36 | extents_type{2,3}, // 4 |
37 | extents_type{2,3,1}, // 5 |
38 | extents_type{1,2,3}, // 6 |
39 | extents_type{1,1,2,3}, // 7 |
40 | extents_type{1,2,3,1,1}, // 8 |
41 | |
42 | extents_type{4,2,3}, // 9 |
43 | extents_type{4,2,1,3}, // 10 |
44 | extents_type{4,2,1,3,1}, // 11 |
45 | extents_type{1,4,2,1,3,1}} // 12 |
46 | { |
47 | } |
48 | std::vector<extents_type> extents; |
49 | }; |
50 | |
51 | |
52 | |
53 | BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_expression_retrieve_extents, value, test_types, fixture) |
54 | { |
55 | using namespace boost::numeric; |
56 | using value_type = typename value::first_type; |
57 | using layout_type = typename value::second_type; |
58 | using tensor_type = ublas::tensor<value_type, layout_type>; |
59 | |
60 | auto uplus1 = std::bind( std::plus<value_type>{}, std::placeholders::_1, value_type(1) ); |
61 | auto uplus2 = std::bind( std::plus<value_type>{}, value_type(2), std::placeholders::_2 ); |
62 | auto bplus = std::plus <value_type>{}; |
63 | auto bminus = std::minus<value_type>{}; |
64 | |
65 | for(auto const& e : extents) { |
66 | |
67 | auto t = tensor_type(e); |
68 | auto v = value_type{}; |
69 | for(auto& tt: t){ tt = v; v+=value_type{1}; } |
70 | |
71 | |
72 | BOOST_CHECK( ublas::detail::retrieve_extents( t ) == e ); |
73 | |
74 | |
75 | // uexpr1 = t+1 |
76 | // uexpr2 = 2+t |
77 | auto uexpr1 = ublas::detail::make_unary_tensor_expression<tensor_type>( t, uplus1 ); |
78 | auto uexpr2 = ublas::detail::make_unary_tensor_expression<tensor_type>( t, uplus2 ); |
79 | |
80 | BOOST_CHECK( ublas::detail::retrieve_extents( uexpr1 ) == e ); |
81 | BOOST_CHECK( ublas::detail::retrieve_extents( uexpr2 ) == e ); |
82 | |
83 | // bexpr_uexpr = (t+1) + (2+t) |
84 | auto bexpr_uexpr = ublas::detail::make_binary_tensor_expression<tensor_type>( uexpr1, uexpr2, bplus ); |
85 | |
86 | BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_uexpr ) == e ); |
87 | |
88 | |
89 | // bexpr_bexpr_uexpr = ((t+1) + (2+t)) - t |
90 | auto bexpr_bexpr_uexpr = ublas::detail::make_binary_tensor_expression<tensor_type>( bexpr_uexpr, t, bminus ); |
91 | |
92 | BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_bexpr_uexpr ) == e ); |
93 | |
94 | } |
95 | |
96 | |
97 | for(auto i = 0u; i < extents.size()-1; ++i) |
98 | { |
99 | |
100 | auto v = value_type{}; |
101 | |
102 | auto t1 = tensor_type(extents[i]); |
103 | for(auto& tt: t1){ tt = v; v+=value_type{1}; } |
104 | |
105 | auto t2 = tensor_type(extents[i+1]); |
106 | for(auto& tt: t2){ tt = v; v+=value_type{2}; } |
107 | |
108 | BOOST_CHECK( ublas::detail::retrieve_extents( t1 ) != ublas::detail::retrieve_extents( t2 ) ); |
109 | |
110 | // uexpr1 = t1+1 |
111 | // uexpr2 = 2+t2 |
112 | auto uexpr1 = ublas::detail::make_unary_tensor_expression<tensor_type>( t1, uplus1 ); |
113 | auto uexpr2 = ublas::detail::make_unary_tensor_expression<tensor_type>( t2, uplus2 ); |
114 | |
115 | BOOST_CHECK( ublas::detail::retrieve_extents( t1 ) == ublas::detail::retrieve_extents( uexpr1 ) ); |
116 | BOOST_CHECK( ublas::detail::retrieve_extents( t2 ) == ublas::detail::retrieve_extents( uexpr2 ) ); |
117 | BOOST_CHECK( ublas::detail::retrieve_extents( uexpr1 ) != ublas::detail::retrieve_extents( uexpr2 ) ); |
118 | |
119 | // bexpr_uexpr = (t1+1) + (2+t2) |
120 | auto bexpr_uexpr = ublas::detail::make_binary_tensor_expression<tensor_type>( uexpr1, uexpr2, bplus ); |
121 | |
122 | BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_uexpr ) == ublas::detail::retrieve_extents(t1) ); |
123 | |
124 | |
125 | // bexpr_bexpr_uexpr = ((t1+1) + (2+t2)) - t2 |
126 | auto bexpr_bexpr_uexpr1 = ublas::detail::make_binary_tensor_expression<tensor_type>( bexpr_uexpr, t2, bminus ); |
127 | |
128 | BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_bexpr_uexpr1 ) == ublas::detail::retrieve_extents(t2) ); |
129 | |
130 | |
131 | // bexpr_bexpr_uexpr = t2 - ((t1+1) + (2+t2)) |
132 | auto bexpr_bexpr_uexpr2 = ublas::detail::make_binary_tensor_expression<tensor_type>( t2, bexpr_uexpr, bminus ); |
133 | |
134 | BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_bexpr_uexpr2 ) == ublas::detail::retrieve_extents(t2) ); |
135 | } |
136 | } |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_expression_all_extents_equal, value, test_types, fixture) |
145 | { |
146 | using namespace boost::numeric; |
147 | using value_type = typename value::first_type; |
148 | using layout_type = typename value::second_type; |
149 | using tensor_type = ublas::tensor<value_type, layout_type>; |
150 | |
151 | auto uplus1 = std::bind( std::plus<value_type>{}, std::placeholders::_1, value_type(1) ); |
152 | auto uplus2 = std::bind( std::plus<value_type>{}, value_type(2), std::placeholders::_2 ); |
153 | auto bplus = std::plus <value_type>{}; |
154 | auto bminus = std::minus<value_type>{}; |
155 | |
156 | for(auto const& e : extents) { |
157 | |
158 | auto t = tensor_type(e); |
159 | auto v = value_type{}; |
160 | for(auto& tt: t){ tt = v; v+=value_type{1}; } |
161 | |
162 | |
163 | BOOST_CHECK( ublas::detail::all_extents_equal( t , e ) ); |
164 | |
165 | |
166 | // uexpr1 = t+1 |
167 | // uexpr2 = 2+t |
168 | auto uexpr1 = ublas::detail::make_unary_tensor_expression<tensor_type>( t, uplus1 ); |
169 | auto uexpr2 = ublas::detail::make_unary_tensor_expression<tensor_type>( t, uplus2 ); |
170 | |
171 | BOOST_CHECK( ublas::detail::all_extents_equal( uexpr1, e ) ); |
172 | BOOST_CHECK( ublas::detail::all_extents_equal( uexpr2, e ) ); |
173 | |
174 | // bexpr_uexpr = (t+1) + (2+t) |
175 | auto bexpr_uexpr = ublas::detail::make_binary_tensor_expression<tensor_type>( uexpr1, uexpr2, bplus ); |
176 | |
177 | BOOST_CHECK( ublas::detail::all_extents_equal( bexpr_uexpr, e ) ); |
178 | |
179 | |
180 | // bexpr_bexpr_uexpr = ((t+1) + (2+t)) - t |
181 | auto bexpr_bexpr_uexpr = ublas::detail::make_binary_tensor_expression<tensor_type>( bexpr_uexpr, t, bminus ); |
182 | |
183 | BOOST_CHECK( ublas::detail::all_extents_equal( bexpr_bexpr_uexpr , e ) ); |
184 | |
185 | } |
186 | |
187 | |
188 | for(auto i = 0u; i < extents.size()-1; ++i) |
189 | { |
190 | |
191 | auto v = value_type{}; |
192 | |
193 | auto t1 = tensor_type(extents[i]); |
194 | for(auto& tt: t1){ tt = v; v+=value_type{1}; } |
195 | |
196 | auto t2 = tensor_type(extents[i+1]); |
197 | for(auto& tt: t2){ tt = v; v+=value_type{2}; } |
198 | |
199 | BOOST_CHECK( ublas::detail::all_extents_equal( t1, ublas::detail::retrieve_extents(t1) ) ); |
200 | BOOST_CHECK( ublas::detail::all_extents_equal( t2, ublas::detail::retrieve_extents(t2) ) ); |
201 | |
202 | // uexpr1 = t1+1 |
203 | // uexpr2 = 2+t2 |
204 | auto uexpr1 = ublas::detail::make_unary_tensor_expression<tensor_type>( t1, uplus1 ); |
205 | auto uexpr2 = ublas::detail::make_unary_tensor_expression<tensor_type>( t2, uplus2 ); |
206 | |
207 | BOOST_CHECK( ublas::detail::all_extents_equal( uexpr1, ublas::detail::retrieve_extents(uexpr1) ) ); |
208 | BOOST_CHECK( ublas::detail::all_extents_equal( uexpr2, ublas::detail::retrieve_extents(uexpr2) ) ); |
209 | |
210 | // bexpr_uexpr = (t1+1) + (2+t2) |
211 | auto bexpr_uexpr = ublas::detail::make_binary_tensor_expression<tensor_type>( uexpr1, uexpr2, bplus ); |
212 | |
213 | BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_uexpr, ublas::detail::retrieve_extents( bexpr_uexpr ) ) ); |
214 | |
215 | // bexpr_bexpr_uexpr = ((t1+1) + (2+t2)) - t2 |
216 | auto bexpr_bexpr_uexpr1 = ublas::detail::make_binary_tensor_expression<tensor_type>( bexpr_uexpr, t2, bminus ); |
217 | |
218 | BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr1, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr1 ) ) ); |
219 | |
220 | // bexpr_bexpr_uexpr = t2 - ((t1+1) + (2+t2)) |
221 | auto bexpr_bexpr_uexpr2 = ublas::detail::make_binary_tensor_expression<tensor_type>( t2, bexpr_uexpr, bminus ); |
222 | |
223 | BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr2, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr2 ) ) ); |
224 | |
225 | |
226 | // bexpr_uexpr2 = (t1+1) + t2 |
227 | auto bexpr_uexpr2 = ublas::detail::make_binary_tensor_expression<tensor_type>( uexpr1, t2, bplus ); |
228 | BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_uexpr2, ublas::detail::retrieve_extents( bexpr_uexpr2 ) ) ); |
229 | |
230 | |
231 | // bexpr_uexpr2 = ((t1+1) + t2) + t1 |
232 | auto bexpr_bexpr_uexpr3 = ublas::detail::make_binary_tensor_expression<tensor_type>( bexpr_uexpr2, t1, bplus ); |
233 | BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr3, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr3 ) ) ); |
234 | |
235 | // bexpr_uexpr2 = t1 + (((t1+1) + t2) + t1) |
236 | auto bexpr_bexpr_uexpr4 = ublas::detail::make_binary_tensor_expression<tensor_type>( t1, bexpr_bexpr_uexpr3, bplus ); |
237 | BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr4, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr4 ) ) ); |
238 | |
239 | } |
240 | } |
241 | |