#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