| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 | // (C) Copyright Jeremy Siek 2001.// 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)#ifndef BOOST_PERMUTATION_HPP#define BOOST_PERMUTATION_HPP#include <vector>#include <memory>#include <functional>#include <algorithm>#include <boost/graph/detail/shadow_iterator.hpp>namespace boost{template < class Iter1, class Iter2 >void permute_serial(Iter1 permuter, Iter1 last, Iter2 result){#ifdef BOOST_NO_STD_ITERATOR_TRAITS    typedef std::ptrdiff_t D :#else    typedef typename std::iterator_traits< Iter1 >::difference_type D;#endif        D n        = 0;    while (permuter != last)    {        std::swap(result[n], result[*permuter]);        ++n;        ++permuter;    }}template < class InIter, class RandIterP, class RandIterR >void permute_copy(InIter first, InIter last, RandIterP p, RandIterR result){#ifdef BOOST_NO_STD_ITERATOR_TRAITS    typedef std::ptrdiff_t i = 0;#else    typename std::iterator_traits< RandIterP >::difference_type i = 0;#endif    for (; first != last; ++first, ++i)        result[p[i]] = *first;}namespace detail{    template < class RandIter, class RandIterPerm, class D, class T >    void permute_helper(RandIter first, RandIter last, RandIterPerm p, D, T)    {        D i = 0, pi, n = last - first, cycle_start;        T tmp;        std::vector< int > visited(n, false);        while (i != n)        { // continue until all elements have been processed            cycle_start = i;            tmp = first[i];            do            { // walk around a cycle                pi = p[i];                visited[pi] = true;                std::swap(tmp, first[pi]);                i = pi;            } while (i != cycle_start);            // find the next cycle            for (i = 0; i < n; ++i)                if (visited[i] == false)                    break;        }    }} // namespace detailtemplate < class RandIter, class RandIterPerm >void permute(RandIter first, RandIter last, RandIterPerm p){    detail::permute_helper(first, last, p, last - first, *first);}// Knuth 1.3.3, Vol. 1 p 176// modified for zero-based arrays// time complexity?//// WARNING: T must be a signed integer!template < class PermIter > void invert_permutation(PermIter X, PermIter Xend){#ifdef BOOST_NO_STD_ITERATOR_TRAITS    typedef std::ptrdiff_t T :#else    typedef typename std::iterator_traits< PermIter >::value_type T;#endif        T n        = Xend - X;    T m = n;    T j = -1;    while (m > 0)    {        T i = X[m - 1] + 1;        if (i > 0)        {            do            {                X[m - 1] = j - 1;                j = -m;                m = i;                i = X[m - 1] + 1;            } while (i > 0);            i = j;        }        X[m - 1] = -i - 1;        --m;    }}// Takes a "normal" permutation array (and its inverse), and turns it// into a BLAS-style permutation array (which can be thought of as a// serialized permutation).template < class Iter1, class Iter2, class Iter3 >inline void serialize_permutation(Iter1 q, Iter1 q_end, Iter2 q_inv, Iter3 p){#ifdef BOOST_NO_STD_ITERATOR_TRAITS    typedef std::ptrdiff_t P1;    typedef std::ptrdiff_t P2;    typedef std::ptrdiff_t D;#else    typedef typename std::iterator_traits< Iter1 >::value_type P1;    typedef typename std::iterator_traits< Iter2 >::value_type P2;    typedef typename std::iterator_traits< Iter1 >::difference_type D;#endif    D n = q_end - q;    for (D i = 0; i < n; ++i)    {        P1 qi = q[i];        P2 qii = q_inv[i];        *p++ = qii;        std::swap(q[i], q[qii]);        std::swap(q_inv[i], q_inv[qi]);    }}// Not used anymore, leaving it here for future reference.template < typename Iter, typename Compare >void merge_sort(Iter first, Iter last, Compare cmp){    if (first + 1 < last)    {        Iter mid = first + (last - first) / 2;        merge_sort(first, mid, cmp);        merge_sort(mid, last, cmp);        std::inplace_merge(first, mid, last, cmp);    }}// time: N log N + 3N + ?// space: 2Ntemplate < class Iter, class IterP, class Cmp, class Alloc >inline void sortp(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc){    typedef typename std::iterator_traits< IterP >::value_type P;    typedef typename std::iterator_traits< IterP >::difference_type D;    D n = last - first;    std::vector< P, Alloc > q(n);    for (D i = 0; i < n; ++i)        q[i] = i;    std::sort(make_shadow_iter(first, q.begin()),        make_shadow_iter(last, q.end()), shadow_cmp< Cmp >(cmp));    invert_permutation(q.begin(), q.end());    std::copy(q.begin(), q.end(), p);}template < class Iter, class IterP, class Cmp >inline void sortp(Iter first, Iter last, IterP p, Cmp cmp){    typedef typename std::iterator_traits< IterP >::value_type P;    sortp(first, last, p, cmp, std::allocator< P >());}template < class Iter, class IterP >inline void sortp(Iter first, Iter last, IterP p){    typedef typename std::iterator_traits< Iter >::value_type T;    typedef typename std::iterator_traits< IterP >::value_type P;    sortp(first, last, p, std::less< T >(), std::allocator< P >());}template < class Iter, class IterP, class Cmp, class Alloc >inline void sortv(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc){    typedef typename std::iterator_traits< IterP >::value_type P;    typedef typename std::iterator_traits< IterP >::difference_type D;    D n = last - first;    std::vector< P, Alloc > q(n), q_inv(n);    for (D i = 0; i < n; ++i)        q_inv[i] = i;    std::sort(make_shadow_iter(first, q_inv.begin()),        make_shadow_iter(last, q_inv.end()), shadow_cmp< Cmp >(cmp));    std::copy(q_inv, q_inv.end(), q.begin());    invert_permutation(q.begin(), q.end());    serialize_permutation(q.begin(), q.end(), q_inv.end(), p);}} // namespace boost#endif // BOOST_PERMUTATION_HPP
 |