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