]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
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
25namespace boost { namespace geometry
26{
27
28#ifndef DOXYGEN_NO_DETAIL
29
30namespace detail { namespace select_most_precise
31{
32
33
20effc67
TL
34// 0 - void
35// 1 - integral
36// 2 - floating point
37// 3 - non-fundamental
38template <typename T>
39struct 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
59template <typename T>
60struct type_size
61 : std::integral_constant<std::size_t, sizeof(T)>
62{};
63
64template <>
65struct 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 92template <typename ...Types>
7c673cae
FG
93struct select_most_precise
94{
20effc67 95 typedef void type;
7c673cae
FG
96};
97
20effc67
TL
98template <typename T>
99struct select_most_precise<T>
7c673cae 100{
20effc67
TL
101 typedef T type;
102};
7c673cae 103
20effc67
TL
104template <typename T1, typename T2>
105struct 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
135template <typename T1, typename T2, typename ...Types>
136struct 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