select_most_precise.hpp 5.3 KB

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