#if !defined HAVE_RADIXPERMUTE_H__
#define      HAVE_RADIXPERMUTE_H__


#include "fxttypes.h"
#include "bits/bitsperlong.h"

#include "aux0/swap.h"


// defined in radixpermute.cc:
extern ulong radix_permute_nt[];  // == 9, 90, 900, ...  for r=10
extern ulong radix_permute_kt[];  // == 1, 10, 100, ...  for r=10
#define  NT  radix_permute_nt
#define  KT  radix_permute_kt

template <typename Type>
void radix_permute(Type *f, ulong n, ulong r)
//
// swap elements with index pairs i, j where the
// radix-r representation of i and j are mutually
// digit-reversed (e.g. 436 <--> 634)
//
// This is a radix-r generalization of revbin_permute()
// revbin_permute(f, n)) =^= radix_permute(f, n, 2)
//
// must have:
//  n == p**x for some x>=1
//  r >= 2
//
// original by Andre Piotrowski
// this optimized version avoids the (n*log(n)) divisions
// by using two size-BITS_PER_LONG tables NT[], KT[]
//
{
    ulong x = 0;
    NT[0] = r-1;
    KT[0] = 1;
    while ( 1 )
    {
        ulong z = KT[x] * r;
        if ( z>n )  break;
        ++x;
        KT[x] = z;

        NT[x] = NT[x-1] * r;
    }
    // here: n == p**x

    for (ulong i=0, j=0;  i < n-1;  i++)
    {
        if ( i<j )  swap2(f[i], f[j]);

        ulong t = x - 1;
        ulong k = NT[t];  // =^=  k = (r-1) * n / r;

        while ( k<=j )
        {
            j -= k;
            k = NT[--t];  // =^=  k /= r;
        }

        j += KT[t]; // =^=  j += (k/(r-1));
    }
}
// -------------------------

#undef  NT
#undef  KT


#endif // !defined HAVE_RADIXPERMUTE_H__
