71 lines
2.0 KiB
C++
71 lines
2.0 KiB
C++
#ifndef OSRM_UTIL_PERMUTATION_HPP
|
|
#define OSRM_UTIL_PERMUTATION_HPP
|
|
|
|
#include "util/integer_range.hpp"
|
|
|
|
#include <vector>
|
|
|
|
namespace osrm::util
|
|
{
|
|
|
|
namespace permutation_detail
|
|
{
|
|
template <typename T> static inline void swap(T &a, T &b) noexcept { std::swap(a, b); }
|
|
|
|
static inline void swap(std::vector<bool>::reference a, std::vector<bool>::reference b) noexcept
|
|
{
|
|
std::vector<bool>::swap(a, b);
|
|
}
|
|
} // namespace permutation_detail
|
|
|
|
template <typename RandomAccessIterator, typename IndexT>
|
|
void inplacePermutation(RandomAccessIterator begin,
|
|
RandomAccessIterator end,
|
|
const std::vector<IndexT> &old_to_new)
|
|
{
|
|
|
|
std::size_t size = std::distance(begin, end);
|
|
BOOST_ASSERT(old_to_new.size() == size);
|
|
// we need a little bit auxililary space since we need to mark
|
|
// replaced elements in a non-destructive way
|
|
std::vector<bool> was_replaced(size, false);
|
|
for (auto index : util::irange<IndexT>(0, size))
|
|
{
|
|
if (was_replaced[index])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (old_to_new[index] == index)
|
|
{
|
|
was_replaced[index] = true;
|
|
continue;
|
|
}
|
|
|
|
// iterate over a cycle in the permutation
|
|
auto buffer = begin[index];
|
|
auto old_index = index;
|
|
auto new_index = old_to_new[old_index];
|
|
for (; new_index != index; old_index = new_index, new_index = old_to_new[new_index])
|
|
{
|
|
was_replaced[old_index] = true;
|
|
permutation_detail::swap(buffer, begin[new_index]);
|
|
}
|
|
was_replaced[old_index] = true;
|
|
permutation_detail::swap(buffer, begin[index]);
|
|
}
|
|
}
|
|
|
|
template <typename IndexT>
|
|
std::vector<IndexT> orderingToPermutation(const std::vector<IndexT> &ordering)
|
|
{
|
|
std::vector<IndexT> permutation(ordering.size());
|
|
for (auto index : util::irange<IndexT>(0, ordering.size()))
|
|
permutation[ordering[index]] = index;
|
|
|
|
return permutation;
|
|
}
|
|
} // namespace osrm::util
|
|
|
|
#endif
|