]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
20effc67 TL |
7 | // This file was modified by Oracle on 2014-2020. |
8 | // Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. | |
7c673cae FG |
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 | ||
20effc67 TL |
21 | |
22 | #include <type_traits> | |
7c673cae FG |
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 | ||
20effc67 TL |
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 | {}; | |
7c673cae FG |
68 | |
69 | ||
70 | }} // namespace detail::select_most_precise | |
71 | #endif // DOXYGEN_NO_DETAIL | |
72 | ||
73 | ||
74 | /*! | |
20effc67 | 75 | \brief Meta-function to select the most accurate type for |
7c673cae FG |
76 | calculations |
77 | \ingroup utility | |
20effc67 | 78 | \details select_most_precise classes, compares types on compile time. |
7c673cae FG |
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. | |
7c673cae FG |
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 | */ | |
20effc67 | 92 | template <typename ...Types> |
7c673cae FG |
93 | struct select_most_precise |
94 | { | |
20effc67 | 95 | typedef void type; |
7c673cae FG |
96 | }; |
97 | ||
20effc67 TL |
98 | template <typename T> |
99 | struct select_most_precise<T> | |
7c673cae | 100 | { |
20effc67 TL |
101 | typedef T type; |
102 | }; | |
7c673cae | 103 | |
20effc67 TL |
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; | |
7c673cae | 111 | |
20effc67 | 112 | typedef std::conditional_t |
7c673cae | 113 | < |
20effc67 TL |
114 | (priority1 > priority2), |
115 | T1, | |
116 | std::conditional_t | |
7c673cae | 117 | < |
20effc67 TL |
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; | |
7c673cae FG |
133 | }; |
134 | ||
20effc67 TL |
135 | template <typename T1, typename T2, typename ...Types> |
136 | struct select_most_precise<T1, T2, Types...> | |
7c673cae | 137 | { |
20effc67 TL |
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; | |
7c673cae FG |
143 | }; |
144 | ||
20effc67 | 145 | |
7c673cae FG |
146 | }} // namespace boost::geometry |
147 | ||
148 | #endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP |