]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/util/select_most_precise.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / geometry / util / select_most_precise.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6
7 // This file was modified by Oracle on 2014-2020.
8 // Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
13
14 // Use, modification and distribution is subject to the Boost Software License,
15 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
17
18 #ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
19 #define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
20
21
22 #include <type_traits>
23
24
25 namespace boost { namespace geometry
26 {
27
28 #ifndef DOXYGEN_NO_DETAIL
29
30 namespace detail { namespace select_most_precise
31 {
32
33
34 // 0 - void
35 // 1 - integral
36 // 2 - floating point
37 // 3 - non-fundamental
38 template <typename T>
39 struct type_priority
40 : std::conditional_t
41 <
42 std::is_void<T>::value,
43 std::integral_constant<int, 0>,
44 std::conditional_t
45 <
46 std::is_fundamental<T>::value,
47 std::conditional_t
48 <
49 std::is_floating_point<T>::value,
50 std::integral_constant<int, 2>,
51 std::integral_constant<int, 1>
52 >,
53 std::integral_constant<int, 3>
54 >
55 >
56 {};
57
58
59 template <typename T>
60 struct type_size
61 : std::integral_constant<std::size_t, sizeof(T)>
62 {};
63
64 template <>
65 struct type_size<void>
66 : std::integral_constant<std::size_t, 0>
67 {};
68
69
70 }} // namespace detail::select_most_precise
71 #endif // DOXYGEN_NO_DETAIL
72
73
74 /*!
75 \brief Meta-function to select the most accurate type for
76 calculations
77 \ingroup utility
78 \details select_most_precise classes, compares types on compile time.
79 For example, if an addition must be done with a double and an integer, the
80 result must be a double.
81 If both types are integer, the result can be an integer.
82 \note It is different from the "promote" class, already in boost. That
83 class promotes e.g. a (one) float to a double. This class selects a
84 type from two types. It takes the most accurate, but does not promote
85 afterwards.
86 \note If the input is a non-fundamental type, it might be a calculation
87 type such as a GMP-value or another high precision value. Therefore,
88 if one is non-fundamental, that one is chosen.
89 \note If both types are non-fundamental, the result is indeterminate and
90 currently the first one is chosen.
91 */
92 template <typename ...Types>
93 struct select_most_precise
94 {
95 typedef void type;
96 };
97
98 template <typename T>
99 struct select_most_precise<T>
100 {
101 typedef T type;
102 };
103
104 template <typename T1, typename T2>
105 struct select_most_precise<T1, T2>
106 {
107 static const int priority1 = detail::select_most_precise::type_priority<T1>::value;
108 static const int priority2 = detail::select_most_precise::type_priority<T2>::value;
109 static const std::size_t size1 = detail::select_most_precise::type_size<T1>::value;
110 static const std::size_t size2 = detail::select_most_precise::type_size<T2>::value;
111
112 typedef std::conditional_t
113 <
114 (priority1 > priority2),
115 T1,
116 std::conditional_t
117 <
118 (priority2 > priority1),
119 T2,
120 std::conditional_t // priority1 == priority2
121 <
122 (priority1 == 0 || priority1 == 3), // both void or non-fundamental
123 T1,
124 std::conditional_t // both fundamental
125 <
126 (size2 > size1),
127 T2,
128 T1
129 >
130 >
131 >
132 > type;
133 };
134
135 template <typename T1, typename T2, typename ...Types>
136 struct select_most_precise<T1, T2, Types...>
137 {
138 typedef typename select_most_precise
139 <
140 typename select_most_precise<T1, T2>::type,
141 typename select_most_precise<Types...>::type
142 >::type type;
143 };
144
145
146 }} // namespace boost::geometry
147
148 #endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP