diff --git a/include/boost/gil/detail/select_most_precise.hpp b/include/boost/gil/detail/select_most_precise.hpp new file mode 100644 index 0000000000..c98cf6a6c1 --- /dev/null +++ b/include/boost/gil/detail/select_most_precise.hpp @@ -0,0 +1,108 @@ +#ifndef BOOST_GIL_DETAIL_SELECT_MOST_PRECISE_HPP +#define BOOST_GIL_DETAIL_SELECT_MOST_PRECISE_HPP + +#include + +namespace boost { namespace gil { namespace detail { + +template +struct dependent_false : std::integral_constant {}; + +template +struct select_non_fundamental +{ + using type = void; +}; + +template +struct select_non_fundamental +{ + static_assert(dependent_false::value, "Specialization needed, if both types are not fundamental."); + using type = void; +}; + +template +struct select_non_fundamental +{ + using type = T2; +}; + +template +struct select_non_fundamental +{ + using type = T1; +}; + +template +struct select_floating_point +{ + using type = void; +}; + +template +struct select_floating_point +{ + static_assert(dependent_false::value, "At least one of both types has to be floating point."); + using type = void; +}; + +template +struct select_floating_point +{ + using type = T1; +}; + +template +struct select_floating_point +{ + using type = T2; +}; + +template +struct select_most_precise +{ + static constexpr bool second_larger = sizeof(T2) > sizeof(T1); + static constexpr bool one_not_fundamental = ! + (std::is_fundamental::value + & std::is_fundamental::value); + + static constexpr bool both_floating_point = + std::is_floating_point::value + && std::is_floating_point::value; + + using type = typename std::conditional + < + one_not_fundamental, + typename select_non_fundamental + < + std::is_fundamental::value, + std::is_fundamental::value, + T1, + T2 + >::type, + typename std::conditional + < + both_floating_point, + typename std::conditional + < + second_larger, + T2, + T1 + >::type, + typename select_floating_point + < + std::is_floating_point::value, + std::is_floating_point::value, + T1, + T2 + >::type + >::type + >::type; +}; + +template +using select_most_precise_t = typename select_most_precise::type; + +} } } // namespace boost::gil::detail + +#endif \ No newline at end of file diff --git a/test/core/Jamfile b/test/core/Jamfile index 9305b8762c..40abf728aa 100644 --- a/test/core/Jamfile +++ b/test/core/Jamfile @@ -25,6 +25,7 @@ build-project point ; build-project channel ; build-project color ; build-project color_base ; +build-project detail ; build-project pixel ; build-project iterator ; build-project locator ; diff --git a/test/core/detail/Jamfile b/test/core/detail/Jamfile new file mode 100644 index 0000000000..8f1b60725e --- /dev/null +++ b/test/core/detail/Jamfile @@ -0,0 +1,12 @@ +# +# Copyright 2022 Marco Langer +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# + +import testing ; + +run select_most_precise.cpp ; + diff --git a/test/core/detail/select_most_precise.cpp b/test/core/detail/select_most_precise.cpp new file mode 100644 index 0000000000..06728a2879 --- /dev/null +++ b/test/core/detail/select_most_precise.cpp @@ -0,0 +1,83 @@ +// +// Copyright 2022 Marco Langer +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +#include +#include + +#include + +namespace gil = boost::gil; + +struct my_non_fundamental{}; + +void test_select_most_precise() +{ + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + double + >::value)); + + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + float + >::value)); + + // float, double + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + double + >::value)); + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + double + >::value)); + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + double + >::value)); + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + float + >::value)); + + // int, double + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + double + >::value)); + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + double + >::value)); + + // double, my_non_fundamental + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + my_non_fundamental + >::value)); + BOOST_TEST((std::is_same + < + gil::detail::select_most_precise::type, + my_non_fundamental + >::value)); +} + +int main() +{ + test_select_most_precise(); + + return ::boost::report_errors(); +} \ No newline at end of file