indirect.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //----------------------------------------------------------------------------
  2. /// @file indirect.hpp
  3. /// @brief Indirect algorithm
  4. ///
  5. /// @author Copyright (c) 2016 Francisco Jose Tapia (fjtapia@gmail.com )\n
  6. /// Distributed under the Boost Software License, Version 1.0.\n
  7. /// ( See accompanying file LICENSE_1_0.txt or copy at
  8. /// http://www.boost.org/LICENSE_1_0.txt )
  9. /// @version 0.1
  10. ///
  11. /// @remarks
  12. //-----------------------------------------------------------------------------
  13. #ifndef __BOOST_SORT_PARALLEL_COMMON_INDIRECT_HPP
  14. #define __BOOST_SORT_PARALLEL_COMMON_INDIRECT_HPP
  15. #include <boost/sort/common/util/traits.hpp>
  16. #include <functional>
  17. #include <iterator>
  18. #include <type_traits>
  19. #include <vector>
  20. namespace boost
  21. {
  22. namespace sort
  23. {
  24. namespace common
  25. {
  26. //
  27. //---------------------------------------------------------------------------
  28. /// @struct less_ptr_no_null
  29. ///
  30. /// @remarks this is the comparison object for pointers. Compare the objects
  31. /// pointed by the iterators
  32. //---------------------------------------------------------------------------
  33. template<class Iter_t, class Compare = util::compare_iter<Iter_t> >
  34. struct less_ptr_no_null
  35. {
  36. //----------------------------- Variables -----------------------
  37. Compare comp; // comparison object of the elements pointed by Iter_t
  38. //------------------------------------------------------------------------
  39. // function : less_ptr_no_null
  40. /// @brief constructor from a Compare object
  41. /// @param C1 : comparison object
  42. //-----------------------------------------------------------------------
  43. less_ptr_no_null(Compare C1 = Compare()): comp(C1) { };
  44. //------------------------------------------------------------------------
  45. // function : operator ( )
  46. /// @brief Make the comparison of the objects pointed by T1 and T2, using
  47. // the internal comp
  48. //
  49. /// @param T1 : first iterator
  50. /// @param T2 : second iterator
  51. /// @return bool result of the comparison
  52. //-----------------------------------------------------------------------
  53. bool operator( )(Iter_t T1, Iter_t T2) const
  54. {
  55. return comp(*T1, *T2);
  56. };
  57. };
  58. //
  59. //-----------------------------------------------------------------------------
  60. // function : create_index
  61. /// @brief From a vector of objects, create a vector of iterators to
  62. /// the objects
  63. ///
  64. /// @param first : iterator to the first element of the range
  65. /// @param last : iterator to the element after the last of the range
  66. /// @param index : vector where store the iterators
  67. //-----------------------------------------------------------------------------
  68. template<class Iter_t>
  69. void create_index(Iter_t first, Iter_t last, std::vector<Iter_t> &index)
  70. {
  71. auto nelem = last - first;
  72. assert(nelem >= 0);
  73. index.clear();
  74. index.reserve(nelem);
  75. for (; first != last; ++first) index.push_back(first);
  76. }
  77. //
  78. //-----------------------------------------------------------------------------
  79. // function : sort_index
  80. /// @brief This function transform a logical sort of the elements in the index
  81. /// in a physical sort
  82. //
  83. /// @param global_first : iterator to the first element of the data
  84. /// @param [in] index : vector of the iterators
  85. //-----------------------------------------------------------------------------
  86. template<class Iter_t>
  87. void sort_index(Iter_t global_first, std::vector<Iter_t> &index)
  88. {
  89. typedef util::value_iter<Iter_t> value_t;
  90. size_t pos_dest = 0;
  91. size_t pos_src = 0;
  92. size_t pos_in_vector = 0;
  93. size_t nelem = index.size();
  94. Iter_t it_dest, it_src;
  95. while (pos_in_vector < nelem)
  96. {
  97. while (pos_in_vector < nelem &&
  98. (size_t(index[pos_in_vector] - global_first)) == pos_in_vector)
  99. {
  100. ++pos_in_vector;
  101. }
  102. if (pos_in_vector == nelem) return;
  103. pos_dest = pos_src = pos_in_vector;
  104. it_dest = global_first + pos_dest;
  105. value_t Aux = std::move(*it_dest);
  106. while ((pos_src = (size_t(index[pos_dest] - global_first)))
  107. != pos_in_vector)
  108. {
  109. index[pos_dest] = it_dest;
  110. it_src = global_first + pos_src;
  111. *it_dest = std::move(*it_src);
  112. it_dest = it_src;
  113. pos_dest = pos_src;
  114. }
  115. *it_dest = std::move(Aux);
  116. index[pos_dest] = it_dest;
  117. ++pos_in_vector;
  118. }
  119. }
  120. template<class func, class Iter_t, class Compare = util::compare_iter<Iter_t> >
  121. void indirect_sort(func method, Iter_t first, Iter_t last, Compare comp)
  122. {
  123. auto nelem = (last - first);
  124. assert(nelem >= 0);
  125. if (nelem < 2) return;
  126. std::vector<Iter_t> index;
  127. index.reserve((size_t) nelem);
  128. create_index(first, last, index);
  129. less_ptr_no_null<Iter_t, Compare> index_comp(comp);
  130. method(index.begin(), index.end(), index_comp);
  131. sort_index(first, index);
  132. }
  133. //
  134. //****************************************************************************
  135. }// End namespace common
  136. }// End namespace sort
  137. }// End namespace boost
  138. //****************************************************************************
  139. //
  140. #endif