• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019-2020 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 <boost/core/lightweight_test.hpp>
12 
13 #include <tuple>
14 #include <type_traits>
15 
16 #include "test_utility_output_stream.hpp"
17 #include "core/channel/test_fixture.hpp"
18 
19 namespace gil = boost::gil;
20 namespace fixture = boost::gil::test::fixture;
21 
22 struct test_plus_integer_same_types
23 {
24     template <typename Channel>
operator ()test_plus_integer_same_types25     void operator()(Channel const&)
26     {
27         using channel_t = Channel;
28         gil::channel_plus_t<channel_t, channel_t, channel_t> f;
29         BOOST_TEST_EQ(f(0, 0), channel_t(0));
30         BOOST_TEST_EQ(f(100, 27), channel_t(127));
31     }
runtest_plus_integer_same_types32     static void run()
33     {
34         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_integer_same_types{});
35     }
36 };
37 
38 struct test_plus_integer_mixed_types
39 {
40     template <typename Channel>
operator ()test_plus_integer_mixed_types41     void operator()(Channel const&)
42     {
43         using channel_t = Channel;
44         {
45             using channel1_t = channel_t;
46             using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
47             gil::channel_plus_t<channel1_t, channel2_t, channel1_t> f;
48             BOOST_TEST_EQ(f(0, 0), channel1_t(0));
49             BOOST_TEST_EQ(f(100, 27), channel_t(127));
50         }
51         {
52             using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
53             using channel2_t = channel_t;
54             gil::channel_plus_t<channel1_t, channel2_t, channel2_t> f;
55             BOOST_TEST_EQ(f(0, 0), channel2_t(0));
56             BOOST_TEST_EQ(f(100, 27), channel_t(127));
57         }
58     }
runtest_plus_integer_mixed_types59     static void run()
60     {
61         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_integer_mixed_types{});
62     }
63 };
64 
65 struct test_plus_integer_signed_types_with_overflow
66 {
67     template <typename Channel>
operator ()test_plus_integer_signed_types_with_overflow68     void operator()(Channel const&)
69     {
70         using channel_t = Channel;
71         // Signed integer overflow is UB, so just check addition does not yield mathematically
72         // expected value but is constrained by the range of representable values for given type.
73 
74         auto const max_value = gil::channel_traits<channel_t>::max_value();
75         gil::channel_plus_t<channel_t, channel_t, channel_t> f;
76         BOOST_TEST_NE(f(max_value, 1), std::int64_t(max_value) + 1);
77         BOOST_TEST_NE(f(max_value, max_value), std::int64_t(max_value) + max_value);
78     }
runtest_plus_integer_signed_types_with_overflow79     static void run()
80     {
81         boost::mp11::mp_for_each<fixture::channel_integer_signed_types>(test_plus_integer_signed_types_with_overflow{});
82     }
83 };
84 
85 struct test_plus_integer_unsigned_types_with_wraparound
86 {
87     template <typename Channel>
operator ()test_plus_integer_unsigned_types_with_wraparound88     void operator()(Channel const&)
89     {
90         using channel_t = Channel;
91         // The C Standard, 6.2.5, paragraph 9 [ISO/IEC 9899:2011], states:
92         // A computation involving unsigned operands can never overflow, because a result that
93         // cannot be represented by the resulting unsigned integer type is reduced modulo the number
94         // that is one greater than the largest value that can be represented by the resulting type.
95 
96         auto const max_value = gil::channel_traits<channel_t>::max_value();
97         auto const min_value = gil::channel_traits<channel_t>::min_value();
98         gil::channel_plus_t<channel_t, channel_t, channel_t> f;
99         BOOST_TEST_EQ(f(max_value, 1), min_value);
100         BOOST_TEST_EQ(f(max_value, max_value), max_value - 1);
101     }
runtest_plus_integer_unsigned_types_with_wraparound102     static void run()
103     {
104         boost::mp11::mp_for_each<fixture::channel_integer_unsigned_types>(test_plus_integer_unsigned_types_with_wraparound{});
105     }
106 };
107 
108 struct test_minus_integer_same_types
109 {
110     template <typename Channel>
operator ()test_minus_integer_same_types111     void operator()(Channel const&)
112     {
113         using channel_t = Channel;
114         gil::channel_minus_t<channel_t, channel_t, channel_t> f;
115         BOOST_TEST_EQ(f(0, 0), channel_t(0));
116         BOOST_TEST_EQ(f(100, 27), channel_t(73));
117     }
runtest_minus_integer_same_types118     static void run()
119     {
120         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_integer_same_types{});
121     }
122 };
123 
124 struct test_minus_integer_mixed_types
125 {
126     template <typename Channel>
operator ()test_minus_integer_mixed_types127     void operator()(Channel const&)
128     {
129         using channel_t = Channel;
130         {
131             using channel1_t = channel_t;
132             using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
133             gil::channel_minus_t<channel1_t, channel2_t, channel1_t> f;
134             BOOST_TEST_EQ(f(0, 0), channel1_t(0));
135             BOOST_TEST_EQ(f(100, 27), channel_t(73));
136         }
137         {
138             using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
139             using channel2_t = channel_t;
140             gil::channel_minus_t<channel1_t, channel2_t, channel2_t> f;
141             BOOST_TEST_EQ(f(0, 0), channel2_t(0));
142             BOOST_TEST_EQ(f(100, 27), channel_t(73));
143         }
144     }
runtest_minus_integer_mixed_types145     static void run()
146     {
147         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_integer_mixed_types{});
148     }
149 };
150 
151 struct test_multiplies_integer_same_types
152 {
153     template <typename Channel>
operator ()test_multiplies_integer_same_types154     void operator()(Channel const&)
155     {
156         using channel_t = Channel;
157         gil::channel_multiplies_t<channel_t, channel_t, channel_t> f;
158         BOOST_TEST_EQ(f(0, 0), channel_t(0));
159         BOOST_TEST_EQ(f(1, 1), channel_t(1));
160         BOOST_TEST_EQ(f(4, 2), channel_t(8));
161     }
runtest_multiplies_integer_same_types162     static void run()
163     {
164         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_integer_same_types{});
165     }
166 };
167 
168 struct test_multiplies_integer_mixed_types
169 {
170     template <typename Channel>
operator ()test_multiplies_integer_mixed_types171     void operator()(Channel const&)
172     {
173         using channel_t = Channel;
174         {
175             using channel1_t = channel_t;
176             using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
177             gil::channel_multiplies_t<channel1_t, channel2_t, channel1_t> f;
178             BOOST_TEST_EQ(f(0, 0), channel1_t(0));
179             BOOST_TEST_EQ(f(4, 2), channel_t(8));
180         }
181         {
182             using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
183             using channel2_t = channel_t;
184             gil::channel_multiplies_t<channel1_t, channel2_t, channel2_t> f;
185             BOOST_TEST_EQ(f(0, 0), channel2_t(0));
186             BOOST_TEST_EQ(f(4, 2), channel_t(8));
187         }
188     }
runtest_multiplies_integer_mixed_types189     static void run()
190     {
191         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_integer_mixed_types{});
192     }
193 };
194 
195 struct test_divides_integer_same_types
196 {
197     template <typename Channel>
operator ()test_divides_integer_same_types198     void operator()(Channel const&)
199     {
200         using channel_t = Channel;
201         gil::channel_divides_t<channel_t, channel_t, channel_t> f;
202         BOOST_TEST_EQ(f(0, 1), channel_t(0));
203         BOOST_TEST_EQ(f(1, 1), channel_t(1));
204         BOOST_TEST_EQ(f(4, 2), channel_t(2));
205     }
runtest_divides_integer_same_types206     static void run()
207     {
208         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_integer_same_types{});
209     }
210 };
211 
212 struct test_divides_integer_mixed_types
213 {
214     template <typename Channel>
operator ()test_divides_integer_mixed_types215     void operator()(Channel const&)
216     {
217         using channel_t = Channel;
218         {
219             using channel1_t = channel_t;
220             using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
221             gil::channel_divides_t<channel1_t, channel2_t, channel1_t> f;
222             BOOST_TEST_EQ(f(0, 1), channel1_t(0));
223             BOOST_TEST_EQ(f(4, 2), channel_t(2));
224         }
225         {
226             using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
227             using channel2_t = channel_t;
228             gil::channel_divides_t<channel1_t, channel2_t, channel2_t> f;
229             BOOST_TEST_EQ(f(0, 1), channel2_t(0));
230             BOOST_TEST_EQ(f(4, 2), channel_t(2));
231         }
232     }
runtest_divides_integer_mixed_types233     static void run()
234     {
235         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_integer_mixed_types{});
236     }
237 };
238 
239 struct test_plus_scalar_integer_same_types
240 {
241     template <typename Channel>
operator ()test_plus_scalar_integer_same_types242     void operator()(Channel const&)
243     {
244         using channel_t = Channel;
245         gil::channel_plus_scalar_t<channel_t, int, channel_t> f;
246         BOOST_TEST_EQ(f(0, 0), channel_t(0));
247         BOOST_TEST_EQ(f(100, 27), channel_t(127));
248     }
runtest_plus_scalar_integer_same_types249     static void run()
250     {
251         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_scalar_integer_same_types{});
252     }
253 };
254 
255 struct test_plus_scalar_integer_mixed_types
256 {
257     template <typename Channel>
operator ()test_plus_scalar_integer_mixed_types258     void operator()(Channel const&)
259     {
260         using channel_t = Channel;
261         using channel_result_t = std::uint8_t;
262         gil::channel_plus_scalar_t<channel_t, int, channel_result_t> f;
263         BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
264         BOOST_TEST_EQ(f(100, 27), channel_result_t(127));
265     }
runtest_plus_scalar_integer_mixed_types266     static void run()
267     {
268         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_scalar_integer_mixed_types{});
269     }
270 };
271 
272 struct test_minus_scalar_integer_same_types
273 {
274     template <typename Channel>
operator ()test_minus_scalar_integer_same_types275     void operator()(Channel const&)
276     {
277         using channel_t = Channel;
278         gil::channel_minus_scalar_t<channel_t, int, channel_t> f;
279         BOOST_TEST_EQ(f(0, 0), channel_t(0));
280         BOOST_TEST_EQ(f(100, 27), channel_t(73));
281     }
runtest_minus_scalar_integer_same_types282     static void run()
283     {
284         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_scalar_integer_same_types{});
285     }
286 };
287 
288 struct test_minus_scalar_integer_mixed_types
289 {
290     template <typename Channel>
operator ()test_minus_scalar_integer_mixed_types291     void operator()(Channel const&)
292     {
293         using channel_t = Channel;
294         using channel_result_t = std::uint8_t;
295         gil::channel_minus_scalar_t<channel_t, int, std::uint8_t> f;
296         BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
297         BOOST_TEST_EQ(f(100, 27), channel_result_t(73));
298     }
runtest_minus_scalar_integer_mixed_types299     static void run()
300     {
301         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_scalar_integer_mixed_types{});
302     }
303 };
304 
305 struct test_multiplies_scalar_integer_same_types
306 {
307     template <typename Channel>
operator ()test_multiplies_scalar_integer_same_types308     void operator()(Channel const&)
309     {
310         using channel_t = Channel;
311         gil::channel_multiplies_scalar_t<channel_t, channel_t, channel_t> f;
312         BOOST_TEST_EQ(f(0, 0), channel_t(0));
313         BOOST_TEST_EQ(f(1, 1), channel_t(1));
314         BOOST_TEST_EQ(f(4, 2), channel_t(8));
315     }
runtest_multiplies_scalar_integer_same_types316     static void run()
317     {
318         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_scalar_integer_same_types{});
319     }
320 };
321 
322 struct test_multiplies_scalar_integer_mixed_types
323 {
324     template <typename Channel>
operator ()test_multiplies_scalar_integer_mixed_types325     void operator()(Channel const&)
326     {
327         using channel_t = Channel;
328         using channel_result_t = std::uint8_t;
329         gil::channel_multiplies_scalar_t<channel_t, int, channel_result_t> f;
330         BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
331         BOOST_TEST_EQ(f(4, 2), channel_result_t(8));
332     }
runtest_multiplies_scalar_integer_mixed_types333     static void run()
334     {
335         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_scalar_integer_mixed_types{});
336     }
337 };
338 
339 struct test_divides_scalar_integer_same_types
340 {
341     template <typename Channel>
operator ()test_divides_scalar_integer_same_types342     void operator()(Channel const&)
343     {
344         using channel_t = Channel;
345         gil::channel_divides_scalar_t<channel_t, channel_t, channel_t> f;
346         BOOST_TEST_EQ(f(0, 1), channel_t(0));
347         BOOST_TEST_EQ(f(1, 1), channel_t(1));
348         BOOST_TEST_EQ(f(4, 2), channel_t(2));
349     }
runtest_divides_scalar_integer_same_types350     static void run()
351     {
352         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_scalar_integer_same_types{});
353     }
354 };
355 
356 struct test_divides_scalar_integer_mixed_types
357 {
358     template <typename Channel>
operator ()test_divides_scalar_integer_mixed_types359     void operator()(Channel const&)
360     {
361         using channel_t = Channel;
362         using channel_result_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
363         gil::channel_divides_scalar_t<channel_t, int, channel_result_t> f;
364         BOOST_TEST_EQ(f(0, 1), channel_t(0));
365         BOOST_TEST_EQ(f(4, 2), channel_t(2));
366     }
runtest_divides_scalar_integer_mixed_types367     static void run()
368     {
369         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_scalar_integer_mixed_types{});
370     }
371 };
372 
373 struct test_halves_integer_same_types
374 {
375     template <typename Channel>
operator ()test_halves_integer_same_types376     void operator()(Channel const&)
377     {
378         using channel_t = Channel;
379         gil::channel_halves_t<channel_t> f;
380         {
381             channel_t c(0);
382             f(c);
383             BOOST_TEST_EQ(c, channel_t(0));
384         }
385         {
386             channel_t c(2);
387             f(c);
388             BOOST_TEST_EQ(c, channel_t(1));
389         }
390         {
391             channel_t c(4);
392             f(c);
393             BOOST_TEST_EQ(c, channel_t(2));
394         }
395     }
runtest_halves_integer_same_types396     static void run()
397     {
398         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_halves_integer_same_types{});
399     }
400 };
401 
402 struct test_zeros_integer_same_types
403 {
404     template <typename Channel>
operator ()test_zeros_integer_same_types405     void operator()(Channel const&)
406     {
407         using channel_t = Channel;
408         gil::channel_zeros_t<channel_t> f;
409         {
410             channel_t c(0);
411             f(c);
412             BOOST_TEST_EQ(c, channel_t(0));
413         }
414         {
415             channel_t c(2);
416             f(c);
417             BOOST_TEST_EQ(c, channel_t(0));
418         }
419         {
420             channel_t c(4);
421             f(c);
422             BOOST_TEST_EQ(c, channel_t(0));
423         }
424     }
runtest_zeros_integer_same_types425     static void run()
426     {
427         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_zeros_integer_same_types{});
428     }
429 };
430 
431 struct test_assigns_integer_same_types
432 {
433     template <typename Channel>
operator ()test_assigns_integer_same_types434     void operator()(Channel const&)
435     {
436         using channel_t = Channel;
437         gil::channel_assigns_t<channel_t, channel_t> f;
438         {
439             channel_t c1(10);
440             channel_t c2(20);
441             f(c1, c2);
442             BOOST_TEST_EQ(c2, c1);
443         }
444     }
runtest_assigns_integer_same_types445     static void run()
446     {
447         boost::mp11::mp_for_each<fixture::channel_integer_types>(test_assigns_integer_same_types{});
448     }
449 };
450 
main()451 int main()
452 {
453     test_plus_integer_same_types::run();
454     test_plus_integer_mixed_types::run();
455     test_plus_integer_signed_types_with_overflow::run();
456     test_plus_integer_unsigned_types_with_wraparound::run();
457 
458     test_minus_integer_same_types::run();
459     test_minus_integer_mixed_types::run();
460 
461     test_multiplies_integer_same_types::run();
462     test_multiplies_integer_mixed_types::run();
463 
464     test_divides_integer_same_types::run();
465     test_divides_integer_mixed_types::run();
466 
467     test_plus_scalar_integer_same_types::run();
468     test_plus_scalar_integer_mixed_types::run();
469 
470     test_minus_scalar_integer_same_types::run();
471     test_minus_scalar_integer_mixed_types::run();
472 
473     test_multiplies_scalar_integer_same_types::run();
474     test_multiplies_scalar_integer_mixed_types::run();
475 
476     test_divides_scalar_integer_same_types::run();
477     test_divides_scalar_integer_mixed_types::run();
478 
479     test_halves_integer_same_types::run();
480     test_zeros_integer_same_types::run();
481     test_assigns_integer_same_types::run();
482 
483     return ::boost::report_errors();
484 }
485