|
|
@ -1,16 +1,14 @@
|
|
|
|
#include <amscppperm1/amscppperm1.hpp>
|
|
|
|
#include <amscppperm1/amscppperm1.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
namespace ams
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace perm
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
//basic factorial found with integer loop
|
|
|
|
//basic factorial found with integer loop
|
|
|
|
int factorial(int n)
|
|
|
|
int amsperm1_factorial(int n)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int I;
|
|
|
|
int I;
|
|
|
|
int ret = 0;
|
|
|
|
int ret = 0;
|
|
|
|
if(n>=0)
|
|
|
|
if(n>=0 && n<=12)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ret = 1;
|
|
|
|
ret = 1;
|
|
|
|
for(I=0;I<n;I++)
|
|
|
|
for(I=0;I<n;I++)
|
|
|
@ -18,29 +16,33 @@ namespace perm
|
|
|
|
ret = ret*(I+1);
|
|
|
|
ret = ret*(I+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(n>12)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ret = -1; //overflow error
|
|
|
|
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//returns a factoriadic multi-index for a given index.
|
|
|
|
//returns a factoriadic multi-index for a given index.
|
|
|
|
//Each factoriadic multi-index corresponds to a permutation according to a simple algorithm
|
|
|
|
//Each factoriadic multi-index corresponds to a permutation according to a simple algorithm
|
|
|
|
// factoriadic indices range from (ex 4 dim case) {0,0,0,0} to {3,2,1,0}
|
|
|
|
// factoriadic indices range from (ex 4 length case) {0,0,0,0} to {3,2,1,0}
|
|
|
|
// parameters:
|
|
|
|
// parameters:
|
|
|
|
// index - [0 to factorial(ndim)) index of permutation
|
|
|
|
// index - [0 to factorial(length)) index of permutation
|
|
|
|
// mindex - factoriadic multi-index output (size=ndim)
|
|
|
|
// mindex - factoriadic multi-index output (size=length)
|
|
|
|
// ndim - dimension of the permutation (number of elements to permute)
|
|
|
|
// length - length of the permutation (number of elements to permute)
|
|
|
|
// return value:
|
|
|
|
// return value:
|
|
|
|
// 0: success
|
|
|
|
// 0: success
|
|
|
|
// -1 : privided index was out of the valid range
|
|
|
|
// -1 : privided index was out of the valid range
|
|
|
|
int index_to_mindex(int index, int *mindex, int ndim)
|
|
|
|
int amsperm1_index_to_mindex(int index, int *mindex, int length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int ret = amsperm1_failure;
|
|
|
|
int I,J,K;
|
|
|
|
int I,J,K;
|
|
|
|
if(index>=0 && index<factorial(ndim))
|
|
|
|
if(index>=0 && index<amsperm1_factorial(length))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ret = 0; //success
|
|
|
|
ret = amsperm1_success; //success
|
|
|
|
K = ndim;
|
|
|
|
K = length;
|
|
|
|
J = index;
|
|
|
|
J = index;
|
|
|
|
for(I=0;I<ndim;I++)
|
|
|
|
for(I=0;I<length;I++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mindex[I] = J%K;
|
|
|
|
mindex[I] = J%K;
|
|
|
|
J = (J - mindex[I])/K;
|
|
|
|
J = (J - mindex[I])/K;
|
|
|
@ -49,9 +51,9 @@ namespace perm
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ret = -1; //error
|
|
|
|
ret = amsperm1_failure; //error
|
|
|
|
//invalid index
|
|
|
|
//invalid index
|
|
|
|
for(I=0;I<ndim;I++)
|
|
|
|
for(I=0;I<length;I++)
|
|
|
|
mindex[I] = -1;
|
|
|
|
mindex[I] = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -60,15 +62,18 @@ namespace perm
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Is the multi-index in the appropriate factoriadic range?
|
|
|
|
//Is the multi-index in the appropriate factoriadic range?
|
|
|
|
// position 0 can range from [0 to ndim)
|
|
|
|
// position 0 can range from [0 to length)
|
|
|
|
// position 1 can range from [0 to (ndim-1))
|
|
|
|
// position 1 can range from [0 to (length-1))
|
|
|
|
bool mindex_valid(int *mindex, int ndim)
|
|
|
|
//parameters:
|
|
|
|
|
|
|
|
// int mindex[length] - multi-index input
|
|
|
|
|
|
|
|
// int length - multi-index length output
|
|
|
|
|
|
|
|
bool amsperm1_mindex_valid(int *mindex, int length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int I;
|
|
|
|
int I;
|
|
|
|
bool ret = 1;
|
|
|
|
bool ret = 1;
|
|
|
|
for(I=0;I<ndim;I++)
|
|
|
|
for(I=0;I<length;I++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(mindex[I]<0 || mindex[I]>=(ndim-I))
|
|
|
|
if(mindex[I]<0 || mindex[I]>=(length-I))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ret = 0;
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -77,19 +82,19 @@ namespace perm
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int mindex_to_index(int *mindex, int ndim)
|
|
|
|
int amsperm1_mindex_to_index(int *mindex, int length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int ret = -1;
|
|
|
|
int I;
|
|
|
|
int I;
|
|
|
|
int K;
|
|
|
|
int K;
|
|
|
|
if(mindex_valid(mindex,ndim))
|
|
|
|
if(amsperm1_mindex_valid(mindex,length))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
K = 1;
|
|
|
|
K = 1;
|
|
|
|
ret = 0;
|
|
|
|
ret = 0;
|
|
|
|
for(I=0;I<ndim;I++)
|
|
|
|
for(I=0;I<length;I++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ret = ret + mindex[I]*K;
|
|
|
|
ret = ret + mindex[I]*K;
|
|
|
|
K = K*(ndim-I);
|
|
|
|
K = K*(length-I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -101,20 +106,198 @@ namespace perm
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int mindex_to_perm(int *mindex, int *perm, int *wrk, int ndim)
|
|
|
|
//multi-index to permutation
|
|
|
|
|
|
|
|
//parameters:
|
|
|
|
|
|
|
|
// mindex[length] - input factoriadic multi-index
|
|
|
|
|
|
|
|
// perm[length] - output permutation
|
|
|
|
|
|
|
|
// wrk[length] - working memory buffer
|
|
|
|
|
|
|
|
// length - length of permutation
|
|
|
|
|
|
|
|
//return values:
|
|
|
|
|
|
|
|
// amsperm1_success - result should be a valid permutation
|
|
|
|
|
|
|
|
// amsperm1_failure - invalid multi-index supplied
|
|
|
|
|
|
|
|
int amsperm1_mindex_to_perm(int *mindex, int *perm, int *wrk, int length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int I,J,K,L;
|
|
|
|
|
|
|
|
int ret = amsperm1_failure;
|
|
|
|
|
|
|
|
if(!amsperm1_mindex_valid(mindex,length))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ret = amsperm1_failure;
|
|
|
|
|
|
|
|
for(I=0;I<length;I++) perm[I] = -1;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for(I=0;I<length;I++) wrk[I] = 0;
|
|
|
|
|
|
|
|
for(I=0;I<length;I++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
J = mindex[I];
|
|
|
|
|
|
|
|
L = 0;
|
|
|
|
|
|
|
|
for(K=0;K<length;K++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if(wrk[K]==0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
L = L + 1;
|
|
|
|
|
|
|
|
if(L==(J+1))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
perm[I] = K;
|
|
|
|
|
|
|
|
wrk[K] = 1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = amsperm1_success;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int perm_to_mindex(int *perm, int *mindex, int *wrk, int ndim)
|
|
|
|
//check validity of permutation
|
|
|
|
|
|
|
|
//parameters:
|
|
|
|
|
|
|
|
//int perm[length] - input permutation
|
|
|
|
|
|
|
|
//int wrk[length] - working buffer
|
|
|
|
|
|
|
|
//int length - permutation array length
|
|
|
|
|
|
|
|
//return values:
|
|
|
|
|
|
|
|
// 1 - is a valid permutation
|
|
|
|
|
|
|
|
// 0 - is not a valid permutation
|
|
|
|
|
|
|
|
bool amsperm1_perm_valid(int *perm, int *wrk, int length)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool ret = 1;
|
|
|
|
|
|
|
|
int I;
|
|
|
|
|
|
|
|
for(I=0;I<length;I++) wrk[I] = 0;
|
|
|
|
|
|
|
|
for(I=0;I<length;I++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if(perm[I]<0 || perm[I]>=length)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(wrk[perm[I]]==1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
wrk[perm[I]]=1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int amsperm1_perm_to_mindex(int *perm, int *mindex, int *wrk, int length)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int ret = amsperm1_failure;
|
|
|
|
|
|
|
|
int I,J,K,L;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!amsperm1_perm_valid(perm,wrk,length))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for(I=0;I<length;I++) mindex[I] = -1;
|
|
|
|
|
|
|
|
ret = amsperm1_failure;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(I=0;I<length;I++) wrk[I]=0;
|
|
|
|
|
|
|
|
for(I=0;I<length;I++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
J = perm[I];
|
|
|
|
|
|
|
|
L = 0;
|
|
|
|
|
|
|
|
for(K=0;K<=J;K++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if(wrk[K]==0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
L = L + 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
wrk[J] = 1;
|
|
|
|
|
|
|
|
mindex[I] = L-1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = amsperm1_success;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int amsperm1_index_to_perm(int index, int *perm, int *mindex, int *wrk, int length)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int ret = amsperm1_failure;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(index<0 || index>=amsperm1_factorial(length))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
amsperm1_index_to_mindex(index,mindex,length);
|
|
|
|
|
|
|
|
amsperm1_mindex_to_perm(mindex,perm,wrk,length);
|
|
|
|
|
|
|
|
ret = amsperm1_success;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int amsperm1_perm_to_index(int *perm, int *mindex, int *wrk, int length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if(!amsperm1_perm_valid(perm,wrk,length))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
amsperm1_perm_to_mindex(perm,mindex,wrk,length);
|
|
|
|
|
|
|
|
ret = amsperm1_mindex_to_index(mindex,length);
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void _intl_print_array(int *array, int length)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int I;
|
|
|
|
|
|
|
|
printf("{");
|
|
|
|
|
|
|
|
for(I=0;I<length-1;I++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("%d,",array[I]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("%d}",array[length-1]);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void amsperm1_test_basicperm1()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int I,J;
|
|
|
|
|
|
|
|
int length = 4;
|
|
|
|
|
|
|
|
int *perm1 = NULL;
|
|
|
|
|
|
|
|
int *perm2 = NULL;
|
|
|
|
|
|
|
|
int *mind1 = NULL;
|
|
|
|
|
|
|
|
int *mind2 = NULL;
|
|
|
|
|
|
|
|
int *wrk = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
perm1 = new(std::nothrow) int[length];
|
|
|
|
|
|
|
|
perm2 = new(std::nothrow) int[length];
|
|
|
|
|
|
|
|
mind1 = new(std::nothrow) int[length];
|
|
|
|
|
|
|
|
mind2 = new(std::nothrow) int[length];
|
|
|
|
|
|
|
|
wrk = new(std::nothrow) int[length];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("Tests of basic permutation and multi-index operations..\n");
|
|
|
|
|
|
|
|
for(I=-1;I<amsperm1_factorial(length)+1;I++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
amsperm1_index_to_mindex(I,mind1,length);
|
|
|
|
|
|
|
|
J = amsperm1_mindex_to_index(mind1,length);
|
|
|
|
|
|
|
|
amsperm1_mindex_to_perm(mind1,perm1,wrk,length);
|
|
|
|
|
|
|
|
amsperm1_perm_to_mindex(perm1,mind2,wrk,length);
|
|
|
|
|
|
|
|
printf("%d\t",I);
|
|
|
|
|
|
|
|
_intl_print_array(mind1,length); printf("\t");
|
|
|
|
|
|
|
|
_intl_print_array(perm1,length); printf("\t");
|
|
|
|
|
|
|
|
_intl_print_array(mind2,length); printf("\t");
|
|
|
|
|
|
|
|
printf("%d\n",J);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
delete[] perm1;
|
|
|
|
|
|
|
|
delete[] perm2;
|
|
|
|
|
|
|
|
delete[] mind1;
|
|
|
|
|
|
|
|
delete[] mind2;
|
|
|
|
|
|
|
|
delete[] wrk;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}; //end namespace perm
|
|
|
|
}; //end extern "C"
|
|
|
|
}; //end namespace ams
|
|
|
|
|