
#include "fxtalloca.h"
#include "aux0/swap.h"
#include "fxttypes.h"

void
perm2ffact_swp(const ulong *x, ulong n, ulong *fc)
// Convert permutation in x[0,...,n-1] into
//   the (n-1) digit (swaps) factorial representation in fc[0,...,n-2].
// One has: fc[0]<n, fc[1]<n-1, ..., fc[n-2]<2 (falling radices)
// Work is proportional n.
{
    ALLOCA(ulong, t, n);
    for (ulong k=0; k<n; ++k)  t[k] = x[k];
    ALLOCA(ulong, ti, n);  // inverse permutation
    for (ulong k=0; k<n; ++k)  ti[t[k]] = k;

    for (ulong k=0; k<n-1; ++k)
    {
        ulong tk = t[k];  // >= k
        fc[k] = tk - k;

//        ulong j = k;
//        while ( t[j]!=k ) ++j;
////        swap2(t[k], t[j]);
//        t[j] = t[k];  // t[k] = k

        ulong j = ti[k];  // location of element k
//        swap2(ti[t[k]], ti[t[j]]);
        ti[tk] = ti[t[j]];
//        swap2(t[k], t[j]);
        t[j] = tk;  // t[k] = k
    }
}
// -------------------------

void
ffact2perm_swp(const ulong *fc, ulong n, ulong *x)
// Inverse of perm2ffact_swp().
// Permutation is different than that obtained via ffact2perm().
// Work is proportional n.
{
    for (ulong k=0; k<n; ++k)  x[k] = k;
    for (ulong k=0; k<n-1; ++k)
    {
        ulong fa = fc[k];
        swap2( x[k], x[k+fa] );
    }
}
// -------------------------

void
ffact2invperm_swp(const ulong *fc, ulong n, ulong *x)
// Generate inverse permutation wrt. ffact2perm_swp().
// Work is proportional n.
{
    for (ulong k=0; k<n; ++k)  x[k] = k;
    if ( n<=1 )  return;
    ulong k = n-2;
    do
    {
        ulong fa = fc[k];
        swap2( x[k], x[k+fa] );
    }
    while ( k-- );
}
// -------------------------


void
perm2rfact_swp(const ulong *x, ulong n, ulong *fc)
// Convert permutation in x[0,...,n-1] into
//   the (n-1) digit (swaps) factorial representation in fc[0,...,n-2].
// One has: fc[0]<2, fc[1]<3, ..., fc[n-2]<n (rising radices)
// Work is proportional n.
{
    ALLOCA(ulong, t, n);
    for (ulong k=0; k<n; ++k)  t[k] = x[k];
    ALLOCA(ulong, ti, n);  // inverse permutation
    for (ulong k=0; k<n; ++k)  ti[t[k]] = k;

    for (ulong k=0; k<n-1; ++k)
    {
//        ulong j = k;
//        while ( t[j]!=k ) ++j;
//        fc[n-2-k] = j - k;
////        swap2(t[k], t[j]);
//        t[j] = t[k];  // t[k] = k

        ulong j = ti[k];  // location of element k, j>=k
        fc[n-2-k] = j - k;
//        swap2(ti[t[k]], ti[t[j]]);
        ulong tk = t[k];
        ti[tk] = ti[t[j]];
//        swap2(t[k], t[j]);
        t[j] = tk;  // t[k] = k
    }
}
// -------------------------

void
rfact2perm_swp(const ulong *fc, ulong n, ulong *x)
// Inverse of perm2rfact_swp().
// Permutation is different than that obtained via rfact2perm().
// Work is proportional n.
{
    for (ulong k=0; k<n; ++k)  x[k] = k;
    for (ulong k=0,j=n-2; k<n-1; ++k,--j)
    {
        ulong fa = fc[k];
        swap2( x[j], x[j+fa] );
    }
}
// -------------------------


void
rfact2invperm_swp(const ulong *fc, ulong n, ulong *x)
// Generate inverse permutation wrt. rfact2perm_swp().
// Work is proportional n.
{
    for (ulong k=0; k<n; ++k)  x[k] = k;
    if ( n<=1 )  return;
    ulong k = n-2, j=0;
    do
    {
        ulong fa = fc[k];
        swap2( x[j], x[j+fa] );
        ++j;
    }
    while ( k-- );
}
// -------------------------


