semigroup.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #ifndef SEMIGROUP_HPP
  2. #define SEMIGROUP_HPP
  3. #include <cstring>
  4. #include <cstdint>
  5. #include <cassert>
  6. #include <immintrin.h>
  7. #include <fstream>
  8. #include "config.hpp"
  9. #include "simd.hpp"
  10. union v8x8{
  11. uint64_t v64;
  12. uint32_t v32[2];
  13. uint8_t v8[8];
  14. };
  15. static const size_t m1_32=((1UL<<32)-1);
  16. class Semigroup{
  17. public:
  18. static const size_t _size=3*(g_max-1);
  19. static const size_t navx=((_size+31)/32);
  20. static const size_t nin=((_size+63)/64);
  21. static const size_t size=navx*32;
  22. union{
  23. __m256i avx[navx];
  24. uint8_t delta[size];
  25. };
  26. union{
  27. uint64_t in64[nin];
  28. uint32_t in32[2*nin];
  29. };
  30. size_t c,m,g,e,e_left,left;
  31. Semigroup();
  32. void init_N();
  33. void copy_delta(const Semigroup& S);
  34. void copy_in(const Semigroup& S);
  35. void son(const Semigroup& S,size_t x,size_t pos);
  36. void display() const;
  37. void copy(const Semigroup& S);
  38. ~Semigroup();
  39. void to_file(string filename) const;
  40. void from_file(string filename);
  41. };
  42. class SonIterator{
  43. public:
  44. const Semigroup *S;
  45. size_t mask; // movemask_epi8 returns a 32 bits values
  46. size_t iblock, gen, bound;
  47. public:
  48. SonIterator(const Semigroup *S);
  49. bool move_next();
  50. uint8_t count();
  51. inline size_t get_gen() const {return gen;};
  52. };
  53. inline SonIterator::SonIterator(const Semigroup* _S)
  54. : S(_S), bound(min(Semigroup::navx-1,(_S->c+_S->m+31) >> 5)){
  55. iblock = S->c >> 5;
  56. size_t imask = (S->c&0x1F);
  57. __m256i a=S->avx[iblock];
  58. __m256i b=mask32[imask];
  59. __m256i block = _mm256_and_si256(a,b);
  60. mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(block,avx1))&m1_32;
  61. gen = (iblock << 5) - 1;
  62. };
  63. inline bool
  64. SonIterator::move_next(){
  65. while (not mask){
  66. iblock++;
  67. if (iblock > bound) return false;
  68. gen = (iblock << 5) - 1;
  69. mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(S->avx[iblock],avx1))&m1_32;
  70. }
  71. //unsigned char shift = __bsfq (mask) +1;
  72. uint64_t shift;
  73. asm("bsfq %1,%0" : "=r" (shift) :"r" (mask));
  74. ++shift;
  75. gen += shift;
  76. mask >>= shift;
  77. return true;
  78. };
  79. inline
  80. Semigroup::Semigroup(){
  81. }
  82. #define copy_delta_unroll(i) case (i): \
  83. avx[(i-1)]=S.avx[(i-1)];
  84. inline void
  85. Semigroup::copy_delta(const Semigroup& S){
  86. switch(navx){
  87. copy_delta_unroll(16);
  88. copy_delta_unroll(15);
  89. copy_delta_unroll(14);
  90. copy_delta_unroll(13);
  91. copy_delta_unroll(12);
  92. copy_delta_unroll(11);
  93. copy_delta_unroll(10);
  94. copy_delta_unroll(9);
  95. copy_delta_unroll(8);
  96. copy_delta_unroll(7);
  97. copy_delta_unroll(6);
  98. copy_delta_unroll(5);
  99. copy_delta_unroll(4);
  100. copy_delta_unroll(3);
  101. copy_delta_unroll(2);
  102. case 1:
  103. avx[0]=S.avx[0];
  104. break;
  105. default:
  106. assert(false);
  107. };
  108. }
  109. #define copy_in_unroll(i) case (i): \
  110. in64[(i-1)]=S.in64[(i-1)];
  111. inline void
  112. Semigroup::copy_in(const Semigroup& S){
  113. switch(nin){
  114. copy_in_unroll(8);
  115. copy_in_unroll(7);
  116. copy_in_unroll(6);
  117. copy_in_unroll(5);
  118. copy_in_unroll(4);
  119. copy_in_unroll(3);
  120. copy_in_unroll(2);
  121. case 1:
  122. in64[0]=S.in64[0];
  123. break;
  124. default:
  125. assert(false);
  126. break;
  127. };
  128. }
  129. inline
  130. Semigroup::~Semigroup(){
  131. }
  132. #endif