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