updates
This commit is contained in:
Binary file not shown.
Binary file not shown.
BIN
build_linux64/objstore/ipermutation.o
Normal file
BIN
build_linux64/objstore/ipermutation.o
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -5,6 +5,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <new>
|
||||
#include <initializer_list>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -89,6 +90,7 @@ public:
|
||||
ipermutation(const int _length);
|
||||
ipermutation(const int _index, const int _length);
|
||||
ipermutation(const int *parray, const int _length);
|
||||
ipermutation(std::initializer_list<int> q);
|
||||
~ipermutation();
|
||||
|
||||
ipermutation(const ipermutation& other);
|
||||
@ -98,6 +100,8 @@ public:
|
||||
ipermutation operator=(const ipermutation &other);
|
||||
int& operator[](const int ind);
|
||||
const int& operator[](const int ind) const;
|
||||
int& at(const int ind);
|
||||
const int& at(const int ind) const;
|
||||
|
||||
bool valid() const;
|
||||
bool operator==(const ipermutation other) const;
|
||||
@ -121,6 +125,8 @@ public:
|
||||
|
||||
void print(int style=0);
|
||||
|
||||
void recalc_from_perm();
|
||||
|
||||
};
|
||||
|
||||
ipermutation ipermutation_first(int _nlength);
|
||||
@ -128,18 +134,54 @@ ipermutation ipermutation_last(int _nlength);
|
||||
int levi_civita(const ipermutation p);
|
||||
|
||||
void test_ipermutation1();
|
||||
void test_ipermutation2();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// non-indexable permutation class
|
||||
// the same permutation logic, but for larger permutation sets
|
||||
// can't index, can't increment or decrement a sequence, but can still
|
||||
// compose, test validity, test levi_civita sign, apply to arrays, etc.
|
||||
//
|
||||
//maybe I *can* increment/decrement by converting to a multi-index (later, possibly not essential)
|
||||
class permutation
|
||||
{
|
||||
public:
|
||||
int length;
|
||||
int *data;
|
||||
|
||||
permutation();
|
||||
permutation(const int _length);
|
||||
permutation(const int *parray, const int _length);
|
||||
permutation(std::initializer_list<int> q);
|
||||
~permutation();
|
||||
|
||||
permutation(const permutation& other);
|
||||
|
||||
int resize(const int _nlength);
|
||||
|
||||
permutation operator=(const permutation &other);
|
||||
|
||||
bool valid() const;
|
||||
bool operator==(const permutation &other) const;
|
||||
|
||||
int& operator[](const int ind);
|
||||
const int& operator[](const int ind) const;
|
||||
int& at(const int ind);
|
||||
const int& at(const int ind) const;
|
||||
|
||||
|
||||
|
||||
static permutation first(int length);
|
||||
static permutation last(int length);
|
||||
|
||||
permutation operator*(const permutation &other) const; //composition
|
||||
permutation inverse() const;
|
||||
|
||||
int _intl_calculate_mindex(int *mindex, int *wrk);
|
||||
int levi_civita();
|
||||
};
|
||||
|
||||
|
||||
|
541
src/amscppperm1/ipermutation.cpp
Normal file
541
src/amscppperm1/ipermutation.cpp
Normal file
@ -0,0 +1,541 @@
|
||||
#include <amscppperm1/amscppperm1.hpp>
|
||||
|
||||
namespace ams
|
||||
{
|
||||
namespace perm
|
||||
{
|
||||
|
||||
ipermutation::ipermutation()
|
||||
{
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ipermutation::~ipermutation()
|
||||
{
|
||||
if(perm!=NULL) {delete[] perm; perm = NULL;}
|
||||
if(mind!=NULL) {delete[] mind; mind = NULL;}
|
||||
if(wrk!=NULL) {delete[] wrk; wrk = NULL;}
|
||||
length = 0;
|
||||
index = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const int _length)
|
||||
{
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
this->resize(_length);
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const int _index, const int _length)
|
||||
{
|
||||
int res = perm_failure;
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
if(_length>0)
|
||||
{
|
||||
res = this->resize(_length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
index = _index;
|
||||
amsperm1_index_to_mindex(index,mind,length);
|
||||
amsperm1_mindex_to_perm(mind,perm,wrk,length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const int *parray, const int _length)
|
||||
{
|
||||
int I;
|
||||
int res = perm_failure;
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
if(_length>0)
|
||||
{
|
||||
res = this->resize(_length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
for(I=0;I<length;I++) perm[I] = parray[I];
|
||||
amsperm1_perm_to_mindex(perm,mind,wrk,length);
|
||||
index = amsperm1_mindex_to_index(mind,length);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(std::initializer_list<int> q)
|
||||
{
|
||||
int I;
|
||||
//int elem;
|
||||
int res = perm_failure;
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
if(q.size()>0)
|
||||
{
|
||||
res = this->resize(q.size());
|
||||
if(res==perm_success)
|
||||
{
|
||||
//for(I=0;I<length;I++) perm[I] = q[I];
|
||||
//need to access things with annoying c++ish iterators
|
||||
I = 0;
|
||||
for(int elem : q)
|
||||
{
|
||||
perm[I] = elem;
|
||||
if(I<length) I++;
|
||||
}
|
||||
amsperm1_perm_to_mindex(perm,mind,wrk,length);
|
||||
index = amsperm1_mindex_to_index(mind,length);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int ipermutation::resize(const int _nlength)
|
||||
{
|
||||
int ret = perm_success;
|
||||
|
||||
int *newperm = NULL;
|
||||
int *newmind = NULL;
|
||||
int *newwrk = NULL;
|
||||
int newind;
|
||||
|
||||
int I;
|
||||
|
||||
if(_nlength<=0)
|
||||
{
|
||||
length = 0;
|
||||
index = -1;
|
||||
if(perm!=NULL) {delete[] perm; perm=NULL;}
|
||||
if(mind!=NULL) {delete[] mind; mind=NULL;}
|
||||
if(wrk!=NULL) {delete[] wrk; wrk=NULL;}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
newperm = new(std::nothrow) int[_nlength];
|
||||
newmind = new(std::nothrow) int[_nlength];
|
||||
newwrk = new(std::nothrow) int[_nlength];
|
||||
|
||||
if(newperm==NULL || newmind == NULL || newwrk == NULL)
|
||||
{
|
||||
if(newperm!=NULL) {delete[] newperm; newperm=NULL;}
|
||||
if(newmind!=NULL) {delete[] newmind; newmind=NULL;}
|
||||
if(newwrk!=NULL) {delete[] newwrk; newwrk=NULL;}
|
||||
|
||||
ret = perm_failure;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(I=0;I<length && I<_nlength; I++)
|
||||
{
|
||||
newmind[I] = mind[I];
|
||||
}
|
||||
for(I=length;I<_nlength;I++) newmind[I] = 0;
|
||||
|
||||
newind = amsperm1_mindex_to_index(newmind,_nlength);
|
||||
amsperm1_mindex_to_perm(newmind,newperm,newwrk,_nlength);
|
||||
|
||||
if(perm!=NULL) {delete[] perm; perm = NULL;}
|
||||
if(mind!=NULL) {delete[] mind; mind = NULL;}
|
||||
if(wrk!=NULL) {delete[] wrk; wrk = NULL;}
|
||||
length = 0;
|
||||
index = -1;
|
||||
|
||||
length = _nlength;
|
||||
index = newind;
|
||||
perm = newperm;
|
||||
mind = newmind;
|
||||
wrk = newwrk;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const ipermutation& other)
|
||||
{
|
||||
int res;
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
int I;
|
||||
|
||||
if(this!=&other)
|
||||
{
|
||||
res = this->resize(other.length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
this->perm[I] = other.perm[I];
|
||||
this->wrk[I] = other.wrk[I];
|
||||
this->mind[I] = other.mind[I];
|
||||
this->index = other.index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ipermutation ipermutation::operator=(const ipermutation &other)
|
||||
{
|
||||
int res;
|
||||
int I;
|
||||
if(this!=&other)
|
||||
{
|
||||
res = this->resize(other.length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
this->perm[I] = other.perm[I];
|
||||
this->wrk[I] = other.wrk[I];
|
||||
this->mind[I] = other.mind[I];
|
||||
this->index = other.index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int& ipermutation::operator[](const int ind)
|
||||
{
|
||||
return perm[ind];
|
||||
}
|
||||
|
||||
const int& ipermutation::operator[](const int ind) const
|
||||
{
|
||||
return perm[ind];
|
||||
}
|
||||
|
||||
int& ipermutation::at(const int ind)
|
||||
{
|
||||
return perm[ind];
|
||||
}
|
||||
|
||||
const int& ipermutation::at(const int ind) const
|
||||
{
|
||||
return perm[ind];
|
||||
}
|
||||
|
||||
int factorial(int n)
|
||||
{
|
||||
return amsperm1_factorial(n);
|
||||
}
|
||||
|
||||
bool ipermutation::valid() const
|
||||
{
|
||||
bool ret = 1;
|
||||
int *lmind = NULL;
|
||||
int *lwrk = NULL;
|
||||
int *lperm = NULL;
|
||||
|
||||
if(index<0 || index>=factorial(length))
|
||||
{
|
||||
ret = 0; return ret;
|
||||
}
|
||||
|
||||
//other tests - skip for speed?
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ipermutation::operator==(const ipermutation other) const
|
||||
{
|
||||
bool ret = 1;
|
||||
int I;
|
||||
|
||||
if(length!=other.length)
|
||||
{
|
||||
ret = 0; return ret;
|
||||
}
|
||||
if(index != other.index)
|
||||
{
|
||||
ret = 0; return ret;
|
||||
}
|
||||
|
||||
//additional tests (skip for speed?)
|
||||
for(I=0;I<length && I<other.length;I++)
|
||||
{
|
||||
if(perm[I]!=other.perm[I]) {ret = 0; break;}
|
||||
if(mind[I]!=other.mind[I]) {ret = 0; break;}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation ipermutation_first(int _nlength)
|
||||
{
|
||||
ipermutation ret = ipermutation(0,_nlength);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation ipermutation_last(int _nlength)
|
||||
{
|
||||
int f = factorial(_nlength);
|
||||
ipermutation ret = ipermutation(f-1,_nlength);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int levi_civita(const ipermutation p)
|
||||
{
|
||||
int ret = 0;
|
||||
bool v = p.valid();
|
||||
if(v)
|
||||
{
|
||||
ret = 2*(!(p.index%2))-1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//pre-increment operator
|
||||
ipermutation& ipermutation::operator++()
|
||||
{
|
||||
int I;
|
||||
if(valid())
|
||||
{
|
||||
if(index+1>=0 && index+1<factorial(length))
|
||||
{
|
||||
index = index + 1;
|
||||
amsperm1_index_to_mindex(index,mind,length);
|
||||
amsperm1_mindex_to_perm(mind,perm,wrk,length);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = -1;
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
perm[I] = -1;
|
||||
mind[I] = -1;
|
||||
wrk[I] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ipermutation& ipermutation::operator--()
|
||||
{
|
||||
int I;
|
||||
if(valid())
|
||||
{
|
||||
if(index-1>=0 && index-1<factorial(length))
|
||||
{
|
||||
index = index - 1;
|
||||
amsperm1_index_to_mindex(index,mind,length);
|
||||
amsperm1_mindex_to_perm(mind,perm,wrk,length);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = -1;
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
perm[I] = -1;
|
||||
mind[I] = -1;
|
||||
wrk[I] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//post-increment operators
|
||||
ipermutation ipermutation::operator++(int)
|
||||
{
|
||||
ipermutation ret = *this;
|
||||
//++ret;
|
||||
this->operator++();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation ipermutation::operator--(int)
|
||||
{
|
||||
ipermutation ret = *this;
|
||||
//--ret;
|
||||
this->operator--();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ipermutation::print(int style)
|
||||
{
|
||||
int I;
|
||||
if(style==0)
|
||||
{
|
||||
printf("{");
|
||||
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
|
||||
printf("%d}",perm[length-1]);
|
||||
}
|
||||
else if(style==1)
|
||||
{
|
||||
printf("%d:{",index);
|
||||
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
|
||||
printf("%d}",perm[length-1]);
|
||||
}
|
||||
else if(style==2)
|
||||
{
|
||||
printf("ipermutation[%d]:{",index);
|
||||
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
|
||||
printf("%d}",perm[length-1]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void test_ipermutation1()
|
||||
{
|
||||
ipermutation a = ipermutation(4);
|
||||
ipermutation *b = NULL;
|
||||
|
||||
b = new(std::nothrow) ipermutation(4);
|
||||
|
||||
a.print(); printf("\n");
|
||||
b->print(); printf("\n");
|
||||
a++;
|
||||
a.print(); printf("\n");
|
||||
++a; a.print(); printf("\n");
|
||||
a++;
|
||||
a++;
|
||||
a++;
|
||||
*b = a;
|
||||
b->print(2); printf("\n");
|
||||
b->resize(3);
|
||||
a.resize(5);
|
||||
a.print(); printf("\n");
|
||||
b->print(); printf("\n");
|
||||
int I;
|
||||
*b = ipermutation_first(3);
|
||||
for(I=0;I<8;I++)
|
||||
{
|
||||
|
||||
b->print(2); printf("\n");
|
||||
(*b)++;
|
||||
}
|
||||
|
||||
for(a=ipermutation_last(3);a.valid();a--)
|
||||
{
|
||||
a.print(2); printf("\n");
|
||||
}
|
||||
|
||||
delete(b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ipermutation::recalc_from_perm()
|
||||
{
|
||||
amsperm1_perm_to_mindex(perm,mind,wrk,length);
|
||||
index = amsperm1_mindex_to_index(mind,length);
|
||||
return;
|
||||
}
|
||||
|
||||
//compose permutations
|
||||
ipermutation ipermutation::operator*(const ipermutation b) const
|
||||
{
|
||||
int I,J;
|
||||
ipermutation ret = ipermutation(this->length);
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
J = this->perm[I];
|
||||
ret[I] = b[J];
|
||||
}
|
||||
ret.recalc_from_perm();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//invert permutation
|
||||
ipermutation ipermutation::inverse() const
|
||||
{
|
||||
int I,J;
|
||||
ipermutation ret = ipermutation(this->length);
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
J = this->perm[I];
|
||||
ret[J] = I;
|
||||
}
|
||||
|
||||
ret.recalc_from_perm();
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//returns first and last permutations of a given lengthension
|
||||
ipermutation ipermutation::first(int _nlength)
|
||||
{
|
||||
ipermutation ret = ipermutation(0,_nlength);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation ipermutation::last(int _nlength)
|
||||
{
|
||||
int f = factorial(_nlength);
|
||||
ipermutation ret = ipermutation(f-1,_nlength);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ipermutation::levi_civita() const
|
||||
{
|
||||
int ret = 0;
|
||||
if(valid())
|
||||
{
|
||||
ret = 2*(!(index%2))-1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void test_ipermutation2()
|
||||
{
|
||||
ipermutation a,b,c;
|
||||
int q1[] = {2,0,1,3};
|
||||
int q2[] = {3,0,2,1};
|
||||
|
||||
a = ipermutation(q1,4);
|
||||
b = ipermutation({3,0,2,1});
|
||||
c = a*b;
|
||||
a.print(); printf("\n");
|
||||
b.print(); printf("\n");
|
||||
c.print(); printf("\n");
|
||||
c = b*a;
|
||||
c.print(); printf("\n");
|
||||
|
||||
b = {3,0,2,1};
|
||||
b = a.inverse();
|
||||
c = b*a;
|
||||
|
||||
a.print(); printf("\n");
|
||||
b.print(); printf("\n");
|
||||
c.print(); printf("\n");
|
||||
c = a*b;
|
||||
c.print(); printf("\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}; //end namespace perm
|
||||
}; //end namespace ams
|
@ -5,445 +5,356 @@ namespace ams
|
||||
namespace perm
|
||||
{
|
||||
|
||||
ipermutation::ipermutation()
|
||||
permutation::permutation()
|
||||
{
|
||||
length = 0;
|
||||
data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
permutation::~permutation()
|
||||
{
|
||||
length = 0;
|
||||
if(data!=NULL) {delete[] data; data=NULL;}
|
||||
}
|
||||
|
||||
permutation::permutation(const permutation& other)
|
||||
{
|
||||
int res;
|
||||
int I;
|
||||
length = 0;
|
||||
data = NULL;
|
||||
|
||||
if(this!=&other)
|
||||
{
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ipermutation::~ipermutation()
|
||||
{
|
||||
if(perm!=NULL) {delete[] perm; perm = NULL;}
|
||||
if(mind!=NULL) {delete[] mind; mind = NULL;}
|
||||
if(wrk!=NULL) {delete[] wrk; wrk = NULL;}
|
||||
length = 0;
|
||||
index = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const int _length)
|
||||
{
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
this->resize(_length);
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const int _index, const int _length)
|
||||
{
|
||||
int res = perm_failure;
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
if(_length>0)
|
||||
res = this->resize(other.length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
res = this->resize(_length);
|
||||
if(res==perm_success)
|
||||
for(I=0;I<length&&I<other.length;I++)
|
||||
{
|
||||
index = _index;
|
||||
amsperm1_index_to_mindex(index,mind,length);
|
||||
amsperm1_mindex_to_perm(mind,perm,wrk,length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const int *parray, const int _length)
|
||||
{
|
||||
int I;
|
||||
int res = perm_failure;
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
if(_length>0)
|
||||
{
|
||||
res = this->resize(_length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
for(I=0;I<length;I++) perm[I] = parray[I];
|
||||
amsperm1_perm_to_mindex(perm,mind,wrk,length);
|
||||
index = amsperm1_mindex_to_index(mind,length);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int ipermutation::resize(const int _nlength)
|
||||
{
|
||||
int ret = perm_success;
|
||||
|
||||
int *newperm = NULL;
|
||||
int *newmind = NULL;
|
||||
int *newwrk = NULL;
|
||||
int newind;
|
||||
|
||||
int I;
|
||||
|
||||
if(_nlength<=0)
|
||||
{
|
||||
length = 0;
|
||||
index = -1;
|
||||
if(perm!=NULL) {delete[] perm; perm=NULL;}
|
||||
if(mind!=NULL) {delete[] mind; mind=NULL;}
|
||||
if(wrk!=NULL) {delete[] wrk; wrk=NULL;}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
newperm = new(std::nothrow) int[_nlength];
|
||||
newmind = new(std::nothrow) int[_nlength];
|
||||
newwrk = new(std::nothrow) int[_nlength];
|
||||
|
||||
if(newperm==NULL || newmind == NULL || newwrk == NULL)
|
||||
{
|
||||
if(newperm!=NULL) {delete[] newperm; newperm=NULL;}
|
||||
if(newmind!=NULL) {delete[] newmind; newmind=NULL;}
|
||||
if(newwrk!=NULL) {delete[] newwrk; newwrk=NULL;}
|
||||
|
||||
ret = perm_failure;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(I=0;I<length && I<_nlength; I++)
|
||||
{
|
||||
newmind[I] = mind[I];
|
||||
}
|
||||
for(I=length;I<_nlength;I++) newmind[I] = 0;
|
||||
|
||||
newind = amsperm1_mindex_to_index(newmind,_nlength);
|
||||
amsperm1_mindex_to_perm(newmind,newperm,newwrk,_nlength);
|
||||
|
||||
if(perm!=NULL) {delete[] perm; perm = NULL;}
|
||||
if(mind!=NULL) {delete[] mind; mind = NULL;}
|
||||
if(wrk!=NULL) {delete[] wrk; wrk = NULL;}
|
||||
length = 0;
|
||||
index = -1;
|
||||
|
||||
length = _nlength;
|
||||
index = newind;
|
||||
perm = newperm;
|
||||
mind = newmind;
|
||||
wrk = newwrk;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation::ipermutation(const ipermutation& other)
|
||||
{
|
||||
int res;
|
||||
length = 0;
|
||||
perm = NULL;
|
||||
index = -1;
|
||||
mind = NULL;
|
||||
wrk = NULL;
|
||||
|
||||
int I;
|
||||
|
||||
if(this!=&other)
|
||||
{
|
||||
res = this->resize(other.length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
this->perm[I] = other.perm[I];
|
||||
this->wrk[I] = other.wrk[I];
|
||||
this->mind[I] = other.mind[I];
|
||||
this->index = other.index;
|
||||
}
|
||||
this->data[I] = other.data[I];
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ipermutation ipermutation::operator=(const ipermutation &other)
|
||||
permutation::permutation(const int _length)
|
||||
{
|
||||
int res;
|
||||
int I;
|
||||
length = 0;
|
||||
data = NULL;
|
||||
|
||||
res = this->resize(_length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
int res;
|
||||
int I;
|
||||
if(this!=&other)
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
res = this->resize(other.length);
|
||||
if(res==perm_success)
|
||||
this->data[I] = I;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
permutation::permutation(const int *parray, const int _length)
|
||||
{
|
||||
int res;
|
||||
int I;
|
||||
length = 0;
|
||||
data = NULL;
|
||||
|
||||
res = this->resize(_length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
this->data[I] = parray[I];
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
permutation::permutation(std::initializer_list<int> q)
|
||||
{
|
||||
int res;
|
||||
int I;
|
||||
length = 0;
|
||||
data = NULL;
|
||||
|
||||
res = this->resize(q.size());
|
||||
if(res==perm_success)
|
||||
{
|
||||
I = 0;
|
||||
for(int elem : q)
|
||||
{
|
||||
data[I] = elem;
|
||||
if(I<length) I++;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
permutation permutation::operator=(const permutation& other)
|
||||
{
|
||||
int res;
|
||||
int I;
|
||||
|
||||
if(this!=&other)
|
||||
{
|
||||
res = this->resize(other.length);
|
||||
if(res==perm_success)
|
||||
{
|
||||
for(I=0;I<length&&I<other.length;I++)
|
||||
{
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
this->perm[I] = other.perm[I];
|
||||
this->wrk[I] = other.wrk[I];
|
||||
this->mind[I] = other.mind[I];
|
||||
this->index = other.index;
|
||||
}
|
||||
this->data[I] = other.data[I];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int& ipermutation::operator[](const int ind)
|
||||
int permutation::resize(const int _nlength)
|
||||
{
|
||||
int ret = perm_success;
|
||||
int I;
|
||||
|
||||
int *newdata = NULL;
|
||||
|
||||
if(_nlength<=0)
|
||||
{
|
||||
return perm[ind];
|
||||
}
|
||||
|
||||
const int& ipermutation::operator[](const int ind) const
|
||||
{
|
||||
return perm[ind];
|
||||
}
|
||||
|
||||
int factorial(int n)
|
||||
{
|
||||
return amsperm1_factorial(n);
|
||||
}
|
||||
|
||||
bool ipermutation::valid() const
|
||||
{
|
||||
bool ret = 1;
|
||||
int *lmind = NULL;
|
||||
int *lwrk = NULL;
|
||||
int *lperm = NULL;
|
||||
|
||||
if(index<0 || index>=factorial(length))
|
||||
{
|
||||
ret = 0; return ret;
|
||||
}
|
||||
|
||||
//other tests - skip for speed?
|
||||
|
||||
length = 0;
|
||||
if(data!=NULL) {delete[] data; data=NULL;}
|
||||
ret = perm_failure;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ipermutation::operator==(const ipermutation other) const
|
||||
newdata = new(std::nothrow) int[_nlength];
|
||||
if(newdata==NULL)
|
||||
{
|
||||
bool ret = 1;
|
||||
int I;
|
||||
|
||||
if(length!=other.length)
|
||||
{
|
||||
ret = 0; return ret;
|
||||
}
|
||||
if(index != other.index)
|
||||
{
|
||||
ret = 0; return ret;
|
||||
}
|
||||
|
||||
//additional tests (skip for speed?)
|
||||
for(I=0;I<length && I<other.length;I++)
|
||||
{
|
||||
if(perm[I]!=other.perm[I]) {ret = 0; break;}
|
||||
if(mind[I]!=other.mind[I]) {ret = 0; break;}
|
||||
}
|
||||
|
||||
ret = perm_failure;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation ipermutation_first(int _nlength)
|
||||
for(I=0;I<length && I<_nlength;I++)
|
||||
{
|
||||
ipermutation ret = ipermutation(0,_nlength);
|
||||
return ret;
|
||||
newdata[I] = data[I];
|
||||
}
|
||||
for(I=length;I<_nlength;I++)
|
||||
{
|
||||
newdata[I] = 0; //will have to fill in for it to be a valid permutation
|
||||
}
|
||||
|
||||
ipermutation ipermutation_last(int _nlength)
|
||||
if(data!=NULL) {delete[] data; data=NULL;}
|
||||
data = newdata;
|
||||
length = _nlength;
|
||||
ret = perm_success;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool permutation::valid() const
|
||||
{
|
||||
bool ret = 1;
|
||||
int *wrk = NULL;
|
||||
int I,J;
|
||||
|
||||
wrk = new(std::nothrow) int[length];
|
||||
if(wrk==NULL)
|
||||
{
|
||||
int f = factorial(_nlength);
|
||||
ipermutation ret = ipermutation(f-1,_nlength);
|
||||
return ret;
|
||||
ret = 0; //wrk buffer allocation failed
|
||||
return ret;
|
||||
}
|
||||
|
||||
int levi_civita(const ipermutation p)
|
||||
for(I=0;I<length;I++) wrk[I] = 0;
|
||||
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
int ret = 0;
|
||||
bool v = p.valid();
|
||||
if(v)
|
||||
J = data[I];
|
||||
if(J<0 || J>=length)
|
||||
{
|
||||
ret = 2*(!(p.index%2))-1;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if(wrk[J]==1)
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
wrk[J] = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//pre-increment operator
|
||||
ipermutation& ipermutation::operator++()
|
||||
|
||||
if(wrk!=NULL) {delete[] wrk; wrk=NULL;}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool permutation::operator==(const permutation &other) const
|
||||
{
|
||||
int I;
|
||||
bool ret = 1;
|
||||
if(this->length != other.length)
|
||||
{
|
||||
int I;
|
||||
if(valid())
|
||||
ret = 0; return ret;
|
||||
}
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
if(this->data[I]!=other.data[I])
|
||||
{
|
||||
if(index+1>=0 && index+1<factorial(length))
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int permutation::_intl_calculate_mindex(int *mindex, int *wrk)
|
||||
{
|
||||
int ret = perm_success;
|
||||
//if(!valid()) //<--- a redundant test given that this is only called from levi_civita
|
||||
//{
|
||||
// ret = perm_failure;
|
||||
// return ret;
|
||||
//}
|
||||
|
||||
int I,J,K,L;
|
||||
|
||||
for(I=0;I<length;I++) wrk[I]=0;
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
J = data[I];
|
||||
L = 0;
|
||||
for(K=0;K<=J;K++)
|
||||
{
|
||||
if(wrk[K]==0)
|
||||
{
|
||||
index = index + 1;
|
||||
amsperm1_index_to_mindex(index,mind,length);
|
||||
amsperm1_mindex_to_perm(mind,perm,wrk,length);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = -1;
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
perm[I] = -1;
|
||||
mind[I] = -1;
|
||||
wrk[I] = 0;
|
||||
}
|
||||
L = L + 1;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
wrk[J] = 1;
|
||||
mindex[I] = L-1;
|
||||
}
|
||||
ret = amsperm1_success;
|
||||
|
||||
ipermutation& ipermutation::operator--()
|
||||
{
|
||||
int I;
|
||||
if(valid())
|
||||
{
|
||||
if(index-1>=0 && index-1<factorial(length))
|
||||
{
|
||||
index = index - 1;
|
||||
amsperm1_index_to_mindex(index,mind,length);
|
||||
amsperm1_mindex_to_perm(mind,perm,wrk,length);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = -1;
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
perm[I] = -1;
|
||||
mind[I] = -1;
|
||||
wrk[I] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//post-increment operators
|
||||
ipermutation ipermutation::operator++(int)
|
||||
int permutation::levi_civita()
|
||||
{
|
||||
int ret = 0;
|
||||
int *mindex = NULL;
|
||||
int *wrk = NULL;
|
||||
|
||||
int Q;
|
||||
|
||||
if(!valid())
|
||||
{
|
||||
ipermutation ret = *this;
|
||||
//++ret;
|
||||
this->operator++();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation ipermutation::operator--(int)
|
||||
if(length<=0)
|
||||
{
|
||||
ipermutation ret = *this;
|
||||
//--ret;
|
||||
this->operator--();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ipermutation::print(int style)
|
||||
mindex = new(std::nothrow) int[length];
|
||||
wrk = new(std::nothrow) int[length];
|
||||
|
||||
this->_intl_calculate_mindex(mindex,wrk);
|
||||
|
||||
if(length==1)
|
||||
{
|
||||
int I;
|
||||
if(style==0)
|
||||
{
|
||||
printf("{");
|
||||
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
|
||||
printf("%d}",perm[length-1]);
|
||||
}
|
||||
else if(style==1)
|
||||
{
|
||||
printf("%d:{",index);
|
||||
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
|
||||
printf("%d}",perm[length-1]);
|
||||
}
|
||||
else if(style==2)
|
||||
{
|
||||
printf("ipermutation[%d]:{",index);
|
||||
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
|
||||
printf("%d}",perm[length-1]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void test_ipermutation1()
|
||||
{
|
||||
ipermutation a = ipermutation(4);
|
||||
ipermutation *b = NULL;
|
||||
|
||||
b = new(std::nothrow) ipermutation(4);
|
||||
|
||||
a.print(); printf("\n");
|
||||
b->print(); printf("\n");
|
||||
a++;
|
||||
a.print(); printf("\n");
|
||||
++a; a.print(); printf("\n");
|
||||
a++;
|
||||
a++;
|
||||
a++;
|
||||
*b = a;
|
||||
b->print(2); printf("\n");
|
||||
b->resize(3);
|
||||
a.resize(5);
|
||||
a.print(); printf("\n");
|
||||
b->print(); printf("\n");
|
||||
int I;
|
||||
*b = ipermutation_first(3);
|
||||
for(I=0;I<8;I++)
|
||||
{
|
||||
|
||||
b->print(2); printf("\n");
|
||||
(*b)++;
|
||||
}
|
||||
|
||||
for(a=ipermutation_last(3);a.valid();a--)
|
||||
{
|
||||
a.print(2); printf("\n");
|
||||
}
|
||||
|
||||
delete(b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//compose permutations
|
||||
ipermutation ipermutation::operator*(const ipermutation b) const
|
||||
{
|
||||
ipermutation ret = ipermutation(this->length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//invert permutation
|
||||
ipermutation ipermutation::inverse() const
|
||||
{
|
||||
ipermutation ret = ipermutation(this->length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//returns first and last permutations of a given lengthension
|
||||
ipermutation ipermutation::first(int _nlength)
|
||||
{
|
||||
ipermutation ret = ipermutation(0,_nlength);
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipermutation ipermutation::last(int _nlength)
|
||||
Q = (mindex[0] + mindex[1]*length)%2;
|
||||
|
||||
ret = 2*(!Q)-1;
|
||||
|
||||
|
||||
if(mindex!=NULL) {delete[] mindex; mindex=NULL;}
|
||||
if(wrk!=NULL) {delete[] wrk; wrk=NULL;}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
permutation permutation::first(int length)
|
||||
{
|
||||
permutation ret = permutation(length);
|
||||
int I;
|
||||
for(I=0;I<ret.length;I++)
|
||||
{
|
||||
int f = factorial(_nlength);
|
||||
ipermutation ret = ipermutation(f-1,_nlength);
|
||||
return ret;
|
||||
ret.data[I] = I;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
permutation permutation::last(int length)
|
||||
{
|
||||
permutation ret = permutation(length);
|
||||
int I;
|
||||
for(I=0;I<ret.length;I++)
|
||||
{
|
||||
ret.data[I] = ret.length-I-1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
permutation permutation::operator*(const permutation &other) const
|
||||
{
|
||||
int I,J;
|
||||
permutation ret = permutation(this->length);
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
J = this->data[I];
|
||||
ret[I] = other[J];
|
||||
}
|
||||
|
||||
int ipermutation::levi_civita() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
permutation permutation::inverse() const
|
||||
{
|
||||
int I,J;
|
||||
permutation ret = permutation(this->length);
|
||||
for(I=0;I<length;I++)
|
||||
{
|
||||
int ret = 0;
|
||||
if(valid())
|
||||
{
|
||||
ret = 2*(!(index%2))-1;
|
||||
}
|
||||
return ret;
|
||||
J = this->data[I];
|
||||
ret[J] = I;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int& permutation::operator[](const int ind)
|
||||
{
|
||||
return data[ind];
|
||||
}
|
||||
|
||||
const int& permutation::operator[](const int ind) const
|
||||
{
|
||||
return data[ind];
|
||||
}
|
||||
|
||||
int& permutation::at(const int ind)
|
||||
{
|
||||
return data[ind];
|
||||
}
|
||||
|
||||
const int& permutation::at(const int ind) const
|
||||
{
|
||||
return data[ind];
|
||||
}
|
||||
|
||||
}; //end namespace perm
|
||||
}; //end namespace ams
|
@ -6,5 +6,6 @@ int main(int argc, char* argv[])
|
||||
printf("ams c++ permutation library tests.\n");
|
||||
//amsperm1_test_basicperm1();
|
||||
//ams::perm::test_ipermutation1();
|
||||
ams::perm::test_ipermutation2();
|
||||
return ret;
|
||||
}
|
Reference in New Issue
Block a user