• 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 
14 #include <boost/numeric/ublas/tensor.hpp>
15 
16 #include <boost/test/unit_test.hpp>
17 #include <boost/multiprecision/cpp_bin_float.hpp>
18 #include "utility.hpp"
19 
20 
21 using double_extended = boost::multiprecision::cpp_bin_float_double_extended;
22 
23 using test_types = zip<int,long,float,double,double_extended>::with_t<boost::numeric::ublas::first_order, boost::numeric::ublas::last_order>;
24 
25 struct fixture
26 {
27 	using extents_type = boost::numeric::ublas::basic_extents<std::size_t>;
fixturefixture28 	fixture()
29 	  : extents{
30 	      extents_type{},    // 0
31 	      extents_type{1,1}, // 1
32 	      extents_type{1,2}, // 2
33 	      extents_type{2,1}, // 3
34 	      extents_type{2,3}, // 4
35 	      extents_type{2,3,1}, // 5
36 	      extents_type{4,1,3}, // 6
37 	      extents_type{1,2,3}, // 7
38 	      extents_type{4,2,3}, // 8
39 	      extents_type{4,2,3,5}} // 9
40 	{
41 	}
42 	std::vector<extents_type> extents;
43 };
44 
45 BOOST_AUTO_TEST_SUITE(test_tensor_arithmetic_operations, * boost::unit_test::depends_on("test_tensor"))
46 
47 
48 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_binary_arithmetic_operations,value,test_types,fixture)49 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_binary_arithmetic_operations, value,  test_types, fixture)
50 {
51 	using namespace boost::numeric;
52 	using value_type  = typename value::first_type;
53 	using layout_type = typename value::second_type;
54 	using tensor_type = ublas::tensor<value_type, layout_type>;
55 
56 
57 	auto check = [](auto const& e)
58 	{
59 		auto t  = tensor_type (e);
60 		auto t2 = tensor_type (e);
61 		auto r  = tensor_type (e);
62 		auto v  = value_type  {};
63 
64 		std::iota(t.begin(), t.end(), v);
65 		std::iota(t2.begin(), t2.end(), v+2);
66 
67 		r = t + t + t + t2;
68 
69 		for(auto i = 0ul; i < t.size(); ++i)
70 			BOOST_CHECK_EQUAL ( r(i), 3*t(i) + t2(i) );
71 
72 
73 		r = t2 / (t+3) * (t+1) - t2; // r = ( t2/ ((t+3)*(t+1)) ) - t2
74 
75 		for(auto i = 0ul; i < t.size(); ++i)
76 			BOOST_CHECK_EQUAL ( r(i), t2(i) / (t(i)+3)*(t(i)+1) - t2(i) );
77 
78 		r = 3+t2 / (t+3) * (t+1) * t - t2; // r = 3+( t2/ ((t+3)*(t+1)*t) ) - t2
79 
80 		for(auto i = 0ul; i < t.size(); ++i)
81 			BOOST_CHECK_EQUAL ( r(i), 3+t2(i) / (t(i)+3)*(t(i)+1)*t(i) - t2(i) );
82 
83 		r = t2 - t + t2 - t;
84 
85 		for(auto i = 0ul; i < r.size(); ++i)
86 			BOOST_CHECK_EQUAL ( r(i), 4 );
87 
88 
89 		r = tensor_type (e,1) + tensor_type (e,1);
90 
91 		for(auto i = 0ul; i < r.size(); ++i)
92 			BOOST_CHECK_EQUAL ( r(i), 2 );
93 
94 		r = t * t * t * t2;
95 
96 		for(auto i = 0ul; i < t.size(); ++i)
97 			BOOST_CHECK_EQUAL ( r(i), t(i)*t(i)*t(i)*t2(i) );
98 
99 		r = (t2/t2) * (t2/t2);
100 
101 		for(auto i = 0ul; i < t.size(); ++i)
102 			BOOST_CHECK_EQUAL ( r(i), 1 );
103 	};
104 
105 	for(auto const& e : extents)
106 		check(e);
107 
108 
109 	BOOST_CHECK_NO_THROW ( tensor_type t = tensor_type(extents.at(0)) + tensor_type(extents.at(0))  );
110 	BOOST_CHECK_THROW    ( tensor_type t = tensor_type(extents.at(0)) + tensor_type(extents.at(2)), std::runtime_error  );
111 	BOOST_CHECK_THROW    ( tensor_type t = tensor_type(extents.at(1)) + tensor_type(extents.at(2)), std::runtime_error  );
112 
113 
114 }
115 
116 
117 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_unary_arithmetic_operations,value,test_types,fixture)118 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_unary_arithmetic_operations, value,  test_types, fixture)
119 {
120 	using namespace boost::numeric;
121 	using value_type  = typename value::first_type;
122 	using layout_type = typename value::second_type;
123 	using tensor_type = ublas::tensor<value_type, layout_type>;
124 
125 
126 	auto check = [](auto const& e)
127 	{
128 		auto t  = tensor_type (e);
129 		auto t2 = tensor_type (e);
130 		auto v  = value_type  {};
131 
132 		std::iota(t.begin(), t.end(), v);
133 		std::iota(t2.begin(), t2.end(), v+2);
134 
135 		tensor_type r1 = t + 2 + t + 2;
136 
137 		for(auto i = 0ul; i < t.size(); ++i)
138 			BOOST_CHECK_EQUAL ( r1(i), 2*t(i) + 4 );
139 
140 		tensor_type r2 = 2 + t + 2 + t;
141 
142 		for(auto i = 0ul; i < t.size(); ++i)
143 			BOOST_CHECK_EQUAL ( r2(i), 2*t(i) + 4 );
144 
145 		tensor_type r3 = (t-2) + (t-2);
146 
147 		for(auto i = 0ul; i < t.size(); ++i)
148 			BOOST_CHECK_EQUAL ( r3(i), 2*t(i) - 4 );
149 
150 		tensor_type r4 = (t*2) * (3*t);
151 
152 		for(auto i = 0ul; i < t.size(); ++i)
153 			BOOST_CHECK_EQUAL ( r4(i), 2*3*t(i)*t(i) );
154 
155 		tensor_type r5 = (t2*2) / (2*t2) * t2;
156 
157 		for(auto i = 0ul; i < t.size(); ++i)
158 			BOOST_CHECK_EQUAL ( r5(i), (t2(i)*2) / (2*t2(i)) * t2(i) );
159 
160 		tensor_type r6 = (t2/2+1) / (2/t2+1) / t2;
161 
162 		for(auto i = 0ul; i < t.size(); ++i)
163 			BOOST_CHECK_EQUAL ( r6(i), (t2(i)/2+1) / (2/t2(i)+1) / t2(i) );
164 
165 	};
166 
167 	for(auto const& e : extents)
168 		check(e);
169 
170 	BOOST_CHECK_NO_THROW ( tensor_type t = tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(0))  );
171 	BOOST_CHECK_THROW    ( tensor_type t = tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(2)), std::runtime_error  );
172 	BOOST_CHECK_THROW    ( tensor_type t = tensor_type(extents.at(1)) + 2 + tensor_type(extents.at(2)), std::runtime_error  );
173 	BOOST_CHECK_THROW    ( tensor_type t = tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + tensor_type(extents.at(1)), std::runtime_error  );
174 	BOOST_CHECK_THROW    ( tensor_type t = tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(1)), std::runtime_error  );
175 }
176 
177 
178 
179 
180 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_assign_arithmetic_operations,value,test_types,fixture)181 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_assign_arithmetic_operations, value,  test_types, fixture)
182 {
183 	using namespace boost::numeric;
184 	using value_type  = typename value::first_type;
185 	using layout_type = typename value::second_type;
186 	using tensor_type = ublas::tensor<value_type, layout_type>;
187 
188 
189 	auto check = [](auto const& e)
190 	{
191 		auto t  = tensor_type (e);
192 		auto t2 = tensor_type (e);
193 		auto r  = tensor_type (e);
194 		auto v  = value_type  {};
195 
196 		std::iota(t.begin(), t.end(), v);
197 		std::iota(t2.begin(), t2.end(), v+2);
198 
199 		r  = t + 2;
200 		r += t;
201 		r += 2;
202 
203 		for(auto i = 0ul; i < t.size(); ++i)
204 			BOOST_CHECK_EQUAL ( r(i), 2*t(i) + 4 );
205 
206 		r  = 2 + t;
207 		r += t;
208 		r += 2;
209 
210 		for(auto i = 0ul; i < t.size(); ++i)
211 			BOOST_CHECK_EQUAL ( r(i), 2*t(i) + 4 );
212 
213 		for(auto i = 0ul; i < t.size(); ++i)
214 			BOOST_CHECK_EQUAL ( r(i), 2*t(i) + 4 );
215 
216 		r = (t-2);
217 		r += t;
218 		r -= 2;
219 
220 		for(auto i = 0ul; i < t.size(); ++i)
221 			BOOST_CHECK_EQUAL ( r(i), 2*t(i) - 4 );
222 
223 		r  = (t*2);
224 		r *= 3;
225 		r *= t;
226 
227 		for(auto i = 0ul; i < t.size(); ++i)
228 			BOOST_CHECK_EQUAL ( r(i), 2*3*t(i)*t(i) );
229 
230 		r  = (t2*2);
231 		r /= 2;
232 		r /= t2;
233 		r *= t2;
234 
235 		for(auto i = 0ul; i < t.size(); ++i)
236 			BOOST_CHECK_EQUAL ( r(i), (t2(i)*2) / (2*t2(i)) * t2(i) );
237 
238 		r  = (t2/2+1);
239 		r /= (2/t2+1);
240 		r /= t2;
241 
242 		for(auto i = 0ul; i < t.size(); ++i)
243 			BOOST_CHECK_EQUAL ( r(i), (t2(i)/2+1) / (2/t2(i)+1) / t2(i) );
244 
245 		tensor_type q = -r;
246 		for(auto i = 0ul; i < t.size(); ++i)
247 			BOOST_CHECK_EQUAL ( q(i), -r(i) );
248 
249 		tensor_type p = +r;
250 		for(auto i = 0ul; i < t.size(); ++i)
251 			BOOST_CHECK_EQUAL ( p(i), r(i) );
252 	};
253 
254 	for(auto const& e : extents)
255 		check(e);
256 
257 	auto r  = tensor_type (extents.at(0));
258 
259 	BOOST_CHECK_NO_THROW ( r += tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(0))  );
260 	BOOST_CHECK_THROW    ( r += tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(2)), std::runtime_error  );
261 	BOOST_CHECK_THROW    ( r += tensor_type(extents.at(1)) + 2 + tensor_type(extents.at(2)), std::runtime_error  );
262 	BOOST_CHECK_THROW    ( r += tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + tensor_type(extents.at(1)), std::runtime_error  );
263 	BOOST_CHECK_THROW    ( r += tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(1)), std::runtime_error  );
264 }
265 
266 
267 BOOST_AUTO_TEST_SUITE_END()
268