123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- /**
- * This file is part of Gomu.
- *
- * Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
- #ifndef PERMUTATIONS_HPP
- #define PERMUTATIONS_HPP
- #include <cassert>
- #include <cstdint>
- #include <iostream>
- #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<CoxeterType T> 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<CoxeterType U> friend ostream& operator<<(ostream&,const Permutation<U>&);
- };
- template<CoxeterType T> class PermutationEnumerator;
-
- template<> class PermutationEnumerator<CoxeterA>{
- protected:
- Permutation<CoxeterA> sigma;
- uint64 n;
- public:
- PermutationEnumerator(uint64);
- void reset();
- bool next();
- size_t size() const;
- const Permutation<CoxeterA>& get() const;
- int cmp(const PermutationEnumerator<CoxeterA>& E) const;
- string display() const;
- friend ostream& operator<<(ostream&,const PermutationEnumerator<CoxeterA>&);
- };
- template<> class PermutationEnumerator<CoxeterB>:public PermutationEnumerator<CoxeterA>{
- protected:
- Permutation<CoxeterB> sigmaB;
- uint64 sign;
- public:
- PermutationEnumerator(uint64);
- void reset();
- bool next();
- size_t size() const;
- const Permutation<CoxeterB>& get() const;
- int cmp(const PermutationEnumerator<CoxeterB>& E) const;
- string display() const;
- friend ostream& operator<<(ostream&,const PermutationEnumerator<CoxeterB>&);
- };
- template<> class PermutationEnumerator<CoxeterD>:public PermutationEnumerator<CoxeterA>{
- protected:
- Permutation<CoxeterD> sigmaD;
- uint64 sign;
- public:
- PermutationEnumerator(uint64);
- void reset();
- bool next();
- size_t size() const;
- const Permutation<CoxeterD>& get() const;
- int cmp(const PermutationEnumerator<CoxeterD>& E) const;
- string display() const;
- friend ostream& operator<<(ostream&,const PermutationEnumerator<CoxeterD>&);
- };
- typedef Permutation<CoxeterA> PermutationA;
- typedef Permutation<CoxeterB> PermutationB;
- typedef Permutation<CoxeterD> 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<CoxeterType T> Permutation<T> Permutation<T>::Ptemp;
- template<CoxeterType T> inline
- Permutation<T>::Permutation(uint64 r):n(r),m128(id128){
- }
- template<CoxeterType T> void
- Permutation<T>::setInverse(Permutation<T>& 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<CoxeterType T> const Permutation<T>&
- Permutation<T>::getInverse() const{
- setInverse(Ptemp);
- return Ptemp;
- }
- template<> inline uint64
- Permutation<CoxeterA>::descentInteger() const{
- __m128i temp=_mm_shuffle_epi8(m128,shmask);
- temp=_mm_cmpgt_epi8(m128,temp);
- return _mm_movemask_epi8(temp);
- }
- template<> inline uint64
- Permutation<CoxeterB>::descentInteger() const{
- __m128i temp=_mm_shuffle_epi8(m128,shmask);
- temp=_mm_cmpgt_epi8(m128,temp);
- return _mm_movemask_epi8(temp);
- }
- template<> inline uint64
- Permutation<CoxeterD>::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<CoxeterType T> int
- Permutation<T>::cmp(const Permutation& P) const{
- if(n!=P.n){
- if(n<P.n) return 1;
- return -1;
- }
- for(uint64 i=1;i<=n;++i){
- if(win[i]!=P.win[i]){
- if(win[i]<P.win[i]) return 1;
- return -1;
- }
- }
- return 0;
- }
- template<CoxeterType T> string
- Permutation<T>::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<CoxeterType T> inline ostream&
- operator<<(ostream& os,const Permutation<T>& sigma){
- return os<<sigma.display();
- }
- //
- // PermutationEnumerator
- //
- inline size_t
- PermutationEnumerator<CoxeterA>::size() const{
- return fact(n);
- }
- inline size_t
- PermutationEnumerator<CoxeterB>::size() const{
- return (1<<n)*fact(n);
- }
- inline size_t
- PermutationEnumerator<CoxeterD>::size() const{
- if(n==0) return 1;
- return (1<<(n-1))*fact(n);
- }
- inline string
- PermutationEnumerator<CoxeterA>::display() const{
- return "Enumerator for permutations of type A and rank <= "+to_string(n);
- }
- inline string
- PermutationEnumerator<CoxeterB>::display() const{
- return "Enumerator for permutations of type B and rank <= "+to_string(n);
- }
- inline string
- PermutationEnumerator<CoxeterD>::display() const{
- return "Enumerator for permutations of type D and rank <= "+to_string(n);
- }
- template<CoxeterType T> inline ostream&
- operator<<(ostream& os,const PermutationEnumerator<T>& E){
- return os<<E.display();
- }
- #endif
|