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.
8// Modifications copyright (c) 2014 Oracle and/or its affiliates.
9
10// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11
12// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14
15// Use, modification and distribution is subject to the Boost Software License,
16// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17// http://www.boost.org/LICENSE_1_0.txt)
18
19#ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
20#define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
21
22#include <boost/mpl/if.hpp>
23#include <boost/type_traits.hpp>
24
25
26namespace boost { namespace geometry
27{
28
29#ifndef DOXYGEN_NO_DETAIL
30
31namespace detail { namespace select_most_precise
32{
33
34
35// At least one of the types is non-fundamental. Take that one.
36// if both are non-fundamental, the type-to-be-selected
37// is unknown, it should be defined by explicit specialization.
38template <bool Fundamental1, bool Fundamental2, typename T1, typename T2>
39struct select_non_fundamental
40{
41 typedef T1 type;
42};
43
44template <typename T1, typename T2>
45struct select_non_fundamental<true, false, T1, T2>
46{
47 typedef T2 type;
48};
49
50template <typename T1, typename T2>
51struct select_non_fundamental<false, true, T1, T2>
52{
53 typedef T1 type;
54};
55
56
57// Selection of largest type (e.g. int of <short int,int>
58// It defaults takes the first one, if second is larger, take the second one
59template <bool SecondLarger, typename T1, typename T2>
60struct select_largest
61{
62 typedef T1 type;
63};
64
65template <typename T1, typename T2>
66struct select_largest<true, T1, T2>
67{
68 typedef T2 type;
69};
70
71
72
73// Selection of floating point and specializations:
74// both FP or both !FP does never occur...
75template <bool FP1, bool FP2, typename T1, typename T2>
76struct select_floating_point
77{
78 typedef char type;
79};
80
81
82// ... so if ONE but not both of these types is floating point, take that one
83template <typename T1, typename T2>
84struct select_floating_point<true, false, T1, T2>
85{
86 typedef T1 type;
87};
88
89
90template <typename T1, typename T2>
91struct select_floating_point<false, true, T1, T2>
92{
93 typedef T2 type;
94};
95
96
97}} // namespace detail::select_most_precise
98#endif // DOXYGEN_NO_DETAIL
99
100
101/*!
102 \brief Meta-function to select, of two types, the most accurate type for
103 calculations
104 \ingroup utility
105 \details select_most_precise classes, compares two types on compile time.
106 For example, if an addition must be done with a double and an integer, the
107 result must be a double.
108 If both types are integer, the result can be an integer.
109 \note It is different from the "promote" class, already in boost. That
110 class promotes e.g. a (one) float to a double. This class selects a
111 type from two types. It takes the most accurate, but does not promote
112 afterwards.
113 \note This traits class is completely independant from GGL and might be a
114 separate addition to Boost
115 \note If the input is a non-fundamental type, it might be a calculation
116 type such as a GMP-value or another high precision value. Therefore,
117 if one is non-fundamental, that one is chosen.
118 \note If both types are non-fundamental, the result is indeterminate and
119 currently the first one is chosen.
120*/
121template <typename T1, typename T2 = void, typename T3 = void>
122struct select_most_precise
123{
124 typedef typename select_most_precise
125 <
126 typename select_most_precise<T1, T2>::type,
127 T3
128 >::type type;
129};
130
131template <typename T1, typename T2>
132struct select_most_precise<T1, T2, void>
133{
134 static const bool second_larger = sizeof(T2) > sizeof(T1);
135 static const bool one_not_fundamental = !
136 (boost::is_fundamental<T1>::type::value
137 && boost::is_fundamental<T2>::type::value);
138
139 static const bool both_same =
140 boost::is_floating_point<T1>::type::value
141 == boost::is_floating_point<T2>::type::value;
142
143 typedef typename boost::mpl::if_c
144 <
145 one_not_fundamental,
146 typename detail::select_most_precise::select_non_fundamental
147 <
148 boost::is_fundamental<T1>::type::value,
149 boost::is_fundamental<T2>::type::value,
150 T1,
151 T2
152 >::type,
153 typename boost::mpl::if_c
154 <
155 both_same,
156 typename detail::select_most_precise::select_largest
157 <
158 second_larger,
159 T1,
160 T2
161 >::type,
162 typename detail::select_most_precise::select_floating_point
163 <
164 boost::is_floating_point<T1>::type::value,
165 boost::is_floating_point<T2>::type::value,
166 T1,
167 T2
168 >::type
169 >::type
170 >::type type;
171};
172
173template <typename T1>
174struct select_most_precise<T1, void, void>
175{
176 typedef T1 type;
177};
178
179}} // namespace boost::geometry
180
181#endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
182

source code of boost/boost/geometry/util/select_most_precise.hpp