PageRenderTime 64ms CodeModel.GetById 27ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

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