/Src/Dependencies/Boost/boost/graph/detail/histogram_sort.hpp

http://hadesmem.googlecode.com/ · C++ Header · 288 lines · 231 code · 31 blank · 26 comment · 28 complexity · 6093d0435866e6f4211ddf7c0b3cefa8 MD5 · raw file

  1. // Copyright 2009 The Trustees of Indiana University.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Jeremiah Willcock
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP
  8. #define BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP
  9. #include <boost/assert.hpp>
  10. namespace boost {
  11. namespace graph {
  12. namespace detail {
  13. template<typename InputIterator>
  14. size_t
  15. reserve_count_for_single_pass_helper(InputIterator, InputIterator,
  16. std::input_iterator_tag)
  17. {
  18. // Do nothing: we have no idea how much storage to reserve.
  19. return 0;
  20. }
  21. template<typename InputIterator>
  22. size_t
  23. reserve_count_for_single_pass_helper(InputIterator first, InputIterator last,
  24. std::random_access_iterator_tag)
  25. {
  26. using std::distance;
  27. typename std::iterator_traits<InputIterator>::difference_type n =
  28. distance(first, last);
  29. return (size_t)n;
  30. }
  31. template<typename InputIterator>
  32. size_t
  33. reserve_count_for_single_pass(InputIterator first, InputIterator last) {
  34. typedef typename std::iterator_traits<InputIterator>::iterator_category
  35. category;
  36. return reserve_count_for_single_pass_helper(first, last, category());
  37. }
  38. template <typename KeyIterator, typename RowstartIterator,
  39. typename VerticesSize, typename KeyFilter, typename KeyTransform>
  40. void
  41. count_starts
  42. (KeyIterator begin, KeyIterator end,
  43. RowstartIterator starts, // Must support numverts + 1 elements
  44. VerticesSize numkeys,
  45. KeyFilter key_filter,
  46. KeyTransform key_transform) {
  47. typedef VerticesSize vertices_size_type;
  48. typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
  49. // Put the degree of each vertex v into m_rowstart[v + 1]
  50. for (KeyIterator i = begin; i != end; ++i) {
  51. if (key_filter(*i)) {
  52. ++starts[key_transform(*i) + 1];
  53. }
  54. }
  55. // Compute the partial sum of the degrees to get the actual values of
  56. // m_rowstart
  57. EdgeIndex start_of_this_row = 0;
  58. starts[0] = start_of_this_row;
  59. for (vertices_size_type i = 1; i <= numkeys; ++i) {
  60. start_of_this_row += starts[i];
  61. starts[i] = start_of_this_row;
  62. }
  63. }
  64. template <typename KeyIterator, typename RowstartIterator,
  65. typename NumKeys,
  66. typename Value1InputIter,
  67. typename Value1OutputIter, typename KeyFilter, typename KeyTransform>
  68. void
  69. histogram_sort(KeyIterator key_begin, KeyIterator key_end,
  70. RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
  71. NumKeys numkeys,
  72. Value1InputIter values1_begin,
  73. Value1OutputIter values1_out,
  74. KeyFilter key_filter,
  75. KeyTransform key_transform) {
  76. typedef NumKeys vertices_size_type;
  77. typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
  78. // Histogram sort the edges by their source vertices, putting the targets
  79. // into m_column. The index current_insert_positions[v] contains the next
  80. // location to insert out edges for vertex v.
  81. std::vector<EdgeIndex>
  82. current_insert_positions(rowstart, rowstart + numkeys);
  83. Value1InputIter v1i = values1_begin;
  84. for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i) {
  85. if (key_filter(*i)) {
  86. vertices_size_type source = key_transform(*i);
  87. EdgeIndex insert_pos = current_insert_positions[source];
  88. ++current_insert_positions[source];
  89. values1_out[insert_pos] = *v1i;
  90. }
  91. }
  92. }
  93. template <typename KeyIterator, typename RowstartIterator,
  94. typename NumKeys,
  95. typename Value1InputIter,
  96. typename Value1OutputIter,
  97. typename Value2InputIter,
  98. typename Value2OutputIter,
  99. typename KeyFilter, typename KeyTransform>
  100. void
  101. histogram_sort(KeyIterator key_begin, KeyIterator key_end,
  102. RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
  103. NumKeys numkeys,
  104. Value1InputIter values1_begin,
  105. Value1OutputIter values1_out,
  106. Value2InputIter values2_begin,
  107. Value2OutputIter values2_out,
  108. KeyFilter key_filter,
  109. KeyTransform key_transform) {
  110. typedef NumKeys vertices_size_type;
  111. typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
  112. // Histogram sort the edges by their source vertices, putting the targets
  113. // into m_column. The index current_insert_positions[v] contains the next
  114. // location to insert out edges for vertex v.
  115. std::vector<EdgeIndex>
  116. current_insert_positions(rowstart, rowstart + numkeys);
  117. Value1InputIter v1i = values1_begin;
  118. Value2InputIter v2i = values2_begin;
  119. for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i, ++v2i) {
  120. if (key_filter(*i)) {
  121. vertices_size_type source = key_transform(*i);
  122. EdgeIndex insert_pos = current_insert_positions[source];
  123. ++current_insert_positions[source];
  124. values1_out[insert_pos] = *v1i;
  125. values2_out[insert_pos] = *v2i;
  126. }
  127. }
  128. }
  129. template <typename KeyIterator, typename RowstartIterator,
  130. typename NumKeys,
  131. typename Value1Iter,
  132. typename KeyTransform>
  133. void
  134. histogram_sort_inplace(KeyIterator key_begin,
  135. RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
  136. NumKeys numkeys,
  137. Value1Iter values1,
  138. KeyTransform key_transform) {
  139. typedef NumKeys vertices_size_type;
  140. typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
  141. // 1. Copy m_rowstart (except last element) to get insert positions
  142. std::vector<EdgeIndex> insert_positions(rowstart, rowstart + numkeys);
  143. // 2. Swap the sources and targets into place
  144. for (size_t i = 0; i < rowstart[numkeys]; ++i) {
  145. // While edge i is not in the right bucket:
  146. while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) {
  147. // Add a slot in the right bucket
  148. size_t target_pos = insert_positions[key_transform(key_begin[i])]++;
  149. BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]);
  150. if (target_pos == i) continue;
  151. // Swap this edge into place
  152. using std::swap;
  153. swap(key_begin[i], key_begin[target_pos]);
  154. swap(values1[i], values1[target_pos]);
  155. }
  156. }
  157. }
  158. template <typename KeyIterator, typename RowstartIterator,
  159. typename NumKeys,
  160. typename Value1Iter,
  161. typename Value2Iter,
  162. typename KeyTransform>
  163. void
  164. histogram_sort_inplace(KeyIterator key_begin,
  165. RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
  166. NumKeys numkeys,
  167. Value1Iter values1,
  168. Value2Iter values2,
  169. KeyTransform key_transform) {
  170. typedef NumKeys vertices_size_type;
  171. typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
  172. // 1. Copy m_rowstart (except last element) to get insert positions
  173. std::vector<EdgeIndex> insert_positions(rowstart, rowstart + numkeys);
  174. // 2. Swap the sources and targets into place
  175. for (size_t i = 0; i < rowstart[numkeys]; ++i) {
  176. // While edge i is not in the right bucket:
  177. while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) {
  178. // Add a slot in the right bucket
  179. size_t target_pos = insert_positions[key_transform(key_begin[i])]++;
  180. BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]);
  181. if (target_pos == i) continue;
  182. // Swap this edge into place
  183. using std::swap;
  184. swap(key_begin[i], key_begin[target_pos]);
  185. swap(values1[i], values1[target_pos]);
  186. swap(values2[i], values2[target_pos]);
  187. }
  188. }
  189. }
  190. template <typename InputIterator, typename VerticesSize>
  191. void split_into_separate_coords(InputIterator begin, InputIterator end,
  192. std::vector<VerticesSize>& firsts,
  193. std::vector<VerticesSize>& seconds) {
  194. firsts.clear();
  195. seconds.clear();
  196. size_t reserve_size
  197. = detail::reserve_count_for_single_pass(begin, end);
  198. firsts.reserve(reserve_size);
  199. seconds.reserve(reserve_size);
  200. for (; begin != end; ++begin) {
  201. std::pair<VerticesSize, VerticesSize> edge = *begin;
  202. firsts.push_back(edge.first);
  203. seconds.push_back(edge.second);
  204. }
  205. }
  206. template <typename InputIterator, typename VerticesSize, typename SourceFilter>
  207. void split_into_separate_coords_filtered
  208. (InputIterator begin, InputIterator end,
  209. std::vector<VerticesSize>& firsts,
  210. std::vector<VerticesSize>& seconds,
  211. const SourceFilter& filter) {
  212. firsts.clear();
  213. seconds.clear();
  214. for (; begin != end; ++begin) {
  215. std::pair<VerticesSize, VerticesSize> edge = *begin;
  216. if (filter(edge.first)) {
  217. firsts.push_back(edge.first);
  218. seconds.push_back(edge.second);
  219. }
  220. }
  221. }
  222. template <typename InputIterator, typename PropInputIterator,
  223. typename VerticesSize, typename PropType, typename SourceFilter>
  224. void split_into_separate_coords_filtered
  225. (InputIterator begin, InputIterator end,
  226. PropInputIterator props,
  227. std::vector<VerticesSize>& firsts,
  228. std::vector<VerticesSize>& seconds,
  229. std::vector<PropType>& props_out,
  230. const SourceFilter& filter) {
  231. firsts.clear();
  232. seconds.clear();
  233. props_out.clear();
  234. for (; begin != end; ++begin) {
  235. std::pair<VerticesSize, VerticesSize> edge = *begin;
  236. if (filter(edge.first)) {
  237. firsts.push_back(edge.first);
  238. seconds.push_back(edge.second);
  239. props_out.push_back(*props);
  240. }
  241. ++props;
  242. }
  243. }
  244. template <typename Pair>
  245. struct project1st {
  246. typedef typename Pair::first_type result_type;
  247. const result_type& operator()(const Pair& p) const {return p.first;}
  248. };
  249. template <typename Pair>
  250. struct project2nd {
  251. typedef typename Pair::second_type result_type;
  252. const result_type& operator()(const Pair& p) const {return p.second;}
  253. };
  254. }
  255. }
  256. }
  257. #endif // BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP