diff --git a/build_linux64/libamscppperm1.linux64.a b/build_linux64/libamscppperm1.linux64.a index 8a75a84..f86ff79 100644 Binary files a/build_linux64/libamscppperm1.linux64.a and b/build_linux64/libamscppperm1.linux64.a differ diff --git a/build_linux64/objstore/amscppperm1.o b/build_linux64/objstore/amscppperm1.o index 8b837b5..68c7724 100644 Binary files a/build_linux64/objstore/amscppperm1.o and b/build_linux64/objstore/amscppperm1.o differ diff --git a/build_linux64/objstore/ipermutation.o b/build_linux64/objstore/ipermutation.o new file mode 100644 index 0000000..b57dad2 Binary files /dev/null and b/build_linux64/objstore/ipermutation.o differ diff --git a/build_linux64/objstore/permutation.o b/build_linux64/objstore/permutation.o index 34f5999..587815f 100644 Binary files a/build_linux64/objstore/permutation.o and b/build_linux64/objstore/permutation.o differ diff --git a/build_linux64/tests b/build_linux64/tests index e2b682a..f0651b2 100644 Binary files a/build_linux64/tests and b/build_linux64/tests differ diff --git a/include/amscppperm1/amscppperm1.hpp b/include/amscppperm1/amscppperm1.hpp index 0015203..2e76cfb 100644 --- a/include/amscppperm1/amscppperm1.hpp +++ b/include/amscppperm1/amscppperm1.hpp @@ -5,6 +5,7 @@ #include #include #include +#include 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 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 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(); }; diff --git a/src/amscppperm1/ipermutation.cpp b/src/amscppperm1/ipermutation.cpp new file mode 100644 index 0000000..81eaaf7 --- /dev/null +++ b/src/amscppperm1/ipermutation.cpp @@ -0,0 +1,541 @@ +#include + +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 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;Iresize(other.length); + if(res==perm_success) + { + for(I=0;Iperm[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;Iperm[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=0 && index+1=0 && index-1operator++(); + 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;Iprint(); 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;Iperm[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;Iperm[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 \ No newline at end of file diff --git a/src/amscppperm1/permutation.cpp b/src/amscppperm1/permutation.cpp index 5970497..aa9efff 100644 --- a/src/amscppperm1/permutation.cpp +++ b/src/amscppperm1/permutation.cpp @@ -5,445 +5,356 @@ 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; - } +permutation::permutation() +{ + length = 0; + data = NULL; + return; +} - ipermutation::ipermutation(const int _length) - { - length = 0; - perm = NULL; - index = -1; - mind = NULL; - wrk = NULL; +permutation::~permutation() +{ + length = 0; + if(data!=NULL) {delete[] data; data=NULL;} +} - this->resize(_length); - } +permutation::permutation(const permutation& other) +{ + int res; + int I; + length = 0; + data = NULL; - ipermutation::ipermutation(const int _index, const int _length) + if(this!=&other) { - 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;Idata[I] = other.data[I]; } - } + } } + return; +} - ipermutation::ipermutation(const int *parray, const int _length) - { - int I; - int res = perm_failure; - length = 0; - perm = NULL; - index = -1; - mind = NULL; - wrk = NULL; +permutation::permutation(const int _length) +{ + int res; + int I; + length = 0; + data = NULL; - if(_length>0) + res = this->resize(_length); + if(res==perm_success) + { + for(I=0;Iresize(_length); - if(res==perm_success) - { - for(I=0;Idata[I] = I; + } } - int ipermutation::resize(const int _nlength) - { - int ret = perm_success; - - int *newperm = NULL; - int *newmind = NULL; - int *newwrk = NULL; - int newind; + return; +} - int I; +permutation::permutation(const int *parray, const int _length) +{ + int res; + int I; + length = 0; + data = NULL; - if(_nlength<=0) + res = this->resize(_length); + if(res==perm_success) + { + for(I=0;Idata[I] = parray[I]; } + } - 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;} + return; +} - ret = perm_failure; - return ret; - } +permutation::permutation(std::initializer_list q) +{ + int res; + int I; + length = 0; + data = NULL; - for(I=0;Iresize(q.size()); + if(res==perm_success) + { + I = 0; + for(int elem : q) { - newmind[I] = mind[I]; + data[I] = elem; + if(Iresize(other.length); + if(res==perm_success) { - res = this->resize(other.length); - if(res==perm_success) + for(I=0;Iperm[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; +} - 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;Iperm[I] = other.perm[I]; - this->wrk[I] = other.wrk[I]; - this->mind[I] = other.mind[I]; - this->index = other.index; - } - } - } +int permutation::resize(const int _nlength) +{ + int ret = perm_success; + int I; - return *this; - } + int *newdata = NULL; - int& ipermutation::operator[](const int ind) + if(_nlength<=0) { - return perm[ind]; + length = 0; + if(data!=NULL) {delete[] data; data=NULL;} + ret = perm_failure; + return ret; } - const int& ipermutation::operator[](const int ind) const + newdata = new(std::nothrow) int[_nlength]; + if(newdata==NULL) { - return perm[ind]; + ret = perm_failure; + return ret; } - int factorial(int n) + for(I=0;I=factorial(length)) - { - ret = 0; return ret; - } + if(data!=NULL) {delete[] data; data=NULL;} + data = newdata; + length = _nlength; + ret = perm_success; - //other tests - skip for speed? + return ret; +} - return ret; +bool permutation::valid() const +{ + bool ret = 1; + int *wrk = NULL; + int I,J; + + wrk = new(std::nothrow) int[length]; + if(wrk==NULL) + { + ret = 0; //wrk buffer allocation failed + return ret; } - bool ipermutation::operator==(const ipermutation other) const + for(I=0;I=length) { - ret = 0; return ret; + ret = 0; + break; } - if(index != other.index) + if(wrk[J]==1) { - ret = 0; return ret; + ret = 0; + break; } - - //additional tests (skip for speed?) - for(I=0;Ilength != other.length) { - int ret = 0; - bool v = p.valid(); - if(v) - { - ret = 2*(!(p.index%2))-1; - } - return ret; + ret = 0; return ret; } - - //pre-increment operator - ipermutation& ipermutation::operator++() + for(I=0;Idata[I]!=other.data[I]) { - if(index+1>=0 && index+1=0 && index-1operator++(); 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;Iprint(); 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)++; - } + Q = (mindex[0] + mindex[1]*length)%2; - for(a=ipermutation_last(3);a.valid();a--) - { - a.print(2); printf("\n"); - } + ret = 2*(!Q)-1; - delete(b); - return; - } + if(mindex!=NULL) {delete[] mindex; mindex=NULL;} + if(wrk!=NULL) {delete[] wrk; wrk=NULL;} - //compose permutations - ipermutation ipermutation::operator*(const ipermutation b) const - { - ipermutation ret = ipermutation(this->length); + return ret; +} - return ret; - } - - //invert permutation - ipermutation ipermutation::inverse() const +permutation permutation::first(int length) +{ + permutation ret = permutation(length); + int I; + for(I=0;Ilength); - - return ret; - } + ret.data[I] = I; + } + return ret; +} - //returns first and last permutations of a given lengthension - ipermutation ipermutation::first(int _nlength) +permutation permutation::last(int length) +{ + permutation ret = permutation(length); + int I; + for(I=0;Ilength); + for(I=0;Idata[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;Idata[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 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 2f63c79..1390d57 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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; } \ No newline at end of file