float_sort.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //Templated Spreadsort-based implementation of float_sort and float_mem_cast
  2. // Copyright Steven J. Ross 2001 - 2014.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org/libs/sort/ for library home page.
  7. /*
  8. Some improvements suggested by:
  9. Phil Endecott and Frank Gennari
  10. float_mem_cast fix provided by:
  11. Scott McMurray
  12. */
  13. #ifndef BOOST_FLOAT_SORT_HPP
  14. #define BOOST_FLOAT_SORT_HPP
  15. #include <algorithm>
  16. #include <vector>
  17. #include <cstring>
  18. #include <limits>
  19. #include <boost/static_assert.hpp>
  20. #include <boost/sort/spreadsort/detail/constants.hpp>
  21. #include <boost/sort/spreadsort/detail/float_sort.hpp>
  22. #include <boost/range/begin.hpp>
  23. #include <boost/range/end.hpp>
  24. namespace boost {
  25. namespace sort {
  26. namespace spreadsort {
  27. /*!
  28. \brief Casts a float to the specified integer type.
  29. \tparam Data_type Floating-point IEEE 754/IEC559 type.
  30. \tparam Cast_type Integer type (same size) to which to cast.
  31. \par Example:
  32. \code
  33. struct rightshift {
  34. int operator()(const DATA_TYPE &x, const unsigned offset) const {
  35. return float_mem_cast<KEY_TYPE, CAST_TYPE>(x.key) >> offset;
  36. }
  37. };
  38. \endcode
  39. */
  40. template<class Data_type, class Cast_type>
  41. inline Cast_type
  42. float_mem_cast(const Data_type & data)
  43. {
  44. // Only cast IEEE floating-point numbers, and only to a same-sized integer.
  45. BOOST_STATIC_ASSERT(sizeof(Cast_type) == sizeof(Data_type));
  46. BOOST_STATIC_ASSERT(std::numeric_limits<Data_type>::is_iec559);
  47. BOOST_STATIC_ASSERT(std::numeric_limits<Cast_type>::is_integer);
  48. Cast_type result;
  49. std::memcpy(&result, &data, sizeof(Cast_type));
  50. return result;
  51. }
  52. /*!
  53. \brief @c float_sort with casting to the appropriate size.
  54. \param[in] first Iterator pointer to first element.
  55. \param[in] last Iterator pointing to one beyond the end of data.
  56. Some performance plots of runtime vs. n and log(range) are provided:\n
  57. <a href="../../doc/graph/windows_float_sort.htm"> windows_float_sort</a>
  58. \n
  59. <a href="../../doc/graph/osx_float_sort.htm"> osx_float_sort</a>
  60. \par A simple example of sorting some floating-point is:
  61. \code
  62. vector<float> vec;
  63. vec.push_back(1.0);
  64. vec.push_back(2.3);
  65. vec.push_back(1.3);
  66. spreadsort(vec.begin(), vec.end());
  67. \endcode
  68. \par The sorted vector contains ascending values "1.0 1.3 2.3".
  69. */
  70. template <class RandomAccessIter>
  71. inline void float_sort(RandomAccessIter first, RandomAccessIter last)
  72. {
  73. if (last - first < detail::min_sort_size)
  74. boost::sort::pdqsort(first, last);
  75. else
  76. detail::float_sort(first, last);
  77. }
  78. /*!
  79. \brief Floating-point sort algorithm using range.
  80. \param[in] range Range [first, last) for sorting.
  81. */
  82. template <class Range>
  83. inline void float_sort(Range& range)
  84. {
  85. float_sort(boost::begin(range), boost::end(range));
  86. }
  87. /*!
  88. \brief Floating-point sort algorithm using random access iterators with just right-shift functor.
  89. \param[in] first Iterator pointer to first element.
  90. \param[in] last Iterator pointing to one beyond the end of data.
  91. \param[in] rshift Functor that returns the result of shifting the value_type right a specified number of bits.
  92. */
  93. template <class RandomAccessIter, class Right_shift>
  94. inline void float_sort(RandomAccessIter first, RandomAccessIter last,
  95. Right_shift rshift)
  96. {
  97. if (last - first < detail::min_sort_size)
  98. boost::sort::pdqsort(first, last);
  99. else
  100. detail::float_sort(first, last, rshift(*first, 0), rshift);
  101. }
  102. /*!
  103. \brief Floating-point sort algorithm using range with just right-shift functor.
  104. \param[in] range Range [first, last) for sorting.
  105. \param[in] rshift Functor that returns the result of shifting the value_type right a specified number of bits.
  106. */
  107. template <class Range, class Right_shift>
  108. inline void float_sort(Range& range, Right_shift rshift)
  109. {
  110. float_sort(boost::begin(range), boost::end(range), rshift);
  111. }
  112. /*!
  113. \brief Float sort algorithm using random access iterators with both right-shift and user-defined comparison operator.
  114. \param[in] first Iterator pointer to first element.
  115. \param[in] last Iterator pointing to one beyond the end of data.
  116. \param[in] rshift Functor that returns the result of shifting the value_type right a specified number of bits.
  117. \param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
  118. */
  119. template <class RandomAccessIter, class Right_shift, class Compare>
  120. inline void float_sort(RandomAccessIter first, RandomAccessIter last,
  121. Right_shift rshift, Compare comp)
  122. {
  123. if (last - first < detail::min_sort_size)
  124. boost::sort::pdqsort(first, last, comp);
  125. else
  126. detail::float_sort(first, last, rshift(*first, 0), rshift, comp);
  127. }
  128. /*!
  129. \brief Float sort algorithm using range with both right-shift and user-defined comparison operator.
  130. \param[in] range Range [first, last) for sorting.
  131. \param[in] rshift Functor that returns the result of shifting the value_type right a specified number of bits.
  132. \param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
  133. */
  134. template <class Range, class Right_shift, class Compare>
  135. inline void float_sort(Range& range, Right_shift rshift, Compare comp)
  136. {
  137. float_sort(boost::begin(range), boost::end(range), rshift, comp);
  138. }
  139. }
  140. }
  141. }
  142. #endif