diff --git a/permutation.cc b/permutation.cc index 4978202..4798ab7 100644 --- a/permutation.cc +++ b/permutation.cc @@ -94,9 +94,36 @@ for(T i=1; i<=this->size(); ++i) q[i]=(*this)[this->size()-i+1]; return q; } +template +NRPerm NRPerm::operator+(const NRPerm &q) const +{ +#ifdef DEBUG + if(!this->is_valid() || !q.is_valid()) laerror("concatenation of invalid permutation"); +#endif + +NRPerm r(size()+q.size()); +for(int i=1; i<=size(); ++i) r[i]=(*this)[i]; +for(int i=1; i<=q.size(); ++i) r[size()+i]=size()+q[i]; +return r; +} template -NRPerm NRPerm::operator*(const NRPerm q) const +NRPerm NRPerm::operator-(const NRPerm &q) const +{ +#ifdef DEBUG + if(!this->is_valid() || !q.is_valid()) laerror("concatenation of invalid permutation"); +#endif + +NRPerm r(size()+q.size()); +for(int i=1; i<=q.size(); ++i) r[i]=size()+q[i]; +for(int i=1; i<=size(); ++i) r[q.size()+i]=(*this)[i]; +return r; +} + + + +template +NRPerm NRPerm::operator*(const NRPerm &q) const { #ifdef DEBUG if(!this->is_valid() || !q.is_valid()) laerror("multiplication of invalid permutation"); @@ -111,7 +138,7 @@ return r; } template -NRPerm NRPerm::conjugate_by(const NRPerm q) const +NRPerm NRPerm::conjugate_by(const NRPerm &q) const { #ifdef DEBUG if(!this->is_valid() || !q.is_valid()) laerror("multiplication of invalid permutation"); @@ -126,6 +153,16 @@ return r; } +template +CyclePerm CyclePerm::conjugate_by(const CyclePerm &q) const +{ +#ifdef DEBUG + if(!this->is_valid() || !q.is_valid()) laerror("multiplication of invalid permutation"); +#endif +return q.inverse()*((*this)*q); +} + + template int NRPerm::parity() const { @@ -740,7 +777,7 @@ return r; //multiplication via NRPerm - could there be a more efficient direct algorithm? template -CyclePerm CyclePerm::operator*(const CyclePerm q) const +CyclePerm CyclePerm::operator*(const CyclePerm &q) const { int m=this->max(); int mm=q.max(); diff --git a/permutation.h b/permutation.h index ab76be9..9a9ca69 100644 --- a/permutation.h +++ b/permutation.h @@ -50,14 +50,17 @@ public: explicit NRPerm(const CyclePerm &rhs, const int n=0); //specific operations + int size() const {return NRVec_from1::size();}; void identity(); bool is_valid() const; //is it really a permutation bool is_identity() const; NRPerm inverse() const; NRPerm reverse() const; //backward order - NRPerm operator*(const NRPerm q) const; //q is rhs and applied first, this applied second + NRPerm operator+(const NRPerm &rhs) const; //concatenate the permutations this,rhs, renumbering rhs (not commutative) + NRPerm operator-(const NRPerm &rhs) const; //concatenate the permutations rhs,this, renumbering rhs (not commutative) + NRPerm operator*(const NRPerm &q) const; //q is rhs and applied first, this applied second NRPerm operator*(const CyclePerm &r) const; - NRPerm conjugate_by(const NRPerm q) const; //q^-1 p q + NRPerm conjugate_by(const NRPerm &q) const; //q^-1 p q int parity() const; //returns +/- 1 void randomize(void); //uniformly random by Fisher-Yates shuffle bool next(); //generate next permutation in lex order @@ -94,8 +97,9 @@ public: T max() const {T m=0; for(int i=1; i<=this->size(); ++i) {T mm= (*this)[i].max(); if(mm>m) m=mm;} return m;} CompressedPartition cycles(const T n) const; void readfrom(const std::string &line); - CyclePerm operator*(const CyclePerm q) const; //q is rhs and applied first, this applied second + CyclePerm operator*(const CyclePerm &q) const; //q is rhs and applied first, this applied second NRPerm operator*(const NRPerm &r) const; + CyclePerm conjugate_by(const CyclePerm &q) const; //q^-1 p q PERM_RANK_TYPE order() const; //lcm of cycle lengths bool operator==(const CyclePerm &rhs) const {return NRPerm(*this) == NRPerm(rhs);}; //cycle representation is not unique, cannot inherit operator== from NRVec void simplify(bool keep1=false); //remove cycles of size 0 or 1