1 // Boost.GIL (Generic Image Library)
3 // Copyright (c) 2015, Oracle and/or its affiliates.
4 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
6 // Licensed under the Boost Software License version 1.0.
7 // http://www.boost.org/users/license.html
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
19 // Uncomment to enable debugging output
20 //#define BOOST_GIL_TEST_DEBUG 1
22 #include <boost/gil/promote_integral.hpp>
27 #ifdef BOOST_GIL_TEST_DEBUG
33 #ifndef BOOST_TEST_MODULE
34 #define BOOST_TEST_MODULE test_promote_integral
36 #include "unit_test.hpp"
38 namespace bg = boost::gil;
43 bool Signed = std::is_fundamental<T>::value && !std::is_unsigned<T>::type::value
47 static inline T apply(T const& t)
49 return static_cast<T>(t < 0 ? -t : t);
54 struct absolute_value<T, false>
56 static inline T apply(T const& t)
66 bool Signed = !std::is_unsigned<Promoted>::value
68 struct test_max_values
70 static inline void apply()
72 // Use >= where value is guaranteed to never be greater than comparator
73 // but to avoid warning: comparing floating point with == is unsafe.
75 Promoted min_value = (std::numeric_limits<Integral>::min)();
76 // Explicit casts to avoid warning: conversion to short int from int may alter its value
77 min_value = static_cast<Promoted>(min_value * min_value);
78 BOOST_CHECK(absolute_value<Promoted>::apply(min_value) >= min_value);
79 BOOST_CHECK(absolute_value<Promoted>::apply(min_value) <= min_value);
80 Promoted max_value = (std::numeric_limits<Integral>::max)();
81 max_value = static_cast<Promoted>(max_value * max_value);
82 BOOST_CHECK(absolute_value<Promoted>::apply(max_value) >= max_value);
83 BOOST_CHECK(absolute_value<Promoted>::apply(max_value) <= max_value);
85 #ifdef BOOST_GIL_TEST_DEBUG
86 std::cout << "integral min_value^2: " << min_value << std::endl;
87 std::cout << "promoted max_value: "
88 << (std::numeric_limits<Promoted>::max)() << std::endl;
93 template <typename Integral, typename Promoted>
94 struct test_max_values<Integral, Promoted, false>
96 static inline void apply()
98 Promoted max_value = (std::numeric_limits<Integral>::max)();
99 Promoted max_value_sqr = static_cast<Promoted>(max_value * max_value);
100 BOOST_CHECK(max_value_sqr < (std::numeric_limits<Promoted>::max)()
102 max_value_sqr > max_value);
104 #ifdef BOOST_GIL_TEST_DEBUG
105 std::cout << "integral max_value^2: " << max_value_sqr << std::endl;
106 std::cout << "promoted max_value: "
107 << (std::numeric_limits<Promoted>::max)() << std::endl;
113 // helper function that returns the bit size of a type
117 bool IsFundamental = std::is_fundamental<T>::value
119 struct bit_size_impl : std::integral_constant<std::size_t, 0>
122 template <typename T>
123 struct bit_size_impl<T, true> : bg::detail::promote_integral::bit_size<T>::type
126 template <typename T>
127 std::size_t bit_size()
129 return bit_size_impl<T>::value;
132 template <bool PromoteUnsignedToUnsigned>
133 struct test_promote_integral
135 template <typename Type, typename ExpectedPromotedType>
136 static inline void apply(std::string const& case_id)
138 using promoted_integral_type = typename bg::promote_integral
140 Type, PromoteUnsignedToUnsigned
143 bool const same_types = std::is_same
145 promoted_integral_type, ExpectedPromotedType
148 BOOST_CHECK_MESSAGE(same_types,
149 "case ID: " << case_id
150 << "input type: " << typeid(Type).name()
152 << typeid(promoted_integral_type).name()
154 << typeid(ExpectedPromotedType).name());
156 if (!std::is_same<Type, promoted_integral_type>::value)
158 test_max_values<Type, promoted_integral_type>::apply();
161 #ifdef BOOST_GIL_TEST_DEBUG
162 std::cout << "case ID: " << case_id << std::endl
163 << "type : " << typeid(Type).name()
164 << ", sizeof (bits): " << bit_size<Type>()
166 << (std::numeric_limits<Type>::min)()
168 << (std::numeric_limits<Type>::max)()
170 std::cout << "detected promoted type : "
171 << typeid(promoted_integral_type).name()
172 << ", sizeof (bits): " << bit_size<promoted_integral_type>()
174 << (std::numeric_limits<promoted_integral_type>::min)()
176 << (std::numeric_limits<promoted_integral_type>::max)()
178 std::cout << "expected promoted type : "
179 << typeid(ExpectedPromotedType).name()
180 << ", sizeof (bits): " << bit_size<ExpectedPromotedType>()
182 << (std::numeric_limits<ExpectedPromotedType>::min)()
184 << (std::numeric_limits<ExpectedPromotedType>::max)()
186 std::cout << std::endl;
194 bool PromoteUnsignedToUnsigned = false,
195 bool IsSigned = !std::is_unsigned<T>::value
197 struct test_promotion
199 static inline void apply(std::string case_id)
201 #ifdef BOOST_GIL_TEST_DEBUG
203 << (IsSigned ? "signed" : "unsigned")
204 << " -> signed ***" << std::endl;
207 using tester = test_promote_integral<PromoteUnsignedToUnsigned>;
209 case_id += (PromoteUnsignedToUnsigned ? "-t" : "-f");
211 std::size_t min_size = 2 * bit_size<T>() - 1;
217 #ifdef BOOST_GIL_TEST_DEBUG
218 std::cout << "min size: " << min_size << std::endl;
221 if (bit_size<short>() >= min_size)
223 tester::template apply<T, short>(case_id);
225 else if (bit_size<int>() >= min_size)
227 tester::template apply<T, int>(case_id);
229 else if (bit_size<long>() >= min_size)
231 tester::template apply<T, long>(case_id);
233 #if defined(BOOST_HAS_LONG_LONG)
234 else if (bit_size<boost::long_long_type>() >= min_size)
236 tester::template apply<T, boost::long_long_type>(case_id);
241 tester::template apply<T, T>(case_id);
246 template <typename T>
247 struct test_promotion<T, true, false>
249 static inline void apply(std::string case_id)
251 #ifdef BOOST_GIL_TEST_DEBUG
252 std::cout << "*** unsigned -> unsigned ***" << std::endl;
256 using tester = test_promote_integral<true>;
258 std::size_t min_size = 2 * bit_size<T>();
260 #ifdef BOOST_GIL_TEST_DEBUG
261 std::cout << "min size: " << min_size << std::endl;
264 if (bit_size<unsigned short>() >= min_size)
266 tester::apply<T, unsigned short>(case_id);
268 else if (bit_size<unsigned int>() >= min_size)
270 tester::apply<T, unsigned int>(case_id);
272 else if (bit_size<unsigned long>() >= min_size)
274 tester::apply<T, unsigned long>(case_id);
276 else if (bit_size<std::size_t>() >= min_size)
278 tester::apply<T, std::size_t>(case_id);
280 #if defined(BOOST_HAS_LONG_LONG)
281 else if (bit_size<boost::ulong_long_type>() >= min_size)
283 tester::template apply<T, boost::ulong_long_type>(case_id);
288 tester::apply<T, T>(case_id);
293 BOOST_AUTO_TEST_CASE( test_char )
295 test_promotion<char>::apply("char");
296 test_promotion<char, true>::apply("char");
297 test_promotion<signed char>::apply("schar");
298 test_promotion<signed char, true>::apply("schar");
299 test_promotion<unsigned char>::apply("uchar");
300 test_promotion<unsigned char, true>::apply("uchar");
303 BOOST_AUTO_TEST_CASE( test_short )
305 test_promotion<short>::apply("short");
306 test_promotion<short, true>::apply("short");
307 test_promotion<unsigned short>::apply("ushort");
308 test_promotion<unsigned short, true>::apply("ushort");
311 BOOST_AUTO_TEST_CASE( test_int )
313 test_promotion<int>::apply("int");
314 test_promotion<int, true>::apply("int");
315 test_promotion<unsigned int>::apply("uint");
316 test_promotion<unsigned int, true>::apply("uint");
319 BOOST_AUTO_TEST_CASE( test_long )
321 test_promotion<long>::apply("long");
322 test_promotion<long, true>::apply("long");
323 test_promotion<unsigned long>::apply("ulong");
324 test_promotion<unsigned long, true>::apply("ulong");
327 BOOST_AUTO_TEST_CASE( test_std_size_t )
329 test_promotion<std::size_t>::apply("size_t");
330 test_promotion<std::size_t, true>::apply("size_t");
333 #ifdef BOOST_HAS_LONG_LONG
334 BOOST_AUTO_TEST_CASE( test_long_long )
336 test_promotion<boost::long_long_type>::apply("long long");
337 test_promotion<boost::long_long_type, true>::apply("long long");
338 test_promotion<boost::ulong_long_type>::apply("ulong long");
339 test_promotion<boost::ulong_long_type, true>::apply("ulong long");
343 BOOST_AUTO_TEST_CASE( test_floating_point )
345 using tester1 = test_promote_integral<true>;
346 using tester2 = test_promote_integral<false>;
348 // for floating-point types we do not do any promotion
349 tester1::apply<float, float>("fp-f");
350 tester1::apply<double, double>("fp-d");
351 tester1::apply<long double, long double>("fp-ld");
353 tester2::apply<float, float>("fp-f");
354 tester2::apply<double, double>("fp-d");
355 tester2::apply<long double, long double>("fp-ld");