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