PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/package/boost_1_58_0/boost/sort/spreadsort/integer_sort.hpp

https://gitlab.com/cdeclare/intcrypt
C++ Header | 185 lines | 40 code | 11 blank | 134 comment | 3 complexity | 40f91cbde59fcedc121adad0bcdf004c MD5 | raw file
  1. //Templated Spreadsort-based implementation of integer_sort
  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. Doxygen comments by Paul A. Bristow Jan 2015
  11. */
  12. #ifndef BOOST_INTEGER_SORT_HPP
  13. #define BOOST_INTEGER_SORT_HPP
  14. #include <algorithm>
  15. #include <vector>
  16. #include <cstring>
  17. #include <limits>
  18. #include <boost/static_assert.hpp>
  19. #include <boost/sort/spreadsort/detail/constants.hpp>
  20. #include <boost/sort/spreadsort/detail/integer_sort.hpp>
  21. namespace boost {
  22. namespace sort {
  23. namespace spreadsort {
  24. //Top-level sorting call for integers.
  25. /*! \brief Integer sort algorithm using random access iterators.
  26. (All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
  27. \details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
  28. which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
  29. Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
  30. so @c integer_sort is asymptotically faster
  31. than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
  32. so its worst-case with default settings for 32-bit integers is
  33. <em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
  34. Some performance plots of runtime vs. n and log(range) are provided:\n
  35. <a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
  36. \n
  37. <a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
  38. \param[in] first Iterator pointer to first element.
  39. \param[in] last Iterator pointing to one beyond the end of data.
  40. \pre [@c first, @c last) is a valid range.
  41. \pre @c RandomAccessIter @c value_type is mutable.
  42. \pre @c RandomAccessIter @c value_type is <a href="http://en.cppreference.com/w/cpp/concept/LessThanComparable">LessThanComparable</a>
  43. \pre @c RandomAccessIter @c value_type supports the @c operator>>,
  44. which returns an integer-type right-shifted a specified number of bits.
  45. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  46. \throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
  47. the right shift, subtraction of right-shifted elements, functors, or any operations on iterators throw.
  48. \warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
  49. \warning Invalid arguments cause undefined behaviour.
  50. \note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
  51. enabling faster generic-programming.
  52. \remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
  53. \remark * N is @c last - @c first,
  54. \remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
  55. \remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
  56. */
  57. template <class RandomAccessIter>
  58. inline void integer_sort(RandomAccessIter first, RandomAccessIter last)
  59. {
  60. // Don't sort if it's too small to optimize.
  61. if (last - first < detail::min_sort_size)
  62. std::sort(first, last);
  63. else
  64. detail::integer_sort(first, last, *first >> 0);
  65. }
  66. /*! \brief Integer sort algorithm using random access iterators with both right-shift and user-defined comparison operator.
  67. (All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
  68. \details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
  69. which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
  70. Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
  71. so @c integer_sort is asymptotically faster
  72. than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
  73. so its worst-case with default settings for 32-bit integers is
  74. <em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
  75. Some performance plots of runtime vs. n and log(range) are provided:\n
  76. <a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
  77. \n
  78. <a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
  79. \param[in] first Iterator pointer to first element.
  80. \param[in] last Iterator pointing to one beyond the end of data.
  81. \param[in] shift Functor that returns the result of shifting the value_type right a specified number of bits.
  82. \param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
  83. \pre [@c first, @c last) is a valid range.
  84. \pre @c RandomAccessIter @c value_type is mutable.
  85. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  86. \return @c void.
  87. \throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
  88. the right shift, subtraction of right-shifted elements, functors,
  89. or any operations on iterators throw.
  90. \warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
  91. \warning Invalid arguments cause undefined behaviour.
  92. \note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
  93. enabling faster generic-programming.
  94. \remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
  95. \remark * N is @c last - @c first,
  96. \remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
  97. \remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
  98. */
  99. template <class RandomAccessIter, class Right_shift, class Compare>
  100. inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
  101. Right_shift shift, Compare comp) {
  102. if (last - first < detail::min_sort_size)
  103. std::sort(first, last, comp);
  104. else
  105. detail::integer_sort(first, last, shift(*first, 0), shift, comp);
  106. }
  107. /*! \brief Integer sort algorithm using random access iterators with just right-shift functor.
  108. (All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
  109. \details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
  110. which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
  111. \par Performance:
  112. Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
  113. so @c integer_sort is asymptotically faster
  114. than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
  115. so its worst-case with default settings for 32-bit integers is
  116. <em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
  117. Some performance plots of runtime vs. n and log(range) are provided:\n
  118. * <a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>\n
  119. * <a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
  120. \param[in] first Iterator pointer to first element.
  121. \param[in] last Iterator pointing to one beyond the end of data.
  122. \param[in] shift A functor that returns the result of shifting the value_type right a specified number of bits.
  123. \pre [@c first, @c last) is a valid range.
  124. \pre @c RandomAccessIter @c value_type is mutable.
  125. \pre @c RandomAccessIter @c value_type is <a href="http://en.cppreference.com/w/cpp/concept/LessThanComparable">LessThanComparable</a>
  126. \post The elements in the range [@c first, @c last) are sorted in ascending order.
  127. \throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
  128. the right shift, subtraction of right-shifted elements, functors,
  129. or any operations on iterators throw.
  130. \warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
  131. \warning Invalid arguments cause undefined behaviour.
  132. \note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
  133. enabling faster generic-programming.
  134. \remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
  135. \remark * N is @c last - @c first,
  136. \remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
  137. \remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
  138. */
  139. template <class RandomAccessIter, class Right_shift>
  140. inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
  141. Right_shift shift) {
  142. if (last - first < detail::min_sort_size)
  143. std::sort(first, last);
  144. else
  145. detail::integer_sort(first, last, shift(*first, 0), shift);
  146. }
  147. }
  148. }
  149. }
  150. #endif