]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // Boost.GIL (Generic Image Library) |
2 | // | |
3 | // Copyright (c) 2015, Oracle and/or its affiliates. | |
4 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle | |
5 | // | |
6 | // Licensed under the Boost Software License version 1.0. | |
7 | // http://www.boost.org/users/license.html | |
8 | // | |
9 | // Source: Boost.Geometry (aka GGL, Generic Geometry Library) | |
10 | // Modifications: adapted for Boost.GIL | |
11 | // - Rename namespace boost::geometry to boost::gil | |
12 | // - Rename define BOOST_GEOMETRY_TEST_DEBUG to BOOST_GIL_TEST_DEBUG | |
13 | // - Remove use of macro BOOST_GEOMETRY_CONDITION | |
14 | // - Remove support for boost::multiprecision types | |
15 | // - Remove support for 128-bit integer types | |
16 | // - Update and sort includes | |
17 | // - Add explicit conversions to avoid warnings due to implicit integral promotions | |
18 | // | |
19 | // Uncomment to enable debugging output | |
20 | //#define BOOST_GIL_TEST_DEBUG 1 | |
f67539c2 | 21 | #include <boost/config.hpp> // BOOST_HAS_LONG_LONG |
92f5a8d4 TL |
22 | #include <boost/gil/promote_integral.hpp> |
23 | ||
f67539c2 TL |
24 | #include <boost/core/lightweight_test.hpp> |
25 | ||
92f5a8d4 TL |
26 | #include <algorithm> |
27 | #include <climits> | |
28 | #include <cstddef> | |
29 | #ifdef BOOST_GIL_TEST_DEBUG | |
30 | #include <iostream> | |
31 | #endif | |
32 | #include <limits> | |
33 | #include <string> | |
34 | ||
92f5a8d4 TL |
35 | namespace bg = boost::gil; |
36 | ||
37 | template | |
38 | < | |
39 | typename T, | |
40 | bool Signed = std::is_fundamental<T>::value && !std::is_unsigned<T>::type::value | |
41 | > | |
42 | struct absolute_value | |
43 | { | |
44 | static inline T apply(T const& t) | |
45 | { | |
46 | return static_cast<T>(t < 0 ? -t : t); | |
47 | } | |
48 | }; | |
49 | ||
50 | template <typename T> | |
51 | struct absolute_value<T, false> | |
52 | { | |
53 | static inline T apply(T const& t) | |
54 | { | |
55 | return t; | |
56 | } | |
57 | }; | |
58 | ||
59 | template | |
60 | < | |
61 | typename Integral, | |
62 | typename Promoted, | |
63 | bool Signed = !std::is_unsigned<Promoted>::value | |
64 | > | |
65 | struct test_max_values | |
66 | { | |
67 | static inline void apply() | |
68 | { | |
69 | // Use >= where value is guaranteed to never be greater than comparator | |
70 | // but to avoid warning: comparing floating point with == is unsafe. | |
71 | ||
72 | Promoted min_value = (std::numeric_limits<Integral>::min)(); | |
73 | // Explicit casts to avoid warning: conversion to short int from int may alter its value | |
74 | min_value = static_cast<Promoted>(min_value * min_value); | |
f67539c2 TL |
75 | BOOST_TEST(absolute_value<Promoted>::apply(min_value) >= min_value); |
76 | BOOST_TEST(absolute_value<Promoted>::apply(min_value) <= min_value); | |
92f5a8d4 TL |
77 | Promoted max_value = (std::numeric_limits<Integral>::max)(); |
78 | max_value = static_cast<Promoted>(max_value * max_value); | |
f67539c2 TL |
79 | BOOST_TEST(absolute_value<Promoted>::apply(max_value) >= max_value); |
80 | BOOST_TEST(absolute_value<Promoted>::apply(max_value) <= max_value); | |
92f5a8d4 TL |
81 | |
82 | #ifdef BOOST_GIL_TEST_DEBUG | |
83 | std::cout << "integral min_value^2: " << min_value << std::endl; | |
84 | std::cout << "promoted max_value: " | |
85 | << (std::numeric_limits<Promoted>::max)() << std::endl; | |
86 | #endif | |
87 | } | |
88 | }; | |
89 | ||
90 | template <typename Integral, typename Promoted> | |
91 | struct test_max_values<Integral, Promoted, false> | |
92 | { | |
93 | static inline void apply() | |
94 | { | |
95 | Promoted max_value = (std::numeric_limits<Integral>::max)(); | |
96 | Promoted max_value_sqr = static_cast<Promoted>(max_value * max_value); | |
f67539c2 | 97 | BOOST_TEST(max_value_sqr < (std::numeric_limits<Promoted>::max)() |
92f5a8d4 TL |
98 | && |
99 | max_value_sqr > max_value); | |
100 | ||
101 | #ifdef BOOST_GIL_TEST_DEBUG | |
102 | std::cout << "integral max_value^2: " << max_value_sqr << std::endl; | |
103 | std::cout << "promoted max_value: " | |
104 | << (std::numeric_limits<Promoted>::max)() << std::endl; | |
105 | #endif | |
106 | } | |
107 | }; | |
108 | ||
109 | ||
110 | // helper function that returns the bit size of a type | |
111 | template | |
112 | < | |
113 | typename T, | |
114 | bool IsFundamental = std::is_fundamental<T>::value | |
115 | > | |
116 | struct bit_size_impl : std::integral_constant<std::size_t, 0> | |
117 | {}; | |
118 | ||
119 | template <typename T> | |
120 | struct bit_size_impl<T, true> : bg::detail::promote_integral::bit_size<T>::type | |
121 | {}; | |
122 | ||
123 | template <typename T> | |
124 | std::size_t bit_size() | |
125 | { | |
126 | return bit_size_impl<T>::value; | |
127 | } | |
128 | ||
f67539c2 TL |
129 | #define BOOST_CHECK_MESSAGE(expr, msg) BOOST_TEST(expr) |
130 | ||
92f5a8d4 TL |
131 | template <bool PromoteUnsignedToUnsigned> |
132 | struct test_promote_integral | |
133 | { | |
134 | template <typename Type, typename ExpectedPromotedType> | |
135 | static inline void apply(std::string const& case_id) | |
136 | { | |
137 | using promoted_integral_type = typename bg::promote_integral | |
138 | < | |
139 | Type, PromoteUnsignedToUnsigned | |
140 | >::type; | |
141 | ||
142 | bool const same_types = std::is_same | |
143 | < | |
144 | promoted_integral_type, ExpectedPromotedType | |
145 | >::value; | |
146 | ||
147 | BOOST_CHECK_MESSAGE(same_types, | |
148 | "case ID: " << case_id | |
149 | << "input type: " << typeid(Type).name() | |
150 | << "; detected: " | |
151 | << typeid(promoted_integral_type).name() | |
152 | << "; expected: " | |
153 | << typeid(ExpectedPromotedType).name()); | |
154 | ||
155 | if (!std::is_same<Type, promoted_integral_type>::value) | |
156 | { | |
157 | test_max_values<Type, promoted_integral_type>::apply(); | |
158 | } | |
159 | ||
160 | #ifdef BOOST_GIL_TEST_DEBUG | |
161 | std::cout << "case ID: " << case_id << std::endl | |
162 | << "type : " << typeid(Type).name() | |
163 | << ", sizeof (bits): " << bit_size<Type>() | |
164 | << ", min value: " | |
165 | << (std::numeric_limits<Type>::min)() | |
166 | << ", max value: " | |
167 | << (std::numeric_limits<Type>::max)() | |
168 | << std::endl; | |
169 | std::cout << "detected promoted type : " | |
170 | << typeid(promoted_integral_type).name() | |
171 | << ", sizeof (bits): " << bit_size<promoted_integral_type>() | |
172 | << ", min value: " | |
173 | << (std::numeric_limits<promoted_integral_type>::min)() | |
174 | << ", max value: " | |
175 | << (std::numeric_limits<promoted_integral_type>::max)() | |
176 | << std::endl; | |
177 | std::cout << "expected promoted type : " | |
178 | << typeid(ExpectedPromotedType).name() | |
179 | << ", sizeof (bits): " << bit_size<ExpectedPromotedType>() | |
180 | << ", min value: " | |
181 | << (std::numeric_limits<ExpectedPromotedType>::min)() | |
182 | << ", max value: " | |
183 | << (std::numeric_limits<ExpectedPromotedType>::max)() | |
184 | << std::endl; | |
185 | std::cout << std::endl; | |
186 | #endif | |
187 | } | |
188 | }; | |
189 | ||
190 | template | |
191 | < | |
192 | typename T, | |
193 | bool PromoteUnsignedToUnsigned = false, | |
194 | bool IsSigned = !std::is_unsigned<T>::value | |
195 | > | |
196 | struct test_promotion | |
197 | { | |
198 | static inline void apply(std::string case_id) | |
199 | { | |
200 | #ifdef BOOST_GIL_TEST_DEBUG | |
201 | std::cout << "*** " | |
202 | << (IsSigned ? "signed" : "unsigned") | |
203 | << " -> signed ***" << std::endl; | |
204 | #endif | |
205 | ||
206 | using tester = test_promote_integral<PromoteUnsignedToUnsigned>; | |
207 | ||
208 | case_id += (PromoteUnsignedToUnsigned ? "-t" : "-f"); | |
209 | ||
210 | std::size_t min_size = 2 * bit_size<T>() - 1; | |
211 | if (!IsSigned) | |
212 | { | |
213 | min_size += 2; | |
214 | } | |
215 | ||
216 | #ifdef BOOST_GIL_TEST_DEBUG | |
217 | std::cout << "min size: " << min_size << std::endl; | |
218 | #endif | |
219 | ||
220 | if (bit_size<short>() >= min_size) | |
221 | { | |
222 | tester::template apply<T, short>(case_id); | |
223 | } | |
224 | else if (bit_size<int>() >= min_size) | |
225 | { | |
226 | tester::template apply<T, int>(case_id); | |
227 | } | |
228 | else if (bit_size<long>() >= min_size) | |
229 | { | |
230 | tester::template apply<T, long>(case_id); | |
231 | } | |
232 | #if defined(BOOST_HAS_LONG_LONG) | |
233 | else if (bit_size<boost::long_long_type>() >= min_size) | |
234 | { | |
235 | tester::template apply<T, boost::long_long_type>(case_id); | |
236 | } | |
237 | #endif | |
238 | else | |
239 | { | |
240 | tester::template apply<T, T>(case_id); | |
241 | } | |
242 | } | |
243 | }; | |
244 | ||
245 | template <typename T> | |
246 | struct test_promotion<T, true, false> | |
247 | { | |
248 | static inline void apply(std::string case_id) | |
249 | { | |
250 | #ifdef BOOST_GIL_TEST_DEBUG | |
251 | std::cout << "*** unsigned -> unsigned ***" << std::endl; | |
252 | #endif | |
253 | case_id += "-t"; | |
254 | ||
255 | using tester = test_promote_integral<true>; | |
256 | ||
257 | std::size_t min_size = 2 * bit_size<T>(); | |
258 | ||
259 | #ifdef BOOST_GIL_TEST_DEBUG | |
260 | std::cout << "min size: " << min_size << std::endl; | |
261 | #endif | |
262 | ||
263 | if (bit_size<unsigned short>() >= min_size) | |
264 | { | |
265 | tester::apply<T, unsigned short>(case_id); | |
266 | } | |
267 | else if (bit_size<unsigned int>() >= min_size) | |
268 | { | |
269 | tester::apply<T, unsigned int>(case_id); | |
270 | } | |
271 | else if (bit_size<unsigned long>() >= min_size) | |
272 | { | |
273 | tester::apply<T, unsigned long>(case_id); | |
274 | } | |
275 | else if (bit_size<std::size_t>() >= min_size) | |
276 | { | |
277 | tester::apply<T, std::size_t>(case_id); | |
278 | } | |
279 | #if defined(BOOST_HAS_LONG_LONG) | |
280 | else if (bit_size<boost::ulong_long_type>() >= min_size) | |
281 | { | |
282 | tester::template apply<T, boost::ulong_long_type>(case_id); | |
283 | } | |
284 | #endif | |
285 | else | |
286 | { | |
287 | tester::apply<T, T>(case_id); | |
288 | } | |
289 | } | |
290 | }; | |
291 | ||
f67539c2 | 292 | void test_char() |
92f5a8d4 TL |
293 | { |
294 | test_promotion<char>::apply("char"); | |
295 | test_promotion<char, true>::apply("char"); | |
296 | test_promotion<signed char>::apply("schar"); | |
297 | test_promotion<signed char, true>::apply("schar"); | |
298 | test_promotion<unsigned char>::apply("uchar"); | |
299 | test_promotion<unsigned char, true>::apply("uchar"); | |
300 | } | |
301 | ||
f67539c2 | 302 | void test_short() |
92f5a8d4 TL |
303 | { |
304 | test_promotion<short>::apply("short"); | |
305 | test_promotion<short, true>::apply("short"); | |
306 | test_promotion<unsigned short>::apply("ushort"); | |
307 | test_promotion<unsigned short, true>::apply("ushort"); | |
308 | } | |
309 | ||
f67539c2 | 310 | void test_int() |
92f5a8d4 TL |
311 | { |
312 | test_promotion<int>::apply("int"); | |
313 | test_promotion<int, true>::apply("int"); | |
314 | test_promotion<unsigned int>::apply("uint"); | |
315 | test_promotion<unsigned int, true>::apply("uint"); | |
316 | } | |
317 | ||
f67539c2 | 318 | void test_long() |
92f5a8d4 TL |
319 | { |
320 | test_promotion<long>::apply("long"); | |
321 | test_promotion<long, true>::apply("long"); | |
322 | test_promotion<unsigned long>::apply("ulong"); | |
323 | test_promotion<unsigned long, true>::apply("ulong"); | |
324 | } | |
325 | ||
f67539c2 | 326 | void test_std_size_t() |
92f5a8d4 TL |
327 | { |
328 | test_promotion<std::size_t>::apply("size_t"); | |
329 | test_promotion<std::size_t, true>::apply("size_t"); | |
330 | } | |
331 | ||
332 | #ifdef BOOST_HAS_LONG_LONG | |
f67539c2 | 333 | void test_long_long() |
92f5a8d4 TL |
334 | { |
335 | test_promotion<boost::long_long_type>::apply("long long"); | |
336 | test_promotion<boost::long_long_type, true>::apply("long long"); | |
337 | test_promotion<boost::ulong_long_type>::apply("ulong long"); | |
338 | test_promotion<boost::ulong_long_type, true>::apply("ulong long"); | |
339 | } | |
340 | #endif | |
341 | ||
f67539c2 | 342 | void test_floating_point() |
92f5a8d4 TL |
343 | { |
344 | using tester1 = test_promote_integral<true>; | |
345 | using tester2 = test_promote_integral<false>; | |
346 | ||
347 | // for floating-point types we do not do any promotion | |
348 | tester1::apply<float, float>("fp-f"); | |
349 | tester1::apply<double, double>("fp-d"); | |
350 | tester1::apply<long double, long double>("fp-ld"); | |
351 | ||
352 | tester2::apply<float, float>("fp-f"); | |
353 | tester2::apply<double, double>("fp-d"); | |
354 | tester2::apply<long double, long double>("fp-ld"); | |
355 | } | |
f67539c2 TL |
356 | |
357 | int main() | |
358 | { | |
359 | test_char(); | |
360 | test_short(); | |
361 | test_int(); | |
362 | test_long(); | |
363 | test_std_size_t(); | |
364 | #ifdef BOOST_HAS_LONG_LONG | |
365 | test_long_long(); | |
366 | #endif | |
367 | test_floating_point(); | |
368 | ||
369 | return boost::report_errors(); | |
370 | } |