/** * This file is part of Gomu. * * Copyright 2016 by Jean Fromentin * * Gomu is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Gomu is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Gomu. If not, see . */ #ifndef PERMUTATIONS_HPP #define PERMUTATIONS_HPP #include #include #include #include "smmintrin.h" #include "coxeter.hpp" using namespace std; typedef int8_t int8; typedef uint32_t uint32; typedef uint64_t uint64; typedef int64_t int64; static const __m128i id128=_mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); static const __m128i shmask=_mm_setr_epi8(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15); void swap(int8& a,int8& b); uint64 fact(uint64 n); template class Permutation{ public: uint64 n; static Permutation Ptemp; union{ __m128i m128; int8 win[16]; }; Permutation(uint64=0); void setInverse(Permutation&) const; const Permutation& getInverse() const; uint64 descentInteger() const; int cmp(const Permutation&) const; string display() const; template friend ostream& operator<<(ostream&,const Permutation&); }; template class PermutationEnumerator; template<> class PermutationEnumerator{ protected: Permutation sigma; uint64 n; public: PermutationEnumerator(uint64); void reset(); bool next(); size_t size() const; const Permutation& get() const; int cmp(const PermutationEnumerator& E) const; string display() const; friend ostream& operator<<(ostream&,const PermutationEnumerator&); }; template<> class PermutationEnumerator:public PermutationEnumerator{ protected: Permutation sigmaB; uint64 sign; public: PermutationEnumerator(uint64); void reset(); bool next(); size_t size() const; const Permutation& get() const; int cmp(const PermutationEnumerator& E) const; string display() const; friend ostream& operator<<(ostream&,const PermutationEnumerator&); }; template<> class PermutationEnumerator:public PermutationEnumerator{ protected: Permutation sigmaD; uint64 sign; public: PermutationEnumerator(uint64); void reset(); bool next(); size_t size() const; const Permutation& get() const; int cmp(const PermutationEnumerator& E) const; string display() const; friend ostream& operator<<(ostream&,const PermutationEnumerator&); }; typedef Permutation PermutationA; typedef Permutation PermutationB; typedef Permutation PermutationD; inline void swap(int8& a,int8& b){ int8 t=a; a=b; b=t; } inline uint64 fact(uint64 n){ if(n<2) return 1; return n*fact(n-1); } //*************** //* Permutation * //*************** template Permutation Permutation::Ptemp; template inline Permutation::Permutation(uint64 r):n(r),m128(id128){ } template void Permutation::setInverse(Permutation& inv) const{ inv.n=n; for(uint64 i=1;i<=n;++i){ int8 v=win[i]; if(v>0) inv.win[v]=i; else inv.win[-v]=-i; } } template const Permutation& Permutation::getInverse() const{ setInverse(Ptemp); return Ptemp; } template<> inline uint64 Permutation::descentInteger() const{ __m128i temp=_mm_shuffle_epi8(m128,shmask); temp=_mm_cmpgt_epi8(m128,temp); return _mm_movemask_epi8(temp); } template<> inline uint64 Permutation::descentInteger() const{ __m128i temp=_mm_shuffle_epi8(m128,shmask); temp=_mm_cmpgt_epi8(m128,temp); return _mm_movemask_epi8(temp); } template<> inline uint64 Permutation::descentInteger() const{ __m128i temp=_mm_shuffle_epi8(m128,shmask); temp=_mm_cmpgt_epi8(m128,temp); uint64 res=_mm_movemask_epi8(temp); if(win[1]+win[2]<0) res|=1L; else res&=(~1L); return res; } template int Permutation::cmp(const Permutation& P) const{ if(n!=P.n){ if(n string Permutation::display() const{ string str; if(n==0) return "()"; str="(\033[34m"+to_string((int64)win[1])+"\033[0m"; for(uint64 i=2;i<=n;++i){ str+=",\033[34m"+to_string((int64)win[i])+"\033[0m"; } str+=')'; return str; } template inline ostream& operator<<(ostream& os,const Permutation& sigma){ return os<::size() const{ return fact(n); } inline size_t PermutationEnumerator::size() const{ return (1<::size() const{ if(n==0) return 1; return (1<<(n-1))*fact(n); } inline string PermutationEnumerator::display() const{ return "Enumerator for permutations of type A and rank <= "+to_string(n); } inline string PermutationEnumerator::display() const{ return "Enumerator for permutations of type B and rank <= "+to_string(n); } inline string PermutationEnumerator::display() const{ return "Enumerator for permutations of type D and rank <= "+to_string(n); } template inline ostream& operator<<(ostream& os,const PermutationEnumerator& E){ return os<