select_most_precise.hpp 4.8 KB

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