// ////////////////////////////////////////////// // d8.c Dedekind numbers. // Implementation of Doug H. Wiedemann Algorithm. // C, OpenMP. On 8 11g cores: 15'. 800 lines. // MIT Licensed // // J. M. Aranda. Madrid. 2021. ////////////////////////////// // References // - A computation of the eighth Dedekind number, // Doug Wiedemann , Order, volume 8, 1991. // - Enumerating Free Distributive Lettices, // George Markowsky, 1989 , Report No. 89-10. // - Cardinalities of finite distributive lattices, 1976. // J. Berman, P. Koehler. ///////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include /****** MAIN PARAMETERS ************/ #define SETCMAX 8000000 #define RSETMAX 18000 #define EXPONMAX 6 #define EFACTMAX 720 #define EXPOW2MAX 64 #define QFLMAX 65 #define CONST64 64 #define PWDIM 72 #define RULEDIM 70 #define STRINGMAX 32 ////////////////////////// typedef uint_fast16_t U16; typedef int_fast32_t I32; typedef uint_fast32_t U32; typedef uint_fast64_t U64; typedef unsigned __int128 VAL128; typedef uint_fast64_t VAL64; typedef uint_fast64_t ITEM64; // #pragma pack(16) static I32 CSetCard=0; static I32 EXPONFACT,RSETCARD=0; static I32 QORBDUA=0; static I32 QBASE=0; static U16 globit=0,EXPONGLOBAL=0,EXPOW; static bool ESPOT=false; #define DIMPAR 8 static int NUMTHR=DIMPAR; /************************************************************************ OMP ****/ static VAL64 POWERS[PWDIM]__attribute__((aligned)); static VAL64 APORTA[SETCMAX]; static ITEM64 CSET[SETCMAX]__attribute__((aligned)); static bool ISDUPLI[SETCMAX]__attribute__((aligned)); static I32 RSET[RSETMAX]__attribute__((aligned)); static I32 RBASE[RSETMAX]; // static I32 INDEXQ[QFLMAX]__attribute__((aligned)); static I32 INDEXF[QFLMAX]; static I32 INDEXL[QFLMAX]; static I32 CENTER[SETCMAX]__attribute__((aligned)); static I32 ORBITSZ[SETCMAX]; static I32 VALDUAL[SETCMAX]__attribute__((aligned)); static I32 ORBITDUAL[SETCMAX]; static I32 LESSCOUNT[SETCMAX]__attribute__((aligned)); static I32 GREATCOUNT[SETCMAX]; /************* OMP ************/ static ITEM64 WTOFIND[DIMPAR][SETCMAX]; static I32 ISWHERE[DIMPAR][SETCMAX]; static VAL64 JKPRODUCT[DIMPAR][SETCMAX]; /************************************************************** OMP ************/ static U64 RULENUMERIC[RULEDIM]; static char RULESTEXT[RULEDIM][RULEDIM]; static U16 PERMsmall[EFACTMAX][EXPONMAX]; static U16 PERMbig[EFACTMAX][EXPOW2MAX]; static char COMONBUFFER[STRINGMAX]; /**************************************/ static inline void clearLine(void) __attribute__((cold)); static inline void clearLine(void) { printf("\r "); printf("\r"); } static inline U16 istrlen(const char *p) __attribute__((hot)); static inline U16 istrlen(const char *p) { U16 r=strlen(p); return r; } static void BUFROM128(const VAL128 p) __attribute__((cold)); static void BUFROM128(const VAL128 p) { const char CHZ='0';VAL128 n=p; for(int i=0;i= 1); int m=n%10; //if(k%5 ==0)COMONBUFFER[k--]='.'; COMONBUFFER[k--]=(CHZ+m); n=(n-m);n=n/10; } assert(k >=0); for(int i=0;i= DIMPAR)NUMTHR=DIMPAR; else NUMTHR=nuc; omp_set_num_threads(NUMTHR); printf("Detected Cores: %4d \n",nuc); /***********************************/ omp_set_dynamic(0);omp_set_nested(0); omp_set_max_active_levels( 1 ); omp_set_schedule(omp_sched_static,200); } static void genrules(const int pn) __attribute__((cold)); static void genrules(const int pn) { const int dkn=pn;char l[dkn+4];int a,b,k; assert(dkn <= RULEDIM); a=3;b=3; for(int r=0;r< dkn;r++) { if(r == 0){a=3;b=3;} for(int i=0;i=0);b--)uder++; rvn=0;cox=0; for(int b=dkn;b>=0;b--) { assert(b <= RULEDIM);ch=l[b]; if(ch == '1')rvn++; else if(ch == 'x')cox++; else if(ch == 'e'){rvn++;break;} rvn<<=1; } RULENUMERIC[r]=rvn; } a--;if(a<0){a=b;b=2*b+1;} } } static bool createset(const int pn) __attribute__((cold)); static bool createset(const int pn) { ITEM64 tmp,rnm,pwm,mit; I32 grovI,kC; const int nk=pn; assert(nk >= 1); CSET[0]=0;CSET[1]=1;grovI=2;kC=grovI; globit=1; for(int k=globit;k= SETCMAX)return false; CSET[kC++]=tmp; } grovI=kC; } CSetCard=grovI; for(int i=0;i <= (CSetCard-2);i++) assert(CSET[i] < CSET[i+1]); /* Checked set m.ascending */ return true; } /******** hot functions **************/ static inline bool nbiti( const ITEM64 n,const U16 globit)__attribute__((hot)); static inline bool nbiti( const ITEM64 n,const U16 globit) { bool v;ITEM64 w; v=false;w=n&POWERS[globit];if(w>0)v=true; return v; } static int factorial(const int e) __attribute__((cold)); static int factorial(const int e) { int f=1; for(int i=2;i<=e;i++)f*=i; return f; } /* modo 64b */ #define TSUXEN 4 typedef struct {U16 E[TSUXEN]; } TSUXE; typedef union {ITEM64 L;TSUXE P; } TU64; /*** mode ITEM64 64bit ***/ static inline bool ITEMLEQITEM(const I32 pa,const I32 pb) __attribute__((hot)) __attribute__((pure)); static inline bool ITEMLEQITEM(const I32 pa,const I32 pb) { TU64 ua,ub,tmp; /* 64b mode leq binary */ ua.L=CSET[pa];ub.L=CSET[pb]; for(int i=0;i < TSUXEN;i++) { tmp.P.E[i]=(ua.P.E[i] & ub.P.E[i]); if(tmp.P.E[i] != ua.P.E[i])return false; } return true; } static void fillQless( const I32 ini,const I32 las) __attribute__((hot)); static void fillQless( const I32 ini,const I32 las) { for(I32 ii=ini;ii=1); assert(GREATCOUNT[i] >=1); } } } static inline I32 binsearchCset( const int capoin,const bool mbe,const I32 ini, const I32 fin,const U64 WTOFIND) __attribute__((hot))__attribute__((pure)); static inline I32 binsearchCset( const int capoin,const bool mbe,const I32 ini, const I32 fin,const ITEM64 WTOFIND) { const ITEM64 wtfk=WTOFIND;const int k64=CONST64; I32 fi,la,mi,di;int lc; /* binary search */ if(wtfk == 0)lc=k64; else lc=__builtin_clzll(wtfk); fi=INDEXF[lc];if(ini > fi)fi=ini; la=INDEXL[lc];if(fin < la)la=fin; di=la-fi; while(di >= 0) { ITEM64 Cmi; di>>=1;mi=fi+di;Cmi=CSET[mi]; if((wtfk < Cmi))la=mi-1; else if((wtfk > Cmi))fi=mi+1; else return mi; di=(la-fi); } if(mbe)assert(mbe == false); if(capoin); return -1; } static inline VAL64 sumaporta(const I32 ii) __attribute__((hot)); static inline VAL64 sumaporta(const I32 ii) { const I32 CSetCardk=CSetCard;const I32 CSetCardk1=CSetCard-1; const int ntk=omp_get_thread_num(); const I32 iik=ii; const ITEM64 Cik=CSET[ii]; const ITEM64 Cik4[4]={Cik,Cik,Cik,Cik}; VAL64 sapo;const I32 L4=(CSetCard-(CSetCard%4)); for(I32 h=0;h pista)pista=h; ISWHERE[ntk][h]= binsearchCset(2,true,pista,CSetCardk1,WTOFIND[ntk][h]); } for(I32 h=0;h 0); return sapo; } static VAL128 setMultiplier(void)__attribute__((hot)); static VAL128 setMultiplier(void) { const I32 CSetCardk=CSetCard; const I32 RVALk=RSETCARD; VAL128 apo8;I32 lcrum; for(I32 i=0;i= 0) APORTA[ii]=APORTA[ORBITDUAL[ii]]; } if(ESPOT) { for(int i=0;i 0); poa=(VAL128)(ORBITSZ[ig]*APORTA[ig]); apo8+=poa; } return apo8; } static void fillINDEXQFL(void)__attribute__((hot)); static void fillINDEXQFL(void) { const I32 CSetCardk=CSetCard; const I32 CSetCardk1=CSetCard-1; const int k64=CONST64; for(int i=0;i < QFLMAX;i++) {INDEXQ[i]=0;INDEXF[i]=0;INDEXL[i]=0; } for(I32 i=0;i < CSetCardk;i++) { ITEM64 Ci=CSET[i]; int lc; if(Ci == 0)lc=k64; else lc=__builtin_clzll(CSET[i]); assert(lc >= 0);assert(lc <= k64); if(INDEXQ[lc] == 0)INDEXF[lc]=i; INDEXQ[lc]++; } for(int i=0;i0)e=true; ba[biTk1-b]=!e; } w=0; for(int b=0;b1 && (impa%2) == 0)impa/=2; if(impa == 1)ESPOT=true; for(I32 i=0;i= pnk)vale=false; } PEVALE[p]=vale; } npermut=0; for(U16 p=0;p 0); /* Big for fillRSET */ for(I32 iii=0;iii= 1);assert(EXPONFACT%sze == 0); ORBITSZ[iii]=sze; for(I32 p=0;p= RSETMAX)return false; // RSETMAX too small. RSET[ctd++]=i; } } RSETCARD=ctd;sorb=0; for(I32 i=0;i= EXPONGLOBAL){ok=false;break;} PPcifra[c]=dig;t/=10; } if(!ok)continue; for(U16 c=0;c 256.*/ for(int e=0;e<64;e++) { /* dont touch POWERS dim */ POWERS[e]=1; for(int i=0;i