• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <iostream>
14 #include <random>
15 #include <boost/numeric/ublas/tensor.hpp>
16 #include <boost/numeric/ublas/matrix.hpp>
17 #include <boost/test/unit_test.hpp>
18 
19 #include "utility.hpp"
20 
21 // BOOST_AUTO_TEST_SUITE ( test_tensor_matrix_interoperability, * boost::unit_test::depends_on("test_tensor") ) ;
22 
23 BOOST_AUTO_TEST_SUITE ( test_tensor_matrix_interoperability )
24 
25 using test_types = zip<int,long,float,double>::with_t<boost::numeric::ublas::first_order, boost::numeric::ublas::last_order>;
26 
27 
BOOST_AUTO_TEST_CASE_TEMPLATE(test_tensor_matrix_copy_ctor,value,test_types)28 BOOST_AUTO_TEST_CASE_TEMPLATE( test_tensor_matrix_copy_ctor, value,  test_types)
29 {
30 	using namespace boost::numeric;
31 	using value_type  = typename value::first_type;
32 	using layout_type = typename value::second_type;
33 	using tensor_type = ublas::tensor<value_type, layout_type>;
34 	using matrix_type = typename tensor_type::matrix_type;
35 
36 	tensor_type a1 = matrix_type();
37 	BOOST_CHECK_EQUAL( a1.size() , 0ul );
38 	BOOST_CHECK( a1.empty() );
39 	BOOST_CHECK_EQUAL( a1.data() , nullptr);
40 
41 	tensor_type a2 = matrix_type(1,1);
42 	BOOST_CHECK_EQUAL(  a2.size() , 1 );
43 	BOOST_CHECK( !a2.empty() );
44 	BOOST_CHECK_NE(  a2.data() , nullptr);
45 
46 	tensor_type a3 = matrix_type(2,1);
47 	BOOST_CHECK_EQUAL(  a3.size() , 2 );
48 	BOOST_CHECK( !a3.empty() );
49 	BOOST_CHECK_NE(  a3.data() , nullptr);
50 
51 	tensor_type a4 = matrix_type(1,2);
52 	BOOST_CHECK_EQUAL(  a4.size() , 2 );
53 	BOOST_CHECK( !a4.empty() );
54 	BOOST_CHECK_NE(  a4.data() , nullptr);
55 
56 	tensor_type a5 = matrix_type(2,3);
57 	BOOST_CHECK_EQUAL(  a5.size() , 6 );
58 	BOOST_CHECK( !a5.empty() );
59 	BOOST_CHECK_NE(  a5.data() , nullptr);
60 }
61 
62 
BOOST_AUTO_TEST_CASE_TEMPLATE(test_tensor_vector_copy_ctor,value,test_types)63 BOOST_AUTO_TEST_CASE_TEMPLATE( test_tensor_vector_copy_ctor, value,  test_types)
64 {
65 	using namespace boost::numeric;
66 	using value_type  = typename value::first_type;
67 	using layout_type = typename value::second_type;
68 	using tensor_type = ublas::tensor<value_type, layout_type>;
69 	using vector_type = typename tensor_type::vector_type;
70 
71 	tensor_type a1 = vector_type();
72 	BOOST_CHECK_EQUAL( a1.size() , 0ul );
73 	BOOST_CHECK( a1.empty() );
74 	BOOST_CHECK_EQUAL( a1.data() , nullptr);
75 
76 	tensor_type a2 = vector_type(1);
77 	BOOST_CHECK_EQUAL(  a2.size() , 1 );
78 	BOOST_CHECK( !a2.empty() );
79 	BOOST_CHECK_NE(  a2.data() , nullptr);
80 
81 	tensor_type a3 = vector_type(2);
82 	BOOST_CHECK_EQUAL(  a3.size() , 2 );
83 	BOOST_CHECK( !a3.empty() );
84 	BOOST_CHECK_NE(  a3.data() , nullptr);
85 
86 	tensor_type a4 = vector_type(2);
87 	BOOST_CHECK_EQUAL(  a4.size() , 2 );
88 	BOOST_CHECK( !a4.empty() );
89 	BOOST_CHECK_NE(  a4.data() , nullptr);
90 
91 	tensor_type a5 = vector_type(3);
92 	BOOST_CHECK_EQUAL(  a5.size() , 3 );
93 	BOOST_CHECK( !a5.empty() );
94 	BOOST_CHECK_NE(  a5.data() , nullptr);
95 }
96 
97 
98 struct fixture
99 {
100 	using extents_type = boost::numeric::ublas::basic_extents<std::size_t>;
fixturefixture101 	fixture()
102 	  : extents{
103 				extents_type{1,1},  // 1
104 				extents_type{1,2},  // 2
105 				extents_type{2,1},  // 3
106 				extents_type{2,3},  // 4
107 				extents_type{9,7},  // 5
108 				extents_type{9,11}, // 6
109 				extents_type{12,12}, // 7
110 	      extents_type{15,17}} // 8
111 	{
112 	}
113 	std::vector<extents_type> extents;
114 };
115 
116 
117 
118 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_matrix_copy_ctor_extents,value,test_types,fixture)119 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_matrix_copy_ctor_extents, value,  test_types, fixture )
120 {
121 	using namespace boost::numeric;
122 	using value_type  = typename value::first_type;
123 	using layout_type = typename value::second_type;
124 	using tensor_type = ublas::tensor<value_type, layout_type>;
125 	using matrix_type = typename tensor_type::matrix_type;
126 
127 	auto check = [](auto const& e) {
128 		assert(e.size()==2);
129 		tensor_type t = matrix_type{e[0],e[1]};
130 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
131 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
132 		BOOST_CHECK       ( !t.empty()    );
133 		BOOST_CHECK_NE    (  t.data() , nullptr);
134 	};
135 
136 	for(auto const& e : extents)
137 		check(e);
138 }
139 
140 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_vector_copy_ctor_extents,value,test_types,fixture)141 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_vector_copy_ctor_extents, value,  test_types, fixture )
142 {
143 	using namespace boost::numeric;
144 	using value_type  = typename value::first_type;
145 	using layout_type = typename value::second_type;
146 	using tensor_type = ublas::tensor<value_type, layout_type>;
147 	using vector_type = typename tensor_type::vector_type;
148 
149 	auto check = [](auto const& e) {
150 		assert(e.size()==2);
151 		if(e.empty())
152 			return;
153 
154 		tensor_type t = vector_type(e.product());
155 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
156 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
157 		BOOST_CHECK       ( !t.empty()    );
158 		BOOST_CHECK_NE    (  t.data() , nullptr);
159 	};
160 
161 	for(auto const& e : extents)
162 		check(e);
163 }
164 
165 
166 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_matrix_copy_assignment,value,test_types,fixture)167 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_matrix_copy_assignment, value,  test_types, fixture )
168 {
169 	using namespace boost::numeric;
170 	using value_type  = typename value::first_type;
171 	using layout_type = typename value::second_type;
172 	using tensor_type = ublas::tensor<value_type, layout_type>;
173 	using matrix_type = typename tensor_type::matrix_type;
174 
175 	auto check = [](auto const& e)
176 	{
177 		assert(e.size() == 2);
178 		auto t = tensor_type{};
179 		auto r = matrix_type(e[0],e[1]);
180 		std::iota(r.data().begin(),r.data().end(), 1);
181 		t = r;
182 
183 		BOOST_CHECK_EQUAL (  t.extents().at(0) , e.at(0) );
184 		BOOST_CHECK_EQUAL (  t.extents().at(1) , e.at(1) );
185 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
186 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
187 		BOOST_CHECK       ( !t.empty()    );
188 		BOOST_CHECK_NE    (  t.data() , nullptr);
189 
190 		for(auto j = 0ul; j < t.size(1); ++j){
191 			for(auto i = 0ul; i < t.size(0); ++i){
192 				BOOST_CHECK_EQUAL( t.at(i,j), r(i,j)  );
193 			}
194 		}
195 	};
196 
197 	for(auto const& e : extents)
198 		check(e);
199 }
200 
201 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_vector_copy_assignment,value,test_types,fixture)202 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_vector_copy_assignment, value,  test_types, fixture )
203 {
204 	using namespace boost::numeric;
205 	using value_type  = typename value::first_type;
206 	using layout_type = typename value::second_type;
207 	using tensor_type = ublas::tensor<value_type, layout_type>;
208 	using vector_type = typename tensor_type::vector_type;
209 
210 	auto check = [](auto const& e)
211 	{
212 		assert(e.size() == 2);
213 		auto t = tensor_type{};
214 		auto r = vector_type(e[0]*e[1]);
215 		std::iota(r.data().begin(),r.data().end(), 1);
216 		t = r;
217 
218 		BOOST_CHECK_EQUAL (  t.extents().at(0) , e.at(0)*e.at(1) );
219 		BOOST_CHECK_EQUAL (  t.extents().at(1) , 1);
220 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
221 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
222 		BOOST_CHECK       ( !t.empty()    );
223 		BOOST_CHECK_NE    (  t.data() , nullptr);
224 
225 		for(auto i = 0ul; i < t.size(); ++i){
226 			BOOST_CHECK_EQUAL( t[i], r(i)  );
227 		}
228 	};
229 
230 	for(auto const& e : extents)
231 		check(e);
232 }
233 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_matrix_move_assignment,value,test_types,fixture)234 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_matrix_move_assignment, value,  test_types, fixture )
235 {
236 	using namespace boost::numeric;
237 	using value_type  = typename value::first_type;
238 	using layout_type = typename value::second_type;
239 	using tensor_type = ublas::tensor<value_type, layout_type>;
240 	using matrix_type = typename tensor_type::matrix_type;
241 
242 	auto check = [](auto const& e)
243 	{
244 		assert(e.size() == 2);
245 		auto t = tensor_type{};
246 		auto r = matrix_type(e[0],e[1]);
247 		std::iota(r.data().begin(),r.data().end(), 1);
248 		auto q = r;
249 		t = std::move(r);
250 
251 		BOOST_CHECK_EQUAL (  t.extents().at(0) , e.at(0) );
252 		BOOST_CHECK_EQUAL (  t.extents().at(1) , e.at(1) );
253 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
254 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
255 		BOOST_CHECK       ( !t.empty()    );
256 		BOOST_CHECK_NE    (  t.data() , nullptr);
257 
258 		for(auto j = 0ul; j < t.size(1); ++j){
259 			for(auto i = 0ul; i < t.size(0); ++i){
260 				BOOST_CHECK_EQUAL( t.at(i,j), q(i,j)  );
261 			}
262 		}
263 	};
264 
265 	for(auto const& e : extents)
266 		check(e);
267 }
268 
269 
270 
271 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_vector_move_assignment,value,test_types,fixture)272 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_vector_move_assignment, value,  test_types, fixture )
273 {
274 	using namespace boost::numeric;
275 	using value_type  = typename value::first_type;
276 	using layout_type = typename value::second_type;
277 	using tensor_type = ublas::tensor<value_type, layout_type>;
278 	using vector_type = typename tensor_type::vector_type;
279 
280 	auto check = [](auto const& e)
281 	{
282 		assert(e.size() == 2);
283 		auto t = tensor_type{};
284 		auto r = vector_type(e[0]*e[1]);
285 		std::iota(r.data().begin(),r.data().end(), 1);
286 		auto q = r;
287 		t = std::move(r);
288 
289 		BOOST_CHECK_EQUAL (  t.extents().at(0) , e.at(0) * e.at(1));
290 		BOOST_CHECK_EQUAL (  t.extents().at(1) , 1);
291 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
292 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
293 		BOOST_CHECK       ( !t.empty()    );
294 		BOOST_CHECK_NE    (  t.data() , nullptr);
295 
296 		for(auto i = 0ul; i < t.size(); ++i){
297 			BOOST_CHECK_EQUAL( t[i], q(i)  );
298 		}
299 	};
300 
301 	for(auto const& e : extents)
302 		check(e);
303 }
304 
305 
306 
307 
308 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_matrix_expressions,value,test_types,fixture)309 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_matrix_expressions, value,  test_types, fixture )
310 {
311 	using namespace boost::numeric;
312 	using value_type  = typename value::first_type;
313 	using layout_type = typename value::second_type;
314 	using tensor_type = ublas::tensor<value_type, layout_type>;
315 	using matrix_type = typename tensor_type::matrix_type;
316 
317 	auto check = [](auto const& e)
318 	{
319 		assert(e.size() == 2);
320 		auto t = tensor_type{};
321 		auto r = matrix_type(e[0],e[1]);
322 		std::iota(r.data().begin(),r.data().end(), 1);
323 		t = r + 3*r;
324 		tensor_type s = r + 3*r;
325 		tensor_type q = s + r + 3*r + s; // + 3*r
326 
327 
328 		BOOST_CHECK_EQUAL (  t.extents().at(0) , e.at(0) );
329 		BOOST_CHECK_EQUAL (  t.extents().at(1) , e.at(1) );
330 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
331 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
332 		BOOST_CHECK       ( !t.empty()    );
333 		BOOST_CHECK_NE    (  t.data() , nullptr);
334 
335 		BOOST_CHECK_EQUAL (  s.extents().at(0) , e.at(0) );
336 		BOOST_CHECK_EQUAL (  s.extents().at(1) , e.at(1) );
337 		BOOST_CHECK_EQUAL (  s.size() , e.product() );
338 		BOOST_CHECK_EQUAL (  s.rank() , e.size() );
339 		BOOST_CHECK       ( !s.empty()    );
340 		BOOST_CHECK_NE    (  s.data() , nullptr);
341 
342 		BOOST_CHECK_EQUAL (  q.extents().at(0) , e.at(0) );
343 		BOOST_CHECK_EQUAL (  q.extents().at(1) , e.at(1) );
344 		BOOST_CHECK_EQUAL (  q.size() , e.product() );
345 		BOOST_CHECK_EQUAL (  q.rank() , e.size() );
346 		BOOST_CHECK       ( !q.empty()    );
347 		BOOST_CHECK_NE    (  q.data() , nullptr);
348 
349 
350 		for(auto j = 0ul; j < t.size(1); ++j){
351 			for(auto i = 0ul; i < t.size(0); ++i){
352 				BOOST_CHECK_EQUAL( t.at(i,j), 4*r(i,j)  );
353 				BOOST_CHECK_EQUAL( s.at(i,j), t.at(i,j)  );
354 				BOOST_CHECK_EQUAL( q.at(i,j), 3*s.at(i,j)  );
355 			}
356 		}
357 	};
358 
359 	for(auto const& e : extents)
360 		check(e);
361 }
362 
363 
364 
365 
366 
367 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_vector_expressions,value,test_types,fixture)368 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_vector_expressions, value,  test_types, fixture )
369 {
370 	using namespace boost::numeric;
371 	using value_type  = typename value::first_type;
372 	using layout_type = typename value::second_type;
373 	using tensor_type = ublas::tensor<value_type, layout_type>;
374 	using vector_type = typename tensor_type::vector_type;
375 
376 	auto check = [](auto const& e)
377 	{
378 		assert(e.size() == 2);
379 		auto t = tensor_type{};
380 		auto r = vector_type(e[0]*e[1]);
381 		std::iota(r.data().begin(),r.data().end(), 1);
382 		t = r + 3*r;
383 		tensor_type s = r + 3*r;
384 		tensor_type q = s + r + 3*r + s; // + 3*r
385 
386 
387 		BOOST_CHECK_EQUAL (  t.extents().at(0) , e.at(0)*e.at(1) );
388 		BOOST_CHECK_EQUAL (  t.extents().at(1) , 1);
389 		BOOST_CHECK_EQUAL (  t.size() , e.product() );
390 		BOOST_CHECK_EQUAL (  t.rank() , e.size() );
391 		BOOST_CHECK       ( !t.empty()    );
392 		BOOST_CHECK_NE    (  t.data() , nullptr);
393 
394 		BOOST_CHECK_EQUAL (  s.extents().at(0) , e.at(0)*e.at(1) );
395 		BOOST_CHECK_EQUAL (  s.extents().at(1) , 1);
396 		BOOST_CHECK_EQUAL (  s.size() , e.product() );
397 		BOOST_CHECK_EQUAL (  s.rank() , e.size() );
398 		BOOST_CHECK       ( !s.empty()    );
399 		BOOST_CHECK_NE    (  s.data() , nullptr);
400 
401 		BOOST_CHECK_EQUAL (  q.extents().at(0) , e.at(0)*e.at(1) );
402 		BOOST_CHECK_EQUAL (  q.extents().at(1) , 1);
403 		BOOST_CHECK_EQUAL (  q.size() , e.product() );
404 		BOOST_CHECK_EQUAL (  q.rank() , e.size() );
405 		BOOST_CHECK       ( !q.empty()    );
406 		BOOST_CHECK_NE    (  q.data() , nullptr);
407 
408 
409 
410 		for(auto i = 0ul; i < t.size(); ++i){
411 			BOOST_CHECK_EQUAL( t.at(i), 4*r(i)  );
412 			BOOST_CHECK_EQUAL( s.at(i), t.at(i)  );
413 			BOOST_CHECK_EQUAL( q.at(i), 3*s.at(i)  );
414 		}
415 	};
416 
417 	for(auto const& e : extents)
418 		check(e);
419 }
420 
421 
422 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_matrix_vector_expressions,value,test_types,fixture)423 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_matrix_vector_expressions, value,  test_types, fixture )
424 {
425 	using namespace boost::numeric;
426 	using value_type  = typename value::first_type;
427 	using layout_type = typename value::second_type;
428 	using tensor_type = ublas::tensor<value_type, layout_type>;
429 	using matrix_type = typename tensor_type::matrix_type;
430 	using vector_type = typename tensor_type::vector_type;
431 
432 	auto check = [](auto const& e)
433 	{
434 		if(e.product() <= 2)
435 			return;
436 		assert(e.size() == 2);
437 		auto Q = tensor_type{e[0],1};
438 		auto A = matrix_type(e[0],e[1]);
439 		auto b = vector_type(e[1]);
440 		auto c = vector_type(e[0]);
441 		std::iota(b.data().begin(),b.data().end(), 1);
442 		std::fill(A.data().begin(),A.data().end(), 1);
443 		std::fill(c.data().begin(),c.data().end(), 2);
444 		std::fill(Q.begin(),Q.end(), 2);
445 
446 		tensor_type T = Q + (ublas::prod(A , b) + 2*c) + 3*Q;
447 
448 		BOOST_CHECK_EQUAL (  T.extents().at(0) , Q.extents().at(0) );
449 		BOOST_CHECK_EQUAL (  T.extents().at(1) , Q.extents().at(1));
450 		BOOST_CHECK_EQUAL (  T.size() , Q.size() );
451 		BOOST_CHECK_EQUAL (  T.size() , c.size() );
452 		BOOST_CHECK_EQUAL (  T.rank() , Q.rank() );
453 		BOOST_CHECK       ( !T.empty()    );
454 		BOOST_CHECK_NE    (  T.data() , nullptr);
455 
456 		for(auto i = 0ul; i < T.size(); ++i){
457 			auto n = e[1];
458 			auto ab = n * (n+1) / 2;
459 			BOOST_CHECK_EQUAL( T(i), ab+4*Q(0)+2*c(0)  );
460 		}
461 
462 	};
463 
464 
465 
466 	for(auto const& e : extents)
467 		check(e);
468 }
469 
470 
471 BOOST_AUTO_TEST_SUITE_END()
472 
473