2 // Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
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
8 #include <boost/gil.hpp>
9 #include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
12 #include <type_traits>
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"
19 namespace gil = boost::gil;
20 namespace fixture = boost::gil::test::fixture;
22 BOOST_AUTO_TEST_SUITE(channel_plus_t)
24 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_same_types, channel_t, fixture::channel_integer_types)
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));
31 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
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));
49 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_signed_types_with_overflow, channel_t, fixture::channel_integer_signed_types)
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.
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);
60 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_integer_unsigned_types_with_wraparound, channel_t, fixture::channel_integer_unsigned_types)
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.
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);
74 BOOST_AUTO_TEST_SUITE_END() // channel_plus_t
76 BOOST_AUTO_TEST_SUITE(channel_minus_t)
78 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_integer_same_types, channel_t, fixture::channel_integer_types)
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));
85 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
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));
103 BOOST_AUTO_TEST_SUITE_END() // channel_minus_t
105 BOOST_AUTO_TEST_SUITE(channel_multiplies_t)
107 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_integer_same_types, channel_t, fixture::channel_integer_types)
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));
115 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
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));
133 BOOST_AUTO_TEST_SUITE_END() // channel_multiplies_t
135 BOOST_AUTO_TEST_SUITE(channel_divides_t)
137 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_integer_same_types, channel_t, fixture::channel_integer_types)
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));
145 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
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));
163 BOOST_AUTO_TEST_SUITE_END() // channel_divides_t
165 BOOST_AUTO_TEST_SUITE(channel_plus_scalar_t)
167 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
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));
174 BOOST_AUTO_TEST_CASE_TEMPLATE(plus_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
182 BOOST_AUTO_TEST_SUITE_END() // channel_plus_scalar_t
184 BOOST_AUTO_TEST_SUITE(channel_minus_scalar_t)
186 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
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));
193 BOOST_AUTO_TEST_CASE_TEMPLATE(minus_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
201 BOOST_AUTO_TEST_SUITE_END() // channel_minus_scalar_t
203 BOOST_AUTO_TEST_SUITE(channel_multiplies_scalar_t)
205 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
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));
213 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplies_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
221 BOOST_AUTO_TEST_SUITE_END() // channel_multiplies_scalar_t
223 BOOST_AUTO_TEST_SUITE(channel_divides_scalar_t)
225 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_scalar_integer_same_types, channel_t, fixture::channel_integer_types)
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));
233 BOOST_AUTO_TEST_CASE_TEMPLATE(divides_scalar_integer_mixed_types, channel_t, fixture::channel_integer_types)
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));
241 BOOST_AUTO_TEST_SUITE_END() // channel_divides_scalar_t
243 BOOST_AUTO_TEST_SUITE(channel_halves_t)
245 BOOST_AUTO_TEST_CASE_TEMPLATE(halves_integer_same_types, channel_t, fixture::channel_integer_types)
247 gil::channel_halves_t<channel_t> f;
251 BOOST_TEST(c == channel_t(0));
256 BOOST_TEST(c == channel_t(1));
261 BOOST_TEST(c == channel_t(2));
265 BOOST_AUTO_TEST_SUITE_END() // channel_halves_t
267 BOOST_AUTO_TEST_SUITE(channel_zeros_t)
269 BOOST_AUTO_TEST_CASE_TEMPLATE(zeros_integer_same_types, channel_t, fixture::channel_integer_types)
271 gil::channel_zeros_t<channel_t> f;
275 BOOST_TEST(c == channel_t(0));
280 BOOST_TEST(c == channel_t(0));
285 BOOST_TEST(c == channel_t(0));
289 BOOST_AUTO_TEST_SUITE_END() // channel_zeros_t
291 BOOST_AUTO_TEST_SUITE(channel_assigns_t)
293 BOOST_AUTO_TEST_CASE_TEMPLATE(assigns_integer_same_types, channel_t, fixture::channel_integer_types)
295 gil::channel_assigns_t<channel_t, channel_t> f;
300 BOOST_TEST(c2 == c1);
305 BOOST_AUTO_TEST_SUITE_END() // channel_assigns_t