spreadsort.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Templated generic hybrid sorting
  2. // Copyright Steven J. Ross 2001 - 2009.
  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. Range support provided by:
  13. Alexander Zaitsev
  14. */
  15. #ifndef BOOST_SORT_SPREADSORT_HPP
  16. #define BOOST_SORT_SPREADSORT_HPP
  17. #include <algorithm>
  18. #include <vector>
  19. #include <cstring>
  20. #include <string>
  21. #include <limits>
  22. #include <boost/type_traits.hpp>
  23. #include <boost/sort/spreadsort/integer_sort.hpp>
  24. #include <boost/sort/spreadsort/float_sort.hpp>
  25. #include <boost/sort/spreadsort/string_sort.hpp>
  26. #include <boost/range/begin.hpp>
  27. #include <boost/range/end.hpp>
  28. namespace boost {
  29. namespace sort {
  30. /*! Namespace for spreadsort sort variants for different data types.
  31. \note Use hyperlinks (coloured) to get detailed information about functions.
  32. */
  33. namespace spreadsort {
  34. /*!
  35. \brief Generic @c spreadsort variant detecting integer-type elements so call to @c integer_sort.
  36. \details If the data type provided is an integer, @c integer_sort is used.
  37. \note Sorting other data types requires picking between @c integer_sort, @c float_sort and @c string_sort directly,
  38. as @c spreadsort won't accept types that don't have the appropriate @c type_traits.
  39. \param[in] first Iterator pointer to first element.
  40. \param[in] last Iterator pointing to one beyond the end of data.
  41. \pre [@c first, @c last) is a valid range.
  42. \pre @c RandomAccessIter @c value_type is mutable.
  43. \pre @c RandomAccessIter @c value_type is <a href="http://en.cppreference.com/w/cpp/concept/LessThanComparable">LessThanComparable</a>
  44. \pre @c RandomAccessIter @c value_type supports the @c operator>>,
  45. which returns an integer-type right-shifted a specified number of bits.
  46. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  47. */
  48. template <class RandomAccessIter>
  49. inline typename boost::enable_if_c< std::numeric_limits<
  50. typename std::iterator_traits<RandomAccessIter>::value_type >::is_integer,
  51. void >::type
  52. spreadsort(RandomAccessIter first, RandomAccessIter last)
  53. {
  54. integer_sort(first, last);
  55. }
  56. /*!
  57. \brief Generic @c spreadsort variant detecting float element type so call to @c float_sort.
  58. \details If the data type provided is a float or castable-float, @c float_sort is used.
  59. \note Sorting other data types requires picking between @c integer_sort, @c float_sort and @c string_sort directly,
  60. as @c spreadsort won't accept types that don't have the appropriate @c type_traits.
  61. \param[in] first Iterator pointer to first element.
  62. \param[in] last Iterator pointing to one beyond the end of data.
  63. \pre [@c first, @c last) is a valid range.
  64. \pre @c RandomAccessIter @c value_type is mutable.
  65. \pre @c RandomAccessIter @c value_type is <a href="http://en.cppreference.com/w/cpp/concept/LessThanComparable">LessThanComparable</a>
  66. \pre @c RandomAccessIter @c value_type supports the @c operator>>,
  67. which returns an integer-type right-shifted a specified number of bits.
  68. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  69. */
  70. template <class RandomAccessIter>
  71. inline typename boost::enable_if_c< !std::numeric_limits<
  72. typename std::iterator_traits<RandomAccessIter>::value_type >::is_integer
  73. && std::numeric_limits<
  74. typename std::iterator_traits<RandomAccessIter>::value_type >::is_iec559,
  75. void >::type
  76. spreadsort(RandomAccessIter first, RandomAccessIter last)
  77. {
  78. float_sort(first, last);
  79. }
  80. /*!
  81. \brief Generic @c spreadsort variant detecting string element type so call to @c string_sort for @c std::strings.
  82. \details If the data type provided is a string, @c string_sort is used.
  83. \note Sorting other data types requires picking between @c integer_sort, @c float_sort and @c string_sort directly,
  84. as @c spreadsort won't accept types that don't have the appropriate @c type_traits.
  85. \param[in] first Iterator pointer to first element.
  86. \param[in] last Iterator pointing to one beyond the end of data.
  87. \pre [@c first, @c last) is a valid range.
  88. \pre @c RandomAccessIter @c value_type is mutable.
  89. \pre @c RandomAccessIter @c value_type is <a href="http://en.cppreference.com/w/cpp/concept/LessThanComparable">LessThanComparable</a>
  90. \pre @c RandomAccessIter @c value_type supports the @c operator>>,
  91. which returns an integer-type right-shifted a specified number of bits.
  92. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  93. */
  94. template <class RandomAccessIter>
  95. inline typename boost::enable_if_c<
  96. is_same<typename std::iterator_traits<RandomAccessIter>::value_type,
  97. typename std::string>::value, void >::type
  98. spreadsort(RandomAccessIter first, RandomAccessIter last)
  99. {
  100. string_sort(first, last);
  101. }
  102. /*!
  103. \brief Generic @c spreadsort variant detecting string element type so call to @c string_sort for @c std::wstrings.
  104. \details If the data type provided is a wstring, @c string_sort is used.
  105. \note Sorting other data types requires picking between @c integer_sort, @c float_sort and @c string_sort directly,
  106. as @c spreadsort won't accept types that don't have the appropriate @c type_traits. Also, 2-byte wide-characters are the limit above which string_sort is inefficient, so on platforms with wider characters, this will not accept wstrings.
  107. \param[in] first Iterator pointer to first element.
  108. \param[in] last Iterator pointing to one beyond the end of data.
  109. \pre [@c first, @c last) is a valid range.
  110. \pre @c RandomAccessIter @c value_type is mutable.
  111. \pre @c RandomAccessIter @c value_type is <a href="http://en.cppreference.com/w/cpp/concept/LessThanComparable">LessThanComparable</a>
  112. \pre @c RandomAccessIter @c value_type supports the @c operator>>,
  113. which returns an integer-type right-shifted a specified number of bits.
  114. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  115. */
  116. template <class RandomAccessIter>
  117. inline typename boost::enable_if_c<
  118. is_same<typename std::iterator_traits<RandomAccessIter>::value_type,
  119. typename std::wstring>::value &&
  120. sizeof(wchar_t) == 2, void >::type
  121. spreadsort(RandomAccessIter first, RandomAccessIter last)
  122. {
  123. boost::uint16_t unused = 0;
  124. string_sort(first, last, unused);
  125. }
  126. /*!
  127. \brief Generic @c spreadsort variant detects value_type and calls required sort function.
  128. \note Sorting other data types requires picking between @c integer_sort, @c float_sort and @c string_sort directly,
  129. as @c spreadsort won't accept types that don't have the appropriate @c type_traits.
  130. \param[in] range Range [first, last) for sorting.
  131. \pre [@c first, @c last) is a valid range.
  132. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  133. */
  134. template <class Range>
  135. void spreadsort(Range& range)
  136. {
  137. spreadsort(boost::begin(range), boost::end(range));
  138. }
  139. } // namespace spreadsort
  140. } // namespace sort
  141. } // namespace boost
  142. #endif