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