Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / gil / test / extension / numeric / channel_numeric_operations.cpp
1 //
2 // Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #include <boost/gil.hpp>
9 #include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
10
11 #include <tuple>
12 #include <type_traits>
13
14 #define BOOST_TEST_MODULE test_ext_numeric_pixel_numeric_operations
15 #include "unit_test.hpp"
16 #include "unit_test_utility.hpp"
17 #include "core/channel/test_fixture.hpp"
18
19 namespace gil = boost::gil;
20 namespace fixture = boost::gil::test::fixture;
21
22 BOOST_AUTO_TEST_SUITE(channel_plus_t)
23
24 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_same_types, channel_t, fixture::channel_integer_types)
25 {
26     gil::channel_plus_t<channel_t, channel_t, channel_t> f;
27     BOOST_TEST(f(0, 0) == channel_t(0));
28     BOOST_TEST(f(100, 27) == channel_t(127));
29 }
30
31 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_mixed_types, channel_t, fixture::channel_integer_types)
32 {
33     {
34         using channel1_t = channel_t;
35         using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
36         gil::channel_plus_t<channel1_t, channel2_t, channel1_t> f;
37         BOOST_TEST(f(0, 0) == channel1_t(0));
38         BOOST_TEST(f(100, 27) == channel_t(127));
39     }
40     {
41         using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
42         using channel2_t = channel_t;
43         gil::channel_plus_t<channel1_t, channel2_t, channel2_t> f;
44         BOOST_TEST(f(0, 0) == channel2_t(0));
45         BOOST_TEST(f(100, 27) == channel_t(127));
46     }
47 }
48
49 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_signed_types_with_overflow, channel_t, fixture::channel_integer_signed_types)
50 {
51     // Signed integer overflow is UB, so just check addition does not yield mathematically
52     // expected value but is constrained by the range of representable values for given type.
53
54     auto const max_value = gil::channel_traits<channel_t>::max_value();
55     gil::channel_plus_t<channel_t, channel_t, channel_t> f;
56     BOOST_TEST(f(max_value, 1) != std::int64_t(max_value) + 1);
57     BOOST_TEST(f(max_value, max_value) != std::int64_t(max_value) + max_value);
58 }
59
60 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_unsigned_types_with_wraparound, channel_t, fixture::channel_integer_unsigned_types)
61 {
62     // The C Standard, 6.2.5, paragraph 9 [ISO/IEC 9899:2011], states:
63     // A computation involving unsigned operands can never overflow, because a result that
64     // cannot be represented by the resulting unsigned integer type is reduced modulo the number
65     // that is one greater than the largest value that can be represented by the resulting type.
66
67     auto const max_value = gil::channel_traits<channel_t>::max_value();
68     auto const min_value = gil::channel_traits<channel_t>::min_value();
69     gil::channel_plus_t<channel_t, channel_t, channel_t> f;
70     BOOST_TEST(f(max_value, 1) == min_value);
71     BOOST_TEST(f(max_value, max_value) == max_value - 1);
72 }
73
74 BOOST_AUTO_TEST_SUITE_END() // channel_plus_t
75
76 BOOST_AUTO_TEST_SUITE(channel_minus_t)
77
78 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_integer_same_types, channel_t, fixture::channel_integer_types)
79 {
80     gil::channel_minus_t<channel_t, channel_t, channel_t> f;
81     BOOST_TEST(f(0, 0) == channel_t(0));
82     BOOST_TEST(f(100, 27) == channel_t(73));
83 }
84
85 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_integer_mixed_types, channel_t, fixture::channel_integer_types)
86 {
87     {
88         using channel1_t = channel_t;
89         using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
90         gil::channel_minus_t<channel1_t, channel2_t, channel1_t> f;
91         BOOST_TEST(f(0, 0) == channel1_t(0));
92         BOOST_TEST(f(100, 27) == channel_t(73));
93     }
94     {
95         using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
96         using channel2_t = channel_t;
97         gil::channel_minus_t<channel1_t, channel2_t, channel2_t> f;
98         BOOST_TEST(f(0, 0) == channel2_t(0));
99         BOOST_TEST(f(100, 27) == channel_t(73));
100     }
101 }
102
103 BOOST_AUTO_TEST_SUITE_END() // channel_minus_t
104
105 BOOST_AUTO_TEST_SUITE(channel_multiplies_t)
106
107 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_integer_same_types, channel_t, fixture::channel_integer_types)
108 {
109     gil::channel_multiplies_t<channel_t, channel_t, channel_t> f;
110     BOOST_TEST(f(0, 0) == channel_t(0));
111     BOOST_TEST(f(1, 1) == channel_t(1));
112     BOOST_TEST(f(4, 2) == channel_t(8));
113 }
114
115 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_integer_mixed_types, channel_t, fixture::channel_integer_types)
116 {
117     {
118         using channel1_t = channel_t;
119         using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
120         gil::channel_multiplies_t<channel1_t, channel2_t, channel1_t> f;
121         BOOST_TEST(f(0, 0) == channel1_t(0));
122         BOOST_TEST(f(4, 2) == channel_t(8));
123     }
124     {
125         using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
126         using channel2_t = channel_t;
127         gil::channel_multiplies_t<channel1_t, channel2_t, channel2_t> f;
128         BOOST_TEST(f(0, 0) == channel2_t(0));
129         BOOST_TEST(f(4, 2) == channel_t(8));
130     }
131 }
132
133 BOOST_AUTO_TEST_SUITE_END() // channel_multiplies_t
134
135 BOOST_AUTO_TEST_SUITE(channel_divides_t)
136
137 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_integer_same_types, channel_t, fixture::channel_integer_types)
138 {
139     gil::channel_divides_t<channel_t, channel_t, channel_t> f;
140     BOOST_TEST(f(0, 1) == channel_t(0));
141     BOOST_TEST(f(1, 1) == channel_t(1));
142     BOOST_TEST(f(4, 2) == channel_t(2));
143 }
144
145 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_integer_mixed_types, channel_t, fixture::channel_integer_types)
146 {
147     {
148         using channel1_t = channel_t;
149         using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
150         gil::channel_divides_t<channel1_t, channel2_t, channel1_t> f;
151         BOOST_TEST(f(0, 1) == channel1_t(0));
152         BOOST_TEST(f(4, 2) == channel_t(2));
153     }
154     {
155         using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
156         using channel2_t = channel_t;
157         gil::channel_divides_t<channel1_t, channel2_t, channel2_t> f;
158         BOOST_TEST(f(0, 1) == channel2_t(0));
159         BOOST_TEST(f(4, 2) == channel_t(2));
160     }
161 }
162
163 BOOST_AUTO_TEST_SUITE_END() // channel_divides_t
164
165 BOOST_AUTO_TEST_SUITE(channel_plus_scalar_t)
166
167 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
168 {
169     gil::channel_plus_scalar_t<channel_t, int, channel_t> f;
170     BOOST_TEST(f(0, 0) == channel_t(0));
171     BOOST_TEST(f(100, 27) == channel_t(127));
172 }
173
174 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
175 {
176     using channel_result_t = std::uint8_t;
177     gil::channel_plus_scalar_t<channel_t, int, channel_result_t> f;
178     BOOST_TEST(f(0, 0) == channel_result_t(0));
179     BOOST_TEST(f(100, 27) == channel_result_t(127));
180 }
181
182 BOOST_AUTO_TEST_SUITE_END() // channel_plus_scalar_t
183
184 BOOST_AUTO_TEST_SUITE(channel_minus_scalar_t)
185
186 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
187 {
188     gil::channel_minus_scalar_t<channel_t, int, channel_t> f;
189     BOOST_TEST(f(0, 0) == channel_t(0));
190     BOOST_TEST(f(100, 27) == channel_t(73));
191 }
192
193 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
194 {
195     using channel_result_t = std::uint8_t;
196     gil::channel_minus_scalar_t<channel_t, int, std::uint8_t> f;
197     BOOST_TEST(f(0, 0) == channel_result_t(0));
198     BOOST_TEST(f(100, 27) == channel_result_t(73));
199 }
200
201 BOOST_AUTO_TEST_SUITE_END() // channel_minus_scalar_t
202
203 BOOST_AUTO_TEST_SUITE(channel_multiplies_scalar_t)
204
205 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
206 {
207     gil::channel_multiplies_scalar_t<channel_t, channel_t, channel_t> f;
208     BOOST_TEST(f(0, 0) == channel_t(0));
209     BOOST_TEST(f(1, 1) == channel_t(1));
210     BOOST_TEST(f(4, 2) == channel_t(8));
211 }
212
213 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
214 {
215     using channel_result_t = std::uint8_t;
216     gil::channel_multiplies_scalar_t<channel_t, int, channel_result_t> f;
217     BOOST_TEST(f(0, 0) == channel_result_t(0));
218     BOOST_TEST(f(4, 2) == channel_result_t(8));
219 }
220
221 BOOST_AUTO_TEST_SUITE_END() // channel_multiplies_scalar_t
222
223 BOOST_AUTO_TEST_SUITE(channel_divides_scalar_t)
224
225 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
226 {
227     gil::channel_divides_scalar_t<channel_t, channel_t, channel_t> f;
228     BOOST_TEST(f(0, 1) == channel_t(0));
229     BOOST_TEST(f(1, 1) == channel_t(1));
230     BOOST_TEST(f(4, 2) == channel_t(2));
231 }
232
233 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
234 {
235     using channel_result_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
236     gil::channel_divides_scalar_t<channel_t, int, channel_result_t> f;
237     BOOST_TEST(f(0, 1) == channel_t(0));
238     BOOST_TEST(f(4, 2) == channel_t(2));
239 }
240
241 BOOST_AUTO_TEST_SUITE_END() // channel_divides_scalar_t
242
243 BOOST_AUTO_TEST_SUITE(channel_halves_t)
244
245 BOOST_AUTO_TEST_CASE_TEMPLATE(halves_integer_same_types, channel_t, fixture::channel_integer_types)
246 {
247     gil::channel_halves_t<channel_t> f;
248     {
249         channel_t c(0);
250         f(c);
251         BOOST_TEST(c == channel_t(0));
252     }
253     {
254         channel_t c(2);
255         f(c);
256         BOOST_TEST(c == channel_t(1));
257     }
258     {
259         channel_t c(4);
260         f(c);
261         BOOST_TEST(c == channel_t(2));
262     }
263 }
264
265 BOOST_AUTO_TEST_SUITE_END() // channel_halves_t
266
267 BOOST_AUTO_TEST_SUITE(channel_zeros_t)
268
269 BOOST_AUTO_TEST_CASE_TEMPLATE(zeros_integer_same_types, channel_t, fixture::channel_integer_types)
270 {
271     gil::channel_zeros_t<channel_t> f;
272     {
273         channel_t c(0);
274         f(c);
275         BOOST_TEST(c == channel_t(0));
276     }
277     {
278         channel_t c(2);
279         f(c);
280         BOOST_TEST(c == channel_t(0));
281     }
282     {
283         channel_t c(4);
284         f(c);
285         BOOST_TEST(c == channel_t(0));
286     }
287 }
288
289 BOOST_AUTO_TEST_SUITE_END() // channel_zeros_t
290
291 BOOST_AUTO_TEST_SUITE(channel_assigns_t)
292
293 BOOST_AUTO_TEST_CASE_TEMPLATE(assigns_integer_same_types, channel_t, fixture::channel_integer_types)
294 {
295     gil::channel_assigns_t<channel_t, channel_t> f;
296     {
297         channel_t c1(10);
298         channel_t c2(20);
299         f(c1, c2);
300         BOOST_TEST(c2 == c1);
301     }
302
303 }
304
305 BOOST_AUTO_TEST_SUITE_END() // channel_assigns_t