|
@@ -1,5 +1,5 @@
|
|
-#ifndef MONOID_HPP
|
|
|
|
-#define MONOID_HPP
|
|
|
|
|
|
+#ifndef SEMIGROUP_HPP
|
|
|
|
+#define SEMIGROUP_HPP
|
|
|
|
|
|
#include <cstdint>
|
|
#include <cstdint>
|
|
#include <fstream>
|
|
#include <fstream>
|
|
@@ -28,7 +28,7 @@ typedef uint_fast64_t ind_t; // The type used for array indexes
|
|
|
|
|
|
using namespace std;
|
|
using namespace std;
|
|
|
|
|
|
-struct monoid
|
|
|
|
|
|
+struct Semigroup
|
|
{
|
|
{
|
|
union {
|
|
union {
|
|
dec_numbers decs;
|
|
dec_numbers decs;
|
|
@@ -38,18 +38,19 @@ struct monoid
|
|
ind_t conductor, min, genus,left_primitive,left,e,wilf;
|
|
ind_t conductor, min, genus,left_primitive,left,e,wilf;
|
|
};
|
|
};
|
|
|
|
|
|
-void init_full_N(monoid &);
|
|
|
|
-void init_ordinary(monoid& O,int m);
|
|
|
|
-void print_monoid(const monoid &);
|
|
|
|
-void print_monoid_gen(const monoid&);
|
|
|
|
|
|
+void init_full_N(Semigroup &);
|
|
|
|
+void init(Semigroup&,char,char,char,char*);
|
|
|
|
+void print_Semigroup(const Semigroup &);
|
|
|
|
+void print_Semigroup_gen(const Semigroup&);
|
|
void print_epi8(epi8);
|
|
void print_epi8(epi8);
|
|
-void output(const monoid& m,fstream& f);
|
|
|
|
|
|
+void output(const Semigroup& m,fstream& f);
|
|
|
|
+void record(const Semigroup& S,fstream& f);
|
|
inline void copy_blocks( dec_blocks &__restrict__ dst,
|
|
inline void copy_blocks( dec_blocks &__restrict__ dst,
|
|
const dec_blocks &__restrict__ src);
|
|
const dec_blocks &__restrict__ src);
|
|
-inline void remove_generator(monoid &__restrict__ dst,
|
|
|
|
- const monoid &__restrict__ src,
|
|
|
|
|
|
+inline void remove_generator(Semigroup &__restrict__ dst,
|
|
|
|
+ const Semigroup &__restrict__ src,
|
|
ind_t gen,ind_t pos);
|
|
ind_t gen,ind_t pos);
|
|
-inline monoid remove_generator(const monoid &src, ind_t gen,ind_t pos);
|
|
|
|
|
|
+inline Semigroup remove_generator(const Semigroup &src, ind_t gen,ind_t pos);
|
|
|
|
|
|
|
|
|
|
// typedef enum { ALL, CHILDREN } generator_type;
|
|
// typedef enum { ALL, CHILDREN } generator_type;
|
|
@@ -57,17 +58,16 @@ class ALL {};
|
|
class CHILDREN {};
|
|
class CHILDREN {};
|
|
|
|
|
|
// template <generator_type T> class generator_iter
|
|
// template <generator_type T> class generator_iter
|
|
-template <class T> class generator_iter
|
|
|
|
-{
|
|
|
|
|
|
+template <class T> class generator_iter{
|
|
private:
|
|
private:
|
|
|
|
|
|
- const monoid &m;
|
|
|
|
|
|
+ const Semigroup &m;
|
|
unsigned int mask; // movemask_epi8 returns a 32 bits values
|
|
unsigned int mask; // movemask_epi8 returns a 32 bits values
|
|
ind_t iblock, gen, bound;
|
|
ind_t iblock, gen, bound;
|
|
|
|
|
|
public:
|
|
public:
|
|
|
|
|
|
- generator_iter(const monoid &mon);
|
|
|
|
|
|
+ generator_iter(const Semigroup &mon);
|
|
bool move_next();
|
|
bool move_next();
|
|
uint8_t count();
|
|
uint8_t count();
|
|
inline ind_t get_gen() const {return gen; };
|
|
inline ind_t get_gen() const {return gen; };
|
|
@@ -137,9 +137,8 @@ const epi8 mask16[16] =
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1} };
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1} };
|
|
|
|
|
|
|
|
|
|
-template<> inline generator_iter<ALL>::generator_iter(const monoid &mon)
|
|
|
|
- : m(mon), bound((mon.conductor+mon.min+15) >> 4)
|
|
|
|
-{
|
|
|
|
|
|
+template<> inline generator_iter<ALL>::generator_iter(const Semigroup &mon)
|
|
|
|
+ : m(mon), bound((mon.conductor+mon.min+15) >> 4){
|
|
epi8 block;
|
|
epi8 block;
|
|
iblock = 0;
|
|
iblock = 0;
|
|
block = m.blocks[0];
|
|
block = m.blocks[0];
|
|
@@ -149,9 +148,8 @@ template<> inline generator_iter<ALL>::generator_iter(const monoid &mon)
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
-template<> inline generator_iter<CHILDREN>::generator_iter(const monoid &mon)
|
|
|
|
- : m(mon), bound((mon.conductor+mon.min+15) >> 4)
|
|
|
|
-{
|
|
|
|
|
|
+template<> inline generator_iter<CHILDREN>::generator_iter(const Semigroup &mon)
|
|
|
|
+ : m(mon), bound((mon.conductor+mon.min+15) >> 4){
|
|
epi8 block;
|
|
epi8 block;
|
|
iblock = m.conductor >> 4;
|
|
iblock = m.conductor >> 4;
|
|
block = m.blocks[iblock] & mask16[m.conductor & 0xF];
|
|
block = m.blocks[iblock] & mask16[m.conductor & 0xF];
|
|
@@ -159,23 +157,20 @@ template<> inline generator_iter<CHILDREN>::generator_iter(const monoid &mon)
|
|
gen = (iblock << 4) - 1;
|
|
gen = (iblock << 4) - 1;
|
|
};
|
|
};
|
|
|
|
|
|
-template <class T> inline uint8_t generator_iter<T>::count()
|
|
|
|
-{
|
|
|
|
|
|
+template <class T> inline uint8_t generator_iter<T>::count(){
|
|
uint8_t nbr = _mm_popcnt_u32(mask); // popcnt returns a 8 bits value
|
|
uint8_t nbr = _mm_popcnt_u32(mask); // popcnt returns a 8 bits value
|
|
for (ind_t ib = iblock+1; ib < bound; ib++)
|
|
for (ind_t ib = iblock+1; ib < bound; ib++)
|
|
nbr += _mm_popcnt_u32(movemask_epi8(m.blocks[ib] == block1));
|
|
nbr += _mm_popcnt_u32(movemask_epi8(m.blocks[ib] == block1));
|
|
return nbr;
|
|
return nbr;
|
|
};
|
|
};
|
|
|
|
|
|
-template <class T> inline bool generator_iter<T>::move_next()
|
|
|
|
-{
|
|
|
|
- while (!mask)
|
|
|
|
- {
|
|
|
|
- iblock++;
|
|
|
|
- if (iblock > bound) return false;
|
|
|
|
- gen = (iblock << 4) - 1;
|
|
|
|
- mask = movemask_epi8(m.blocks[iblock] == block1);
|
|
|
|
- }
|
|
|
|
|
|
+template <class T> inline bool generator_iter<T>::move_next(){
|
|
|
|
+ while (!mask){
|
|
|
|
+ iblock++;
|
|
|
|
+ if (iblock > bound) return false;
|
|
|
|
+ gen = (iblock << 4) - 1;
|
|
|
|
+ mask = movemask_epi8(m.blocks[iblock] == block1);
|
|
|
|
+ }
|
|
unsigned char shift = __bsfd (mask) + 1; // Bit Scan Forward
|
|
unsigned char shift = __bsfd (mask) + 1; // Bit Scan Forward
|
|
gen += shift;
|
|
gen += shift;
|
|
mask >>= shift;
|
|
mask >>= shift;
|
|
@@ -185,8 +180,7 @@ template <class T> inline bool generator_iter<T>::move_next()
|
|
|
|
|
|
|
|
|
|
inline __attribute__((always_inline))
|
|
inline __attribute__((always_inline))
|
|
-void copy_blocks(dec_blocks &dst, dec_blocks const &src)
|
|
|
|
-{
|
|
|
|
|
|
+void copy_blocks(dec_blocks &dst, dec_blocks const &src){
|
|
for (ind_t i=0; i<NBLOCKS; i++) dst[i] = src[i];
|
|
for (ind_t i=0; i<NBLOCKS; i++) dst[i] = src[i];
|
|
}
|
|
}
|
|
|
|
|
|
@@ -194,11 +188,10 @@ void copy_blocks(dec_blocks &dst, dec_blocks const &src)
|
|
#include <cassert>
|
|
#include <cassert>
|
|
|
|
|
|
inline __attribute__((always_inline))
|
|
inline __attribute__((always_inline))
|
|
-void remove_generator(monoid &__restrict__ dst,
|
|
|
|
- const monoid &__restrict__ src,
|
|
|
|
|
|
+void remove_generator(Semigroup &__restrict__ dst,
|
|
|
|
+ const Semigroup &__restrict__ src,
|
|
ind_t gen,
|
|
ind_t gen,
|
|
- ind_t pos)
|
|
|
|
-{
|
|
|
|
|
|
+ ind_t pos){
|
|
ind_t start_block, decal;
|
|
ind_t start_block, decal;
|
|
epi8 block;
|
|
epi8 block;
|
|
|
|
|
|
@@ -207,8 +200,15 @@ void remove_generator(monoid &__restrict__ dst,
|
|
ind_t t=gen+1;
|
|
ind_t t=gen+1;
|
|
dst.conductor = t;
|
|
dst.conductor = t;
|
|
dst.genus = src.genus + 1;
|
|
dst.genus = src.genus + 1;
|
|
- dst.min=src.min;
|
|
|
|
- int delta=(src.decs[gen+src.min]==2)?0:-1;
|
|
|
|
|
|
+ int delta;
|
|
|
|
+ if(gen==src.min){
|
|
|
|
+ dst.min=gen+1;
|
|
|
|
+ delta=1;
|
|
|
|
+ }
|
|
|
|
+ else{
|
|
|
|
+ dst.min=src.min;
|
|
|
|
+ delta=(src.decs[gen+src.min]==2)?0:-1;
|
|
|
|
+ }
|
|
dst.e=src.e+delta;
|
|
dst.e=src.e+delta;
|
|
assert(dst.e==((gen==src.min)?src.e+1:((src.decs[gen+src.min]==2)?src.e:src.e-1)));
|
|
assert(dst.e==((gen==src.min)?src.e+1:((src.decs[gen+src.min]==2)?src.e:src.e-1)));
|
|
ind_t k=gen-src.conductor;
|
|
ind_t k=gen-src.conductor;
|
|
@@ -226,21 +226,18 @@ void remove_generator(monoid &__restrict__ dst,
|
|
dst.blocks[start_block] -= ((block != zero) & block1);
|
|
dst.blocks[start_block] -= ((block != zero) & block1);
|
|
|
|
|
|
|
|
|
|
- for (auto i=start_block+1; i<NBLOCKS; i++)
|
|
|
|
- {
|
|
|
|
|
|
+ for (auto i=start_block+1; i<NBLOCKS; i++){
|
|
// The following won't work due to some alignment problem (bug in GCC 4.7.1?)
|
|
// The following won't work due to some alignment problem (bug in GCC 4.7.1?)
|
|
// block = *((epi8*)(src.decs + ((i-start_block)<<4) - decal));
|
|
// block = *((epi8*)(src.decs + ((i-start_block)<<4) - decal));
|
|
block = load_unaligned_epi8(src.decs + ((i-start_block)<<4) - decal);
|
|
block = load_unaligned_epi8(src.decs + ((i-start_block)<<4) - decal);
|
|
dst.blocks[i] -= ((block != zero) & block1);
|
|
dst.blocks[i] -= ((block != zero) & block1);
|
|
}
|
|
}
|
|
-
|
|
|
|
-
|
|
|
|
assert(dst.decs[dst.conductor-1] == 0);
|
|
assert(dst.decs[dst.conductor-1] == 0);
|
|
}
|
|
}
|
|
|
|
|
|
-inline monoid remove_generator(const monoid &src, ind_t gen,ind_t pos)
|
|
|
|
-{
|
|
|
|
- monoid dst;
|
|
|
|
|
|
+inline Semigroup
|
|
|
|
+remove_generator(const Semigroup &src, ind_t gen,ind_t pos){
|
|
|
|
+ Semigroup dst;
|
|
remove_generator(dst, src, gen,pos);
|
|
remove_generator(dst, src, gen,pos);
|
|
return dst;
|
|
return dst;
|
|
}
|
|
}
|