123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // 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 <type_traits>
- 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 <typename T>
- struct type_priority
- : std::conditional_t
- <
- std::is_void<T>::value,
- std::integral_constant<int, 0>,
- std::conditional_t
- <
- std::is_fundamental<T>::value,
- std::conditional_t
- <
- std::is_floating_point<T>::value,
- std::integral_constant<int, 2>,
- std::integral_constant<int, 1>
- >,
- std::integral_constant<int, 3>
- >
- >
- {};
- template <typename T>
- struct type_size
- : std::integral_constant<std::size_t, sizeof(T)>
- {};
- template <>
- struct type_size<void>
- : std::integral_constant<std::size_t, 0>
- {};
- }} // 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 <typename ...Types>
- struct select_most_precise
- {
- typedef void type;
- };
- template <typename T>
- struct select_most_precise<T>
- {
- typedef T type;
- };
- template <typename T1, typename T2>
- struct select_most_precise<T1, T2>
- {
- static const int priority1 = detail::select_most_precise::type_priority<T1>::value;
- static const int priority2 = detail::select_most_precise::type_priority<T2>::value;
- static const std::size_t size1 = detail::select_most_precise::type_size<T1>::value;
- static const std::size_t size2 = detail::select_most_precise::type_size<T2>::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 <typename T1, typename T2, typename ...Types>
- struct select_most_precise<T1, T2, Types...>
- {
- typedef typename select_most_precise
- <
- typename select_most_precise<T1, T2>::type,
- typename select_most_precise<Types...>::type
- >::type type;
- };
- }} // namespace boost::geometry
- #endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
|