// Boost.GIL (Generic Image Library) // // Copyright (c) 2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html // // Source: Boost.Geometry (aka GGL, Generic Geometry Library) // Modifications: adapted for Boost.GIL // - Rename namespace boost::geometry to boost::gil // - Rename define BOOST_GEOMETRY_TEST_DEBUG to BOOST_GIL_TEST_DEBUG // - Remove use of macro BOOST_GEOMETRY_CONDITION // - Remove support for boost::multiprecision types // - Remove support for 128-bit integer types // - Update and sort includes // - Add explicit conversions to avoid warnings due to implicit integral promotions // // Uncomment to enable debugging output //#define BOOST_GIL_TEST_DEBUG 1 #include #include #include #include #ifdef BOOST_GIL_TEST_DEBUG #include #endif #include #include #ifndef BOOST_TEST_MODULE #define BOOST_TEST_MODULE test_promote_integral #endif #include "unit_test.hpp" namespace bg = boost::gil; template < typename T, bool Signed = std::is_fundamental::value && !std::is_unsigned::type::value > struct absolute_value { static inline T apply(T const& t) { return static_cast(t < 0 ? -t : t); } }; template struct absolute_value { static inline T apply(T const& t) { return t; } }; template < typename Integral, typename Promoted, bool Signed = !std::is_unsigned::value > struct test_max_values { static inline void apply() { // Use >= where value is guaranteed to never be greater than comparator // but to avoid warning: comparing floating point with == is unsafe. Promoted min_value = (std::numeric_limits::min)(); // Explicit casts to avoid warning: conversion to short int from int may alter its value min_value = static_cast(min_value * min_value); BOOST_CHECK(absolute_value::apply(min_value) >= min_value); BOOST_CHECK(absolute_value::apply(min_value) <= min_value); Promoted max_value = (std::numeric_limits::max)(); max_value = static_cast(max_value * max_value); BOOST_CHECK(absolute_value::apply(max_value) >= max_value); BOOST_CHECK(absolute_value::apply(max_value) <= max_value); #ifdef BOOST_GIL_TEST_DEBUG std::cout << "integral min_value^2: " << min_value << std::endl; std::cout << "promoted max_value: " << (std::numeric_limits::max)() << std::endl; #endif } }; template struct test_max_values { static inline void apply() { Promoted max_value = (std::numeric_limits::max)(); Promoted max_value_sqr = static_cast(max_value * max_value); BOOST_CHECK(max_value_sqr < (std::numeric_limits::max)() && max_value_sqr > max_value); #ifdef BOOST_GIL_TEST_DEBUG std::cout << "integral max_value^2: " << max_value_sqr << std::endl; std::cout << "promoted max_value: " << (std::numeric_limits::max)() << std::endl; #endif } }; // helper function that returns the bit size of a type template < typename T, bool IsFundamental = std::is_fundamental::value > struct bit_size_impl : std::integral_constant {}; template struct bit_size_impl : bg::detail::promote_integral::bit_size::type {}; template std::size_t bit_size() { return bit_size_impl::value; } template struct test_promote_integral { template static inline void apply(std::string const& case_id) { using promoted_integral_type = typename bg::promote_integral < Type, PromoteUnsignedToUnsigned >::type; bool const same_types = std::is_same < promoted_integral_type, ExpectedPromotedType >::value; BOOST_CHECK_MESSAGE(same_types, "case ID: " << case_id << "input type: " << typeid(Type).name() << "; detected: " << typeid(promoted_integral_type).name() << "; expected: " << typeid(ExpectedPromotedType).name()); if (!std::is_same::value) { test_max_values::apply(); } #ifdef BOOST_GIL_TEST_DEBUG std::cout << "case ID: " << case_id << std::endl << "type : " << typeid(Type).name() << ", sizeof (bits): " << bit_size() << ", min value: " << (std::numeric_limits::min)() << ", max value: " << (std::numeric_limits::max)() << std::endl; std::cout << "detected promoted type : " << typeid(promoted_integral_type).name() << ", sizeof (bits): " << bit_size() << ", min value: " << (std::numeric_limits::min)() << ", max value: " << (std::numeric_limits::max)() << std::endl; std::cout << "expected promoted type : " << typeid(ExpectedPromotedType).name() << ", sizeof (bits): " << bit_size() << ", min value: " << (std::numeric_limits::min)() << ", max value: " << (std::numeric_limits::max)() << std::endl; std::cout << std::endl; #endif } }; template < typename T, bool PromoteUnsignedToUnsigned = false, bool IsSigned = !std::is_unsigned::value > struct test_promotion { static inline void apply(std::string case_id) { #ifdef BOOST_GIL_TEST_DEBUG std::cout << "*** " << (IsSigned ? "signed" : "unsigned") << " -> signed ***" << std::endl; #endif using tester = test_promote_integral; case_id += (PromoteUnsignedToUnsigned ? "-t" : "-f"); std::size_t min_size = 2 * bit_size() - 1; if (!IsSigned) { min_size += 2; } #ifdef BOOST_GIL_TEST_DEBUG std::cout << "min size: " << min_size << std::endl; #endif if (bit_size() >= min_size) { tester::template apply(case_id); } else if (bit_size() >= min_size) { tester::template apply(case_id); } else if (bit_size() >= min_size) { tester::template apply(case_id); } #if defined(BOOST_HAS_LONG_LONG) else if (bit_size() >= min_size) { tester::template apply(case_id); } #endif else { tester::template apply(case_id); } } }; template struct test_promotion { static inline void apply(std::string case_id) { #ifdef BOOST_GIL_TEST_DEBUG std::cout << "*** unsigned -> unsigned ***" << std::endl; #endif case_id += "-t"; using tester = test_promote_integral; std::size_t min_size = 2 * bit_size(); #ifdef BOOST_GIL_TEST_DEBUG std::cout << "min size: " << min_size << std::endl; #endif if (bit_size() >= min_size) { tester::apply(case_id); } else if (bit_size() >= min_size) { tester::apply(case_id); } else if (bit_size() >= min_size) { tester::apply(case_id); } else if (bit_size() >= min_size) { tester::apply(case_id); } #if defined(BOOST_HAS_LONG_LONG) else if (bit_size() >= min_size) { tester::template apply(case_id); } #endif else { tester::apply(case_id); } } }; BOOST_AUTO_TEST_CASE( test_char ) { test_promotion::apply("char"); test_promotion::apply("char"); test_promotion::apply("schar"); test_promotion::apply("schar"); test_promotion::apply("uchar"); test_promotion::apply("uchar"); } BOOST_AUTO_TEST_CASE( test_short ) { test_promotion::apply("short"); test_promotion::apply("short"); test_promotion::apply("ushort"); test_promotion::apply("ushort"); } BOOST_AUTO_TEST_CASE( test_int ) { test_promotion::apply("int"); test_promotion::apply("int"); test_promotion::apply("uint"); test_promotion::apply("uint"); } BOOST_AUTO_TEST_CASE( test_long ) { test_promotion::apply("long"); test_promotion::apply("long"); test_promotion::apply("ulong"); test_promotion::apply("ulong"); } BOOST_AUTO_TEST_CASE( test_std_size_t ) { test_promotion::apply("size_t"); test_promotion::apply("size_t"); } #ifdef BOOST_HAS_LONG_LONG BOOST_AUTO_TEST_CASE( test_long_long ) { test_promotion::apply("long long"); test_promotion::apply("long long"); test_promotion::apply("ulong long"); test_promotion::apply("ulong long"); } #endif BOOST_AUTO_TEST_CASE( test_floating_point ) { using tester1 = test_promote_integral; using tester2 = test_promote_integral; // for floating-point types we do not do any promotion tester1::apply("fp-f"); tester1::apply("fp-d"); tester1::apply("fp-ld"); tester2::apply("fp-f"); tester2::apply("fp-d"); tester2::apply("fp-ld"); }