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/operators_comparison.hpp>
15 #include <boost/numeric/ublas/tensor/operators_arithmetic.hpp>
16 #include <boost/numeric/ublas/tensor/tensor.hpp>
17 #include <boost/test/unit_test.hpp>
18 #include <boost/multiprecision/cpp_bin_float.hpp>
19 #include "utility.hpp"
20
21
22 using double_extended = boost::multiprecision::cpp_bin_float_double_extended;
23
24 using test_types = zip<int,long,float,double,double_extended>::with_t<boost::numeric::ublas::first_order, boost::numeric::ublas::last_order>;
25
26 struct fixture {
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_comparison, * boost::unit_test::depends_on("test_tensor"))
46
47
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_comparison,value,test_types,fixture)48 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_comparison, value, test_types, fixture)
49 {
50 using namespace boost::numeric;
51 using value_type = typename value::first_type;
52 using layout_type = typename value::second_type;
53 using tensor_type = ublas::tensor<value_type, layout_type>;
54
55
56 auto check = [](auto const& e)
57 {
58 auto t = tensor_type (e);
59 auto t2 = tensor_type (e);
60 auto v = value_type {};
61
62 std::iota(t.begin(), t.end(), v);
63 std::iota(t2.begin(), t2.end(), v+2);
64
65 BOOST_CHECK( t == t );
66 BOOST_CHECK( t != t2 );
67
68 if(t.empty())
69 return;
70
71 BOOST_CHECK(!(t < t));
72 BOOST_CHECK(!(t > t));
73 BOOST_CHECK( t < t2 );
74 BOOST_CHECK( t2 > t );
75 BOOST_CHECK( t <= t );
76 BOOST_CHECK( t >= t );
77 BOOST_CHECK( t <= t2 );
78 BOOST_CHECK( t2 >= t );
79 BOOST_CHECK( t2 >= t2 );
80 BOOST_CHECK( t2 >= t );
81 };
82
83 for(auto const& e : extents)
84 check(e);
85
86 auto e0 = extents.at(0);
87 auto e1 = extents.at(1);
88 auto e2 = extents.at(2);
89
90
91 auto b = false;
92 BOOST_CHECK_NO_THROW ( b = (tensor_type(e0) == tensor_type(e0)));
93 BOOST_CHECK_NO_THROW ( b = (tensor_type(e1) == tensor_type(e2)));
94 BOOST_CHECK_NO_THROW ( b = (tensor_type(e0) == tensor_type(e2)));
95 BOOST_CHECK_NO_THROW ( b = (tensor_type(e1) != tensor_type(e2)));
96
97 BOOST_CHECK_THROW ( b = (tensor_type(e1) >= tensor_type(e2)), std::runtime_error );
98 BOOST_CHECK_THROW ( b = (tensor_type(e1) <= tensor_type(e2)), std::runtime_error );
99 BOOST_CHECK_THROW ( b = (tensor_type(e1) < tensor_type(e2)), std::runtime_error );
100 BOOST_CHECK_THROW ( b = (tensor_type(e1) > tensor_type(e2)), std::runtime_error );
101
102 }
103
104
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_comparison_with_tensor_expressions,value,test_types,fixture)105 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_comparison_with_tensor_expressions, value, test_types, fixture)
106 {
107 using namespace boost::numeric;
108 using value_type = typename value::first_type;
109 using layout_type = typename value::second_type;
110 using tensor_type = ublas::tensor<value_type, layout_type>;
111
112
113 auto check = [](auto const& e)
114 {
115 auto t = tensor_type (e);
116 auto t2 = tensor_type (e);
117 auto v = value_type {};
118
119 std::iota(t.begin(), t.end(), v);
120 std::iota(t2.begin(), t2.end(), v+2);
121
122 BOOST_CHECK( t == t );
123 BOOST_CHECK( t != t2 );
124
125 if(t.empty())
126 return;
127
128 BOOST_CHECK( !(t < t) );
129 BOOST_CHECK( !(t > t) );
130 BOOST_CHECK( t < (t2+t) );
131 BOOST_CHECK( (t2+t) > t );
132 BOOST_CHECK( t <= (t+t) );
133 BOOST_CHECK( (t+t2) >= t );
134 BOOST_CHECK( (t2+t2+2) >= t);
135 BOOST_CHECK( 2*t2 > t );
136 BOOST_CHECK( t < 2*t2 );
137 BOOST_CHECK( 2*t2 > t);
138 BOOST_CHECK( 2*t2 >= t2 );
139 BOOST_CHECK( t2 <= 2*t2);
140 BOOST_CHECK( 3*t2 >= t );
141
142 };
143
144 for(auto const& e : extents)
145 check(e);
146
147 auto e0 = extents.at(0);
148 auto e1 = extents.at(1);
149 auto e2 = extents.at(2);
150
151 auto b = false;
152 BOOST_CHECK_NO_THROW (b = tensor_type(e0) == (tensor_type(e0) + tensor_type(e0)) );
153 BOOST_CHECK_NO_THROW (b = tensor_type(e1) == (tensor_type(e2) + tensor_type(e2)) );
154 BOOST_CHECK_NO_THROW (b = tensor_type(e0) == (tensor_type(e2) + 2) );
155 BOOST_CHECK_NO_THROW (b = tensor_type(e1) != (2 + tensor_type(e2)) );
156
157 BOOST_CHECK_NO_THROW (b = (tensor_type(e0) + tensor_type(e0)) == tensor_type(e0) );
158 BOOST_CHECK_NO_THROW (b = (tensor_type(e2) + tensor_type(e2)) == tensor_type(e1) );
159 BOOST_CHECK_NO_THROW (b = (tensor_type(e2) + 2) == tensor_type(e0) );
160 BOOST_CHECK_NO_THROW (b = (2 + tensor_type(e2)) != tensor_type(e1) );
161
162 BOOST_CHECK_THROW (b = tensor_type(e1) >= (tensor_type(e2) + tensor_type(e2)), std::runtime_error );
163 BOOST_CHECK_THROW (b = tensor_type(e1) <= (tensor_type(e2) + tensor_type(e2)), std::runtime_error );
164 BOOST_CHECK_THROW (b = tensor_type(e1) < (tensor_type(e2) + tensor_type(e2)), std::runtime_error );
165 BOOST_CHECK_THROW (b = tensor_type(e1) > (tensor_type(e2) + tensor_type(e2)), std::runtime_error );
166
167 BOOST_CHECK_THROW (b = tensor_type(e1) >= (tensor_type(e2) + 2), std::runtime_error );
168 BOOST_CHECK_THROW (b = tensor_type(e1) <= (2 + tensor_type(e2)), std::runtime_error );
169 BOOST_CHECK_THROW (b = tensor_type(e1) < (tensor_type(e2) + 3), std::runtime_error );
170 BOOST_CHECK_THROW (b = tensor_type(e1) > (4 + tensor_type(e2)), std::runtime_error );
171
172 }
173
174
175
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_comparison_with_scalar,value,test_types,fixture)176 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_comparison_with_scalar, value, test_types, fixture)
177 {
178 using namespace boost::numeric;
179 using value_type = typename value::first_type;
180 using layout_type = typename value::second_type;
181 using tensor_type = ublas::tensor<value_type, layout_type>;
182
183
184 auto check = [](auto const& e)
185 {
186
187 BOOST_CHECK( tensor_type(e,value_type{2}) == tensor_type(e,value_type{2}) );
188 BOOST_CHECK( tensor_type(e,value_type{2}) != tensor_type(e,value_type{1}) );
189
190 if(e.empty())
191 return;
192
193 BOOST_CHECK( !(tensor_type(e,2) < 2) );
194 BOOST_CHECK( !(tensor_type(e,2) > 2) );
195 BOOST_CHECK( (tensor_type(e,2) >= 2) );
196 BOOST_CHECK( (tensor_type(e,2) <= 2) );
197 BOOST_CHECK( (tensor_type(e,2) == 2) );
198 BOOST_CHECK( (tensor_type(e,2) != 3) );
199
200 BOOST_CHECK( !(2 > tensor_type(e,2)) );
201 BOOST_CHECK( !(2 < tensor_type(e,2)) );
202 BOOST_CHECK( (2 <= tensor_type(e,2)) );
203 BOOST_CHECK( (2 >= tensor_type(e,2)) );
204 BOOST_CHECK( (2 == tensor_type(e,2)) );
205 BOOST_CHECK( (3 != tensor_type(e,2)) );
206
207 BOOST_CHECK( !( tensor_type(e,2)+3 < 5) );
208 BOOST_CHECK( !( tensor_type(e,2)+3 > 5) );
209 BOOST_CHECK( ( tensor_type(e,2)+3 >= 5) );
210 BOOST_CHECK( ( tensor_type(e,2)+3 <= 5) );
211 BOOST_CHECK( ( tensor_type(e,2)+3 == 5) );
212 BOOST_CHECK( ( tensor_type(e,2)+3 != 6) );
213
214
215 BOOST_CHECK( !( 5 > tensor_type(e,2)+3) );
216 BOOST_CHECK( !( 5 < tensor_type(e,2)+3) );
217 BOOST_CHECK( ( 5 >= tensor_type(e,2)+3) );
218 BOOST_CHECK( ( 5 <= tensor_type(e,2)+3) );
219 BOOST_CHECK( ( 5 == tensor_type(e,2)+3) );
220 BOOST_CHECK( ( 6 != tensor_type(e,2)+3) );
221
222
223 BOOST_CHECK( !( tensor_type(e,2)+tensor_type(e,3) < 5) );
224 BOOST_CHECK( !( tensor_type(e,2)+tensor_type(e,3) > 5) );
225 BOOST_CHECK( ( tensor_type(e,2)+tensor_type(e,3) >= 5) );
226 BOOST_CHECK( ( tensor_type(e,2)+tensor_type(e,3) <= 5) );
227 BOOST_CHECK( ( tensor_type(e,2)+tensor_type(e,3) == 5) );
228 BOOST_CHECK( ( tensor_type(e,2)+tensor_type(e,3) != 6) );
229
230
231 BOOST_CHECK( !( 5 > tensor_type(e,2)+tensor_type(e,3)) );
232 BOOST_CHECK( !( 5 < tensor_type(e,2)+tensor_type(e,3)) );
233 BOOST_CHECK( ( 5 >= tensor_type(e,2)+tensor_type(e,3)) );
234 BOOST_CHECK( ( 5 <= tensor_type(e,2)+tensor_type(e,3)) );
235 BOOST_CHECK( ( 5 == tensor_type(e,2)+tensor_type(e,3)) );
236 BOOST_CHECK( ( 6 != tensor_type(e,2)+tensor_type(e,3)) );
237
238 };
239
240 for(auto const& e : extents)
241 check(e);
242
243 }
244
245
246 BOOST_AUTO_TEST_SUITE_END()
247