// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // This file was modified by Oracle on 2014-2020. // Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // Use, modification and distribution is subject to 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) #ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP #define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace select_most_precise { // 0 - void // 1 - integral // 2 - floating point // 3 - non-fundamental template struct type_priority : std::conditional_t < std::is_void::value, std::integral_constant, std::conditional_t < std::is_fundamental::value, std::conditional_t < std::is_floating_point::value, std::integral_constant, std::integral_constant >, std::integral_constant > > {}; template struct type_size : std::integral_constant {}; template <> struct type_size : std::integral_constant {}; }} // namespace detail::select_most_precise #endif // DOXYGEN_NO_DETAIL /*! \brief Meta-function to select the most accurate type for calculations \ingroup utility \details select_most_precise classes, compares types on compile time. For example, if an addition must be done with a double and an integer, the result must be a double. If both types are integer, the result can be an integer. \note It is different from the "promote" class, already in boost. That class promotes e.g. a (one) float to a double. This class selects a type from two types. It takes the most accurate, but does not promote afterwards. \note If the input is a non-fundamental type, it might be a calculation type such as a GMP-value or another high precision value. Therefore, if one is non-fundamental, that one is chosen. \note If both types are non-fundamental, the result is indeterminate and currently the first one is chosen. */ template struct select_most_precise { typedef void type; }; template struct select_most_precise { typedef T type; }; template struct select_most_precise { static const int priority1 = detail::select_most_precise::type_priority::value; static const int priority2 = detail::select_most_precise::type_priority::value; static const std::size_t size1 = detail::select_most_precise::type_size::value; static const std::size_t size2 = detail::select_most_precise::type_size::value; typedef std::conditional_t < (priority1 > priority2), T1, std::conditional_t < (priority2 > priority1), T2, std::conditional_t // priority1 == priority2 < (priority1 == 0 || priority1 == 3), // both void or non-fundamental T1, std::conditional_t // both fundamental < (size2 > size1), T2, T1 > > > > type; }; template struct select_most_precise { typedef typename select_most_precise < typename select_most_precise::type, typename select_most_precise::type >::type type; }; }} // namespace boost::geometry #endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP