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