Description: enable runtime detection of popcnt-enabled CPU Origin: fedora Author: Jerry James Last-Update: 2016-04-20 --- a/addedgeg.c +++ b/addedgeg.c @@ -74,6 +74,23 @@ no4path(graph *g, int m, int n, int v, i } /*************************************************************************/ +STATIC_POPCNTFUNC(int,compute_degree,(const graph *g, int *deg, int m, int n), +{ + const setword *gv; + int v, actmaxdeg = 0; + + for (v = 0, gv = g; v < n; ++v, gv += m) + { + int i, degv = 0; + for (i = 0; i < m; ++i) + degv += POPCOUNT(gv[i]); + if (degv > actmaxdeg) actmaxdeg = degv; + deg[v] = degv; + } + return actmaxdeg; +}) + +/*************************************************************************/ int main(int argc, char *argv[]) @@ -89,7 +106,7 @@ main(int argc, char *argv[]) nauty_counter nin,nout; char *arg,sw; setword *gv,*gw; - int maxdeg,actmaxdeg,degv; + int maxdeg,actmaxdeg; double t; #if MAXN graph h[MAXN*MAXM]; @@ -208,16 +225,7 @@ main(int argc, char *argv[]) DYNALLOC1(int,dist,dist_sz,n,"addedgeg"); #endif - actmaxdeg = n; - for (v = 0, gv = g; v < n; ++v, gv += m) - { - degv = 0; - for (i = 0; i < m; ++i) - degv += POPCOUNT(gv[i]); - if (degv < actmaxdeg) actmaxdeg = degv; - deg[v] = degv; - } - + actmaxdeg = compute_degree(g, deg, m, n); if (actmaxdeg > maxdeg) continue; okdist[0] = okdist[1] = FALSE; --- a/complg.c +++ b/complg.c @@ -50,6 +50,17 @@ compl(graph *g, int m, int n, graph *h, } } +/*************************************************************************/ +STATIC_POPCNTFUNC(size_t __attribute__((pure)),num_edges, + (const graph *g, size_t gwords), +{ + size_t ii, ned; + + ned = 0; + for (ii = 0; ii < gwords; ++ii) ned += POPCOUNT(g[ii]); + return ned; +}) + /**************************************************************************/ int @@ -172,10 +183,10 @@ main(int argc, char *argv[]) if (restricted || Restricted) { - ned = loops = 0; + loops = 0; gwords = m * (size_t)n; nn = n * (size_t)(n-1); - for (ii = 0; ii < gwords; ++ii) ned += POPCOUNT(g[ii]); + ned = num_edges(g, gwords); for (ii = 0; ii < n; ++ii) if (ISELEMENT(g+m*ii,ii)) ++loops; if (Lswitch) { --- a/configure.ac +++ b/configure.ac @@ -300,6 +300,9 @@ dnl --disable-popcnt disables the use of AC_MSG_CHECKING(if popcnt instruction is available and requested) AC_ARG_ENABLE([popcnt], AS_HELP_STRING([--disable-popcnt], [Disable popcnt extensions]), [popcntarg=given], [popcntarg=notgiven]) +AC_ARG_ENABLE([runtime-popcnt], + AS_HELP_STRING([--enable-runtime-popcnt], [Detect popcnt extensions at runtime]), + [runtime_popcnt=1;enable_popcnt=yes], [runtime_popcnt=0]) AS_IF([test "x$popcntarg" = "xnotgiven" -o "x$enable_popcnt" = "xyes"], [ have_hwpopcnt=0 test -e /proc/cpuinfo && grep -i popcnt /proc/cpuinfo >/dev/null && have_hwpopcnt=1 @@ -329,7 +333,6 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([#include main(){unsigned int x; x = _mm_popcnt_u64(x);}])], [have_mmpop64=1], [have_mmpop64=0]) AC_MSG_RESULT($have_mmpop64) ], [ -CFLAGS="$CFLAGS -mpopcnt" AC_MSG_CHECKING(if __builtin_popcount() is supported) AC_LINK_IFELSE([AC_LANG_SOURCE([main(){unsigned int x; x = __builtin_popcount(x);}])], [have_popcnt=1], [have_popcnt=0]) AC_MSG_RESULT($have_popcnt) @@ -348,6 +351,7 @@ AC_SUBST(have_popcntl) AC_SUBST(have_popcntll) AC_SUBST(have_mmpop32) AC_SUBST(have_mmpop64) +AC_SUBST(runtime_popcnt) AC_SUBST(MORECFLAGS) dnl --disable-clz disables the use of gcc extensions __builtin_clz*() --- a/deledgeg.c +++ b/deledgeg.c @@ -16,6 +16,23 @@ #include "gtools.h" +/*************************************************************************/ +STATIC_POPCNTFUNC(int,compute_degree,(const graph *g, int *deg, int m, int n), +{ + const setword *gv; + int v, actmindeg = n; + + for (v = 0, gv = g; v < n; ++v, gv += m) + { + int i, degv = 0; + for (i = 0; i < m; ++i) + degv += POPCOUNT(gv[i]); + if (degv < actmindeg) actmindeg = degv; + deg[v] = degv; + } + return actmindeg; +}) + /**************************************************************************/ int @@ -25,13 +42,13 @@ main(int argc, char *argv[]) FILE *infile,*outfile; boolean badargs,dolabel,quiet,dswitch; boolean digraph; - int i,j,m,n,v,w,argnum; + int j,m,n,v,w,argnum; int codetype,outcode; graph *g,*gq; nauty_counter nin,nout; char *arg,sw; setword *gv,*gw; - int mindeg,actmindeg,degv; + int mindeg,actmindeg; boolean zswitch; double t; #if MAXN @@ -136,16 +153,7 @@ main(int argc, char *argv[]) DYNALLOC1(int,deg,deg_sz,n,"deledgeg"); #endif - actmindeg = n; - for (v = 0, gv = g; v < n; ++v, gv += m) - { - degv = 0; - for (i = 0; i < m; ++i) - degv += POPCOUNT(gv[i]); - if (degv < actmindeg) actmindeg = degv; - deg[v] = degv; - } - + actmindeg = compute_degree(g, deg, m, n); if (actmindeg < mindeg) continue; if (zswitch || digraph) --- a/delptg.c +++ b/delptg.c @@ -104,6 +104,22 @@ search(int level, int ndel, int *del, gr } } +/*************************************************************************/ +STATIC_POPCNTFUNC(void,check_degree, + (const graph *g, boolean *degok, int m, int n, long mindeg, long maxdeg), +{ + const setword *gv; + int v; + + for (v = 0, gv = g; v < n; ++v, gv += m) + { + int i, degv = 0; + for (i = 0; i < m; ++i) + degv += POPCOUNT(gv[i]); + degok[v] = (degv >= mindeg) && (degv <= maxdeg); + } +}) + /**************************************************************************/ int @@ -112,15 +128,13 @@ main(int argc, char *argv[]) char *infilename,*outfilename; FILE *infile; boolean badargs,quiet,dswitch,nswitch; - int i,j,m,n,v,argnum; + int j,m,n,argnum; int ndel; int codetype; graph *g; nauty_counter nin; char *arg,sw; - setword *gv; long mindeg,maxdeg; - int degv; double t; #if MAXN boolean degok[MAXN]; @@ -239,13 +253,7 @@ main(int argc, char *argv[]) DYNALLOC1(int,del,del_sz,n,"delptg"); #endif - for (v = 0, gv = g; v < n; ++v, gv += m) - { - degv = 0; - for (i = 0; i < m; ++i) - degv += POPCOUNT(gv[i]); - degok[v] = (degv >= mindeg) && (degv <= maxdeg); - } + check_degree(g, degok, m, n, mindeg, maxdeg); search(0,ndel,del,g,m,n,degok); --- a/directg.c +++ b/directg.c @@ -380,6 +380,16 @@ scan(int level, int ne, int minarcs, int return level-1; } +/*************************************************************************/ +STATIC_POPCNTFUNC(int __attribute__((pure)),compute_degree,(const set *s, int m), +{ + int i, deg; + + deg = 0; + for (i = 0; i < m; ++i) deg += POPCOUNT(s[i]); + return deg; +}) + /**************************************************************************/ static void @@ -406,8 +416,7 @@ direct(graph *g, int nfixed, long minarc ne = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { - deg = 0; - for (j = 0; j < m; ++j) deg += POPCOUNT(gi[j]); + deg = compute_degree(gi, m); if (deg == 0) { lab[++j0] = i; --- a/genbg.c +++ b/genbg.c @@ -465,8 +465,7 @@ isconnected(graph *g, int n) /**************************************************************************/ -static boolean -distinvar(graph *g, int *invar, int n1, int n2) +STATIC_POPCNTFUNC(boolean,distinvar,(graph *g, int *invar, int n1, int n2), /* make distance invariant/ exit immediately FALSE if n-1 not maximal else exit TRUE Note: only invar[n1..n1+n2-1] set */ @@ -498,7 +497,7 @@ distinvar(graph *g, int *invar, int n1, if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; -} +}) /**************************************************************************/ @@ -654,10 +653,10 @@ userautomproc(int count, int *p, int *or * * *****************************************************************************/ -static void -refinex(graph *g, int *lab, int *ptn, int level, int *numcells, +STATIC_POPCNTFUNC(void,refinex, + (graph *g, int *lab, int *ptn, int level, int *numcells, int *count, set *active, boolean goodret, - int *code, int m, int n) + int *code, int m, int n), { int i,c1,c2,labc1; setword x; @@ -790,7 +789,7 @@ refinex(graph *g, int *lab, int *ptn, in } } } -} +}) /**************************************************************************/ @@ -938,9 +937,28 @@ accept1(graph *g, int n2, int x, graph * } /**************************************************************************/ +#ifdef INSTRUMENT +#define INSTRUMENT_VAR(var) ++var +#define INSTRUMENT_UNIQ(var) if (nuniq) ++var +#else +#define INSTRUMENT_VAR(var) +#define INSTRUMENT_UNIQ(var) +#endif -static boolean -accept2(graph *g, int n2, int x, graph *gx, int *deg, boolean nuniq) +#ifdef PRUNE1 +#define DO_PRUNE1(a,b,c,d,e) if (PRUNE1(a,b,c,d,e)) return FALSE +#else +#define DO_PRUNE1(a,b,c,d,e) +#endif + +#ifdef PRUNE2 +#define DO_PRUNE2(a,b,c,d,e) if (PRUNE2(a,b,c,d,e)) return FALSE +#else +#define DO_PRUNE2(a,b,c,d,e) +#endif + +STATIC_POPCNTFUNC(boolean,accept2, + (graph *g, int n2, int x, graph *gx, int *deg, boolean nuniq), /* decide if n in theta(g+x) -- version for n+1 == maxn */ { int i,n; @@ -957,10 +975,8 @@ accept2(graph *g, int n2, int x, graph * static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; -#ifdef INSTRUMENT - ++a2calls; - if (nuniq) ++a2uniq; -#endif + INSTRUMENT_VAR(a2calls); + INSTRUMENT_UNIQ(a2uniq); n = n1 + n2; nx = n + 1; for (i = 0; i < n; ++i) @@ -980,18 +996,12 @@ accept2(graph *g, int n2, int x, graph * gx[n] |= bit[i]; ++degx[i]; } -#ifdef PRUNE1 - if (PRUNE1(gx,degx,n1,n2+1,maxn2)) return FALSE; -#endif + DO_PRUNE1(gx,degx,n1,n2+1,maxn2); if (nuniq) { -#ifdef INSTRUMENT - ++a2succs; -#endif -#ifdef PRUNE2 - if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; -#endif + INSTRUMENT_VAR(a2succs); + DO_PRUNE2(gx,degx,n1,n2+1,maxn2); if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } @@ -1040,12 +1050,8 @@ accept2(graph *g, int n2, int x, graph * { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif -#ifdef PRUNE2 - if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; -#endif + INSTRUMENT_VAR(a2succs); + DO_PRUNE2(gx,degx,n1,n2+1,maxn2); if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } @@ -1096,12 +1102,8 @@ accept2(graph *g, int n2, int x, graph * { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif -#ifdef PRUNE2 - if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; -#endif + INSTRUMENT_VAR(a2succs); + DO_PRUNE2(gx,degx,n1,n2+1,maxn2); if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } @@ -1117,12 +1119,8 @@ accept2(graph *g, int n2, int x, graph * return FALSE; else if (code > 0 || numcells >= nx-4) { -#ifdef INSTRUMENT - ++a2succs; -#endif -#ifdef PRUNE2 - if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; -#endif + INSTRUMENT_VAR(a2succs); + DO_PRUNE2(gx,degx,n1,n2+1,maxn2); if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } @@ -1133,25 +1131,19 @@ accept2(graph *g, int n2, int x, graph * options.defaultptn = FALSE; active[0] = 0; -#ifdef INSTRUMENT - ++a2nauty; -#endif + INSTRUMENT_VAR(a2nauty); nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan); if (orbits[lab[n]] == orbits[n]) { -#ifdef INSTRUMENT - ++a2succs; -#endif -#ifdef PRUNE2 - if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; -#endif + INSTRUMENT_VAR(a2succs); + DO_PRUNE2(gx,degx,n1,n2+1,maxn2); if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } else return FALSE; -} +}) /**************************************************************************/ --- a/geng.c +++ b/geng.c @@ -703,8 +703,7 @@ gcomplement(graph *g, graph *gc, int n) /**********************************************************************/ -static boolean -distinvar(graph *g, int *invar, int n) +STATIC_POPCNTFUNC(boolean,distinvar,(graph *g, int *invar, int n), /* make distance invariant return FALSE if n-1 not maximal else return TRUE */ { @@ -734,7 +733,7 @@ distinvar(graph *g, int *invar, int n) if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; -} +}) /**************************************************************************/ @@ -1174,9 +1173,9 @@ userautomprocb(int count, int *p, int *o * * *****************************************************************************/ -static void -refinex(graph *g, int *lab, int *ptn, int level, int *numcells, - int *count, set *active, boolean goodret, int *code, int m, int n) +STATIC_POPCNTFUNC(void,refinex, + (graph *g, int *lab, int *ptn, int level, int *numcells, + int *count, set *active, boolean goodret, int *code, int m, int n), { int i,c1,c2,labc1; setword x,lact; @@ -1307,7 +1306,7 @@ refinex(graph *g, int *lab, int *ptn, in } } } -} +}) /**************************************************************************/ @@ -1540,9 +1539,22 @@ accept1b(graph *g, int n, xword x, graph } /**************************************************************************/ +#ifdef INSTRUMENT +#define INSTRUMENT_VAR(var) ++var +#define INSTRUMENT_UNIQ(var) if (nuniq) ++var +#else +#define INSTRUMENT_VAR(var) +#define INSTRUMENT_UNIQ(var) +#endif -static boolean -accept2(graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq) +#ifdef PREPRUNE +#define DO_PREPRUNE(a,b,c) if (PREPRUNE(a,b,c)) return FALSE +#else +#define DO_PREPRUNE(a,b,c) +#endif + +STATIC_POPCNTFUNC(boolean,accept2, + (graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq), /* decide if n in theta(g+x) -- version for n+1 == maxn */ { int i; @@ -1560,10 +1572,8 @@ accept2(graph *g, int n, xword x, graph setword workspace[50]; boolean cheapacc; -#ifdef INSTRUMENT - ++a2calls; - if (nuniq) ++a2uniq; -#endif + INSTRUMENT_VAR(a2calls); + INSTRUMENT_UNIQ(a2uniq); nx = n + 1; for (i = 0; i < n; ++i) { @@ -1583,15 +1593,11 @@ accept2(graph *g, int n, xword x, graph ++degx[i]; } -#ifdef PREPRUNE - if (PREPRUNE(gx,n+1,maxn)) return FALSE; -#endif + DO_PREPRUNE(gx,n+1,maxn); if (nuniq) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1631,9 +1637,7 @@ accept2(graph *g, int n, xword x, graph { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1676,9 +1680,7 @@ accept2(graph *g, int n, xword x, graph { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1718,9 +1720,7 @@ accept2(graph *g, int n, xword x, graph if (cheapacc) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1729,22 +1729,18 @@ accept2(graph *g, int n, xword x, graph options.defaultptn = FALSE; active[0] = 0; -#ifdef INSTRUMENT - ++a2nauty; -#endif + INSTRUMENT_VAR(a2nauty); nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan); if (orbits[lab[n]] == orbits[n]) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } else return FALSE; -} +}) /**************************************************************************/ --- a/genquarticg.c +++ b/genquarticg.c @@ -228,9 +228,9 @@ isbiconnected(graph *g, int n) * of the graph reaches nmax after which it is written to outputfile * ****************************************************************************/ -static void -extend(int n, graph *g, edgestruct *edge, pairstruct *epair, int numpair, - int *epairorbit, int *multar, setword *zar, int *col00w, boolean connectflag) +STATIC_POPCNTFUNC(void,extend, + (int n, graph *g, edgestruct *edge, pairstruct *epair, int numpair, + int *epairorbit, int *multar, setword *zar, int *col00w, boolean connectflag), { int vm1, vm2, vm3, vm4, vt1, vt2, vt3, vt4, c, b, mcol1, mcol, tcol, got_one, i, j, k, numpair1, numdovi, maxdovi, i1, j1, i2, j2, @@ -916,7 +916,7 @@ extend(int n, graph *g, edgestruct *edge } //end for c.. -} +}) /***************************************************************************** * * @@ -1160,9 +1160,9 @@ init_refinex( int *clr, int *lb, int *p, * code := -1 for n-1 not max, 0 for maybe, 1 for definite * * * *****************************************************************************/ -static void -refinex(graph *g, int *lab, int *ptn, int level, int *numcells, int *count, - set *active, boolean goodret, int *code, int m, int n) +STATIC_POPCNTFUNC(void,refinex, + (graph *g, int *lab, int *ptn, int level, int *numcells, int *count, + set *active, boolean goodret, int *code, int m, int n), { int i, c1, c2, labc1, split1, split2, cell1, cell2, cnt, bmin, bmax; int workperm[MAXN], bucket[MAXN+2]; @@ -1290,7 +1290,7 @@ refinex(graph *g, int *lab, int *ptn, in } } } -} +}) /*****************************************************************************/ --- a/gentourng.c +++ b/gentourng.c @@ -547,9 +547,9 @@ userautomproc(int count, int *p, int *or * * *****************************************************************************/ -static void -refinex(graph *g, int *lab, int *ptn, int level, int *numcells, - int *count, set *active, boolean goodret, int *code, int m, int n) +STATIC_POPCNTFUNC(void,refinex, + (graph *g, int *lab, int *ptn, int level, int *numcells, + int *count, set *active, boolean goodret, int *code, int m, int n), { int i,c1,c2,labc1; setword x,lact; @@ -681,7 +681,7 @@ refinex(graph *g, int *lab, int *ptn, in } } } -} +}) /**************************************************************************/ @@ -803,8 +803,7 @@ accept1(graph *g, int n, xword x, graph /**************************************************************************/ -static boolean -hitinvar(graph *g, int *invar, int n) +STATIC_POPCNTFUNC(boolean,hitinvar,(graph *g, int *invar, int n), /* make hitting invariant * return FALSE if n-1 not maximal else return TRUE */ { @@ -827,12 +826,26 @@ hitinvar(graph *g, int *invar, int n) if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; -} +}) /**************************************************************************/ -static boolean -accept2(graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq) +#ifdef INSTRUMENT +#define INSTRUMENT_VAR(var) ++var +#define INSTRUMENT_UNIQ(var) if (nuniq) ++var +#else +#define INSTRUMENT_VAR(var) +#define INSTRUMENT_UNIQ(var) +#endif + +#ifdef PREPRUNE +#define DO_PREPRUNE(a,b,c) if (PREPRUNE(a,b,c)) return FALSE +#else +#define DO_PREPRUNE(a,b,c) +#endif + +STATIC_POPCNTFUNC(boolean,accept2, + (graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq), /* decide if n in theta(g+x) -- version for n+1 == maxn */ { int i; @@ -849,10 +862,8 @@ accept2(graph *g, int n, xword x, graph setword workspace[50]; boolean cheapacc; -#ifdef INSTRUMENT - ++a2calls; - if (nuniq) ++a2uniq; -#endif + INSTRUMENT_VAR(a2calls); + INSTRUMENT_UNIQ(a2uniq); nx = n + 1; gxn = 0; @@ -873,15 +884,11 @@ accept2(graph *g, int n, xword x, graph gx[n] = gxn; degx[n] = degn = XPOPCOUNT(x); -#ifdef PREPRUNE - if (PREPRUNE(gx,n+1,maxn)) return FALSE; -#endif + DO_PREPRUNE(gx,n+1,maxn); if (nuniq) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -920,9 +927,7 @@ accept2(graph *g, int n, xword x, graph { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -965,9 +970,7 @@ accept2(graph *g, int n, xword x, graph { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -986,9 +989,7 @@ accept2(graph *g, int n, xword x, graph if (cheapacc) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -998,22 +999,18 @@ accept2(graph *g, int n, xword x, graph options.defaultptn = FALSE; active[0] = 0; -#ifdef INSTRUMENT - ++a2nauty; -#endif + INSTRUMENT_VAR(a2nauty); nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan); if (orbits[lab[n]] == orbits[n]) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } else return FALSE; -} +}) /**************************************************************************/ --- a/gutil1.c +++ b/gutil1.c @@ -5,9 +5,9 @@ /**************************************************************************/ -void -degstats(graph *g, int m, int n, unsigned long *edges, int *mindeg, - int *mincount, int *maxdeg, int *maxcount, boolean *eulerian) +POPCNTFUNC(void,degstats, + (graph *g, int m, int n, unsigned long *edges, int *mindeg, + int *mincount, int *maxdeg, int *maxcount, boolean *eulerian), /* Compute degree-related graph properties. *edges = number of edges *mindeg, *mincount = minimum degree and how many there are @@ -60,16 +60,16 @@ degstats(graph *g, int m, int n, unsigne *maxcount = maxdc; *edges = ned / 2; *eulerian = (dor & 1) == 0; -} +}) /**************************************************************************/ -void -degstats2(graph *g, boolean digraph, int m, int n, +POPCNTFUNC(void,degstats2, + (graph *g, boolean digraph, int m, int n, unsigned long *edges, int *loops, int *minindeg, int *minincount, int *maxindeg, int *maxincount, int *minoutdeg, int *minoutcount, int *maxoutdeg, int *maxoutcount, - boolean *eulerian) + boolean *eulerian), /* Compute degree-related graph properties. *edges = number of edges (including loops), directed edges for digraphs *loops = number of loops @@ -232,12 +232,11 @@ degstats2(graph *g, boolean digraph, int if (indeg[i] != outdeg[i]) break; *eulerian = (i == n); } -} +}) /*********************************************************************/ -boolean -isconnected1(graph *g, int n) +POPCNTFUNC(boolean,isconnected1,(graph *g, int n), /* test if g is connected (m=1) */ { setword seen,expanded,toexpand; @@ -254,7 +253,7 @@ isconnected1(graph *g, int n) } return POPCOUNT(seen) == n; -} +}) /**************************************************************************/ @@ -304,24 +303,18 @@ isconnected(graph *g, int m, int n) /**************************************************************************/ -boolean -issubconnected(graph *g, set *sub, int m, int n) +POPCNTFUNC(boolean,issubconnected,(graph *g, set *sub, int m, int n), /* Test if the subset of g induced by sub is connected. Empty is connected. */ { int i,head,tail,w,subsize; set *gw; -#if MAXN - int queue[MAXN],visited[MAXN]; - setword subw[MAXM]; -#else - DYNALLSTAT(int,queue,queue_sz); - DYNALLSTAT(int,visited,visited_sz); - DYNALLSTAT(set,subw,subw_sz); + DCL_DYNINT(queue); + DCL_DYNINT(visited); + DCL_DYNSET(subw); - DYNALLOC1(int,queue,queue_sz,n,"issubconnected"); - DYNALLOC1(int,visited,visited_sz,n,"issubconnected"); - DYNALLOC1(set,subw,subw_sz,m,"issubconnected"); -#endif + DEF_DYNINT(queue,n,"issubconnected"); + DEF_DYNINT(visited,n,"issubconnected"); + DEF_DYNSET(subw,m,"issubconnected"); subsize = 0; for (i = 0; i < m; ++i) subsize += (sub[i] ? POPCOUNT(sub[i]) : 0); @@ -353,7 +346,7 @@ issubconnected(graph *g, set *sub, int m } return tail == subsize; -} +}) /**********************************************************************/ --- a/gutil2.c +++ b/gutil2.c @@ -21,8 +21,7 @@ loopcount(graph *g, int m, int n) /**************************************************************************/ -long -pathcount1(graph *g, int start, setword body, setword last) +POPCNTFUNC(long,pathcount1,(graph *g, int start, setword body, setword last), /* Number of paths in g starting at start, lying within body and ending in last. {start} and last should be disjoint subsets of body. */ { @@ -43,7 +42,7 @@ pathcount1(graph *g, int start, setword } return count; -} +}) /**************************************************************************/ @@ -86,8 +85,7 @@ cyclecount(graph *g, int m, int n) /**************************************************************************/ -long -indpathcount1(graph *g, int start, setword body, setword last) +POPCNTFUNC(long,indpathcount1,(graph *g, int start, setword body, setword last), /* Number of induced paths in g starting at start, extravertices within * body and ending in last. * {start}, body and last should be disjoint. */ @@ -108,7 +106,7 @@ indpathcount1(graph *g, int start, setwo } return count; -} +}) /**************************************************************************/ @@ -153,8 +151,7 @@ indcyclecount(graph *g, int m, int n) /**************************************************************************/ -long -numtriangles1(graph *g, int n) +POPCNTFUNC(long,numtriangles1,(graph *g, int n), /* The number of triangles in g */ { int i,j; @@ -174,12 +171,11 @@ numtriangles1(graph *g, int n) } return total; -} +}) /**************************************************************************/ -long -numtriangles(graph *g, int m, int n) +POPCNTFUNC(long,numtriangles,(graph *g, int m, int n), /* The number of triangles in g */ { int i,j,k,kw; @@ -204,7 +200,7 @@ numtriangles(graph *g, int m, int n) } return total; -} +}) /**************************************************************************/ @@ -230,9 +226,8 @@ numdirtriangles(graph *g, int m, int n) /**************************************************************************/ -void -commonnbrs(graph *g, int *minadj, int *maxadj, int *minnon, int *maxnon, - int m, int n) +POPCNTFUNC(void,commonnbrs, + (graph *g, int *minadj, int *maxadj, int *minnon, int *maxnon, int m, int n), /* Count the common neighbours of pairs of vertices, and give the minimum and maximum for adjacent and non-adjacent vertices. Undirected only. Null minimums are n+1 and null maximums are -1. @@ -273,7 +268,7 @@ commonnbrs(graph *g, int *minadj, int *m *maxadj = maxa; *minnon = minn; *maxnon = maxn; -} +}) /**************************************************************************/ @@ -342,8 +337,7 @@ contract1(graph *g, graph *h, int v, int static TLS_ATTR int knm[18][16]; /* knm[n,m] = conncontent(K_n - m*K_2) */ static TLS_ATTR boolean knm_computed = FALSE; -int -conncontent(graph *g, int m, int n) +POPCNTFUNC(int,conncontent,(graph *g, int m, int n), /* number of connected spanning subgraphs with an even number of edges minus the number with an odd number of edges */ { @@ -403,14 +397,6 @@ conncontent(graph *g, int m, int n) if (mindeg == 0) return 0; -#if 0 - if (mindeg == 1 && ne == n-1) - { - if (isconnected1(g,n)) return ((n&1) ? 1 : -1); - else return 0; - } -#endif - /* Cases of clique and near-clique */ if (mindeg == n-1) @@ -494,7 +480,7 @@ conncontent(graph *g, int m, int n) v2 = conncontent(h,m,n-1); return v1 - v2; -} +}) boolean stronglyconnected(graph *g, int m, int n) --- a/listg.c +++ b/listg.c @@ -252,8 +252,8 @@ putcgraph(FILE *f, graph *g, int linelen /**************************************************************************/ -static void -putve(FILE *f, unsigned long id, graph *g, boolean digraph, int m, int n) +STATIC_POPCNTFUNC(void,putve, + (FILE *f, unsigned long id, graph *g, boolean digraph, int m, int n), /* Write the numbers of vertices and edges */ { unsigned long ne; @@ -265,7 +265,7 @@ putve(FILE *f, unsigned long id, graph * fprintf(f,"Graph %lu has %d vertices and %lu edges.\n",id,n, (digraph?ne:ne/2)); -} +}) /**************************************************************************/ @@ -326,8 +326,8 @@ putdotty(FILE *f, graph *g, unsigned lon /**************************************************************************/ -static void -putbliss(FILE *f, unsigned long id, graph *g, int m, int n) +STATIC_POPCNTFUNC(void,putbliss, + (FILE *f, unsigned long id, graph *g, int m, int n), /* Write the graph in Bliss format, according to * http://www.tcs.hut.fi/Software/bliss/fileformat.shtml */ { @@ -346,7 +346,7 @@ putbliss(FILE *f, unsigned long id, grap for (i = 0, pg = g; i < n; ++i, pg += m) for (j = nextelement(pg,m,i); j >= 0; j = nextelement(pg,m,j)) fprintf(f,"e %d %d\n",i+1,j+1); -} +}) /**************************************************************************/ --- a/multig.c +++ b/multig.c @@ -442,6 +442,18 @@ scan_reg(int level, int ne, long minedge /**************************************************************************/ +STATIC_POPCNTFUNC(int __attribute__((pure)),compute_degree, + (const set *gi, int m), +{ + int i, thisdeg; + + thisdeg = 0; + for (i = 0; i < m; ++i) thisdeg += POPCOUNT(gi[i]); + return thisdeg; +}) + +/**************************************************************************/ + static void multi(graph *g, int nfixed, long minedges, long maxedges, long maxmult, int maxdeg, boolean lswitch, int m, int n) @@ -469,8 +481,7 @@ multi(graph *g, int nfixed, long minedge maxd = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { - thisdeg = 0; - for (j = 0; j < m; ++j) thisdeg += POPCOUNT(gi[j]); + thisdeg = compute_degree(gi, m); deg[i] = thisdeg; if (thisdeg > maxd) maxd = thisdeg; if (thisdeg == 0) lab[++j0] = i; --- a/naugraph.c +++ b/naugraph.c @@ -173,16 +173,17 @@ updatecan(graph *g, graph *canong, int * * * *****************************************************************************/ +#if MAXM==1 void refine(graph *g, int *lab, int *ptn, int level, int *numcells, int *count, set *active, int *code, int m, int n) { - -#if MAXM==1 refine1(g,lab,ptn,level,numcells,count,active,code,m,n); } #else - +POPCNTFUNC(void,refine,(graph *g, int *lab, int *ptn, int level, int *numcells, + int *count, set *active, int *code, int m, int n), +{ int i,c1,c2,labc1; setword x; set *set1,*set2; @@ -192,11 +193,9 @@ refine(graph *g, int *lab, int *ptn, int set *gptr; int maxcell,maxpos,hint; -#if !MAXN - DYNALLOC1(int,workperm,workperm_sz,n,"refine"); - DYNALLOC1(set,workset,workset_sz,m,"refine"); - DYNALLOC1(int,bucket,bucket_sz,n+2,"refine"); -#endif + DEF_DYNINT(workperm,n,"refine"); + DEF_DYNSET(workset,m,"refine"); + DEF_DYNINT(bucket,n+2,"refine"); longcode = *numcells; split1 = -1; @@ -324,7 +323,7 @@ refine(graph *g, int *lab, int *ptn, int longcode = MASH(longcode,*numcells); *code = CLEANUP(longcode); -} +}) #endif /* else case of MAXM==1 */ /***************************************************************************** @@ -336,9 +335,8 @@ refine(graph *g, int *lab, int *ptn, int * * *****************************************************************************/ -void -refine1(graph *g, int *lab, int *ptn, int level, int *numcells, - int *count, set *active, int *code, int m, int n) +POPCNTFUNC(void,refine1,(graph *g, int *lab, int *ptn, int level, + int *numcells, int *count, set *active, int *code, int m, int n), { int i,c1,c2,labc1; setword x; @@ -348,10 +346,8 @@ refine1(graph *g, int *lab, int *ptn, in set *gptr,workset0; int maxcell,maxpos,hint; -#if !MAXN - DYNALLOC1(int,workperm,workperm_sz,n,"refine1"); - DYNALLOC1(int,bucket,bucket_sz,n+2,"refine1"); -#endif + DEF_DYNINT(workperm,n,"refine1"); + DEF_DYNINT(bucket,n+2,"refine1"); longcode = *numcells; split1 = -1; @@ -474,7 +470,7 @@ refine1(graph *g, int *lab, int *ptn, in longcode = MASH(longcode,*numcells); *code = CLEANUP(longcode); -} +}) /***************************************************************************** * * --- a/nausparse.c +++ b/nausparse.c @@ -1473,8 +1473,7 @@ copy_sg(sparsegraph *sg1, sparsegraph *s * * *****************************************************************************/ -sparsegraph* -nauty_to_sg(graph *g, sparsegraph *sg, int m, int n) +POPCNTFUNC(sparsegraph*,nauty_to_sg,(graph *g, sparsegraph *sg, int m, int n), { int *d,*e; int i,k; @@ -1512,7 +1511,7 @@ nauty_to_sg(graph *g, sparsegraph *sg, i } return sg; -} +}) /***************************************************************************** * * --- a/nautinv.c +++ b/nautinv.c @@ -221,6 +221,19 @@ twopaths(graph *g, int *lab, int *ptn, i } } +STATIC_POPCNTFUNC(int __attribute__((pure)),disjoint_edges, + (const set *ws, const set *gw, int m), +{ + int i,pc; + setword sw; + + pc = 0; + for (i = M; --i >= 0;) + if ((sw = ws[i] ^ gw[i]) != 0) + pc += POPCOUNT(sw); + return pc; +}) + /***************************************************************************** * * * quadruples() assigns to each vertex v a value depending on the set of * @@ -236,7 +249,6 @@ quadruples(graph *g, int *lab, int *ptn, int *invar, int invararg, boolean digraph, int m, int n) { int i,pc; - setword sw; set *gw; int wt; int v,iv,v1,v2,v3; @@ -284,9 +296,7 @@ quadruples(graph *g, int *lab, int *ptn, if (wv3 == wv && v3 <= v) continue; wv3 += wv2; gw = GRAPHROW(g,v3,m); - pc = 0; - for (i = M; --i >= 0;) - if ((sw = ws1[i] ^ gw[i]) != 0) pc += POPCOUNT(sw); + pc = disjoint_edges(ws1,gw,m); wt = (FUZZ1(pc)+wv3) & 077777; wt = FUZZ2(wt); ACCUM(invar[v],wt); @@ -315,7 +325,6 @@ triples(graph *g, int *lab, int *ptn, in int *invar, int invararg, boolean digraph, int m, int n) { int i,pc; - setword sw; set *gw; int wt; int v,iv,v1,v2; @@ -355,9 +364,7 @@ triples(graph *g, int *lab, int *ptn, in if (wv2 == wv && v2 <= v) continue; wv2 += wv1; gw = GRAPHROW(g,v2,m); - pc = 0; - for (i = M; --i >= 0;) - if ((sw = workset[i] ^ gw[i]) != 0) pc += POPCOUNT(sw); + pc = disjoint_edges(workset,gw,m); wt = (FUZZ1(pc)+wv2) & 077777; wt = FUZZ2(wt); ACCUM(invar[v],wt); @@ -382,8 +389,7 @@ void adjtriang(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, int *invar, int invararg, boolean digraph, int m, int n) { - int j,pc; - setword sw; + int pc; set *gi; int wt; int i,v1,v2; @@ -421,10 +427,8 @@ adjtriang(graph *g, int *lab, int *ptn, i = -1; while ((i = nextelement(workset,M,i)) >= 0) { - pc = 0; gi = GRAPHROW(g,i,m); - for (j = M; --j >= 0;) - if ((sw = workset[j] & gi[j]) != 0) pc += POPCOUNT(sw); + pc = disjoint_edges(workset,gi,m); pc = (pc + wt) & 077777; ACCUM(invar[i],pc); } @@ -509,7 +513,6 @@ celltrips(graph *g, int *lab, int *ptn, int *invar, int invararg, boolean digraph, int m, int n) { int i,pc; - setword sw; set *gw; int wt; int v,iv,v1,iv1,v2,iv2; @@ -545,10 +548,7 @@ celltrips(graph *g, int *lab, int *ptn, { v2 = lab[iv2]; gw = GRAPHROW(g,v2,m); - pc = 0; - for (i = M; --i >= 0;) - if ((sw = workset[i] ^ gw[i]) != 0) - pc += POPCOUNT(sw); + pc = disjoint_edges(workset,gw,m); wt = FUZZ1(pc); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); @@ -577,7 +577,6 @@ cellquads(graph *g, int *lab, int *ptn, int *invar, int invararg, boolean digraph, int m, int n) { int i,pc; - setword sw; set *gw; int wt; int v,iv,v1,iv1,v2,iv2,v3,iv3; @@ -619,10 +618,7 @@ cellquads(graph *g, int *lab, int *ptn, { v3 = lab[iv3]; gw = GRAPHROW(g,v3,m); - pc = 0; - for (i = M; --i >= 0;) - if ((sw = ws1[i] ^ gw[i]) != 0) - pc += POPCOUNT(sw); + pc = disjoint_edges(ws1,gw,m); wt = FUZZ1(pc); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); @@ -653,7 +649,6 @@ cellquins(graph *g, int *lab, int *ptn, int *invar, int invararg, boolean digraph, int m, int n) { int i,pc; - setword sw; set *gw; int wt; int v,iv,v1,iv1,v2,iv2,v3,iv3,v4,iv4; @@ -701,10 +696,7 @@ cellquins(graph *g, int *lab, int *ptn, { v4 = lab[iv4]; gw = GRAPHROW(g,v4,m); - pc = 0; - for (i = M; --i >= 0;) - if ((sw = ws2[i] ^ gw[i]) != 0) - pc += POPCOUNT(sw); + pc = disjoint_edges(ws2,gw,m); wt = FUZZ1(pc); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); @@ -749,6 +741,21 @@ uniqinter(set *s1, set *s2, int m) return -1; } +STATIC_POPCNTFUNC(int __attribute__((pure)),triedges, + (const set *s0, const set *s1, const set *s2, int m), +{ + int i,pc; + setword sw; + + pc = 0; + for (i = M; --i >= 0;) + { + sw = s0[i] & s1[i] & s2[i]; + if (sw) pc += POPCOUNT(sw); + } + return pc; +}) + /***************************************************************************** * * * cellfano2() assigns to each vertex v a value depending on the set of * @@ -765,7 +772,6 @@ cellfano2(graph *g, int *lab, int *ptn, int *invar, int invararg, boolean digraph, int m, int n) { int i,pc; - setword sw; int wt; int v0,v1,v2,v3,iv0,iv1,iv2,iv3; int icell,bigcells,cell1,cell2; @@ -847,12 +853,7 @@ cellfano2(graph *g, int *lab, int *ptn, gp1 = GRAPHROW(g,pnt1,m); gp2 = GRAPHROW(g,pnt2,m); - pc = 0; - for (i = M; --i >= 0;) - { - sw = gp0[i] & gp1[i] & gp2[i]; - if (sw) pc += POPCOUNT(sw); - } + pc = triedges(gp0,gp1,gp2,m); wt = FUZZ1(pc); ACCUM(invar[v0],wt); ACCUM(invar[v1],wt); @@ -914,7 +915,6 @@ cellfano(graph *g, int *lab, int *ptn, i int *invar, int invararg, boolean digraph, int m, int n) { int i,pc; - setword sw; int wt; int v0,v1,v2,v3,iv0,iv1,iv2,iv3; int icell,bigcells,cell1,cell2; @@ -989,12 +989,7 @@ cellfano(graph *g, int *lab, int *ptn, i setnbhd(g,m,n,workset,pt1); for (i = M; --i >= 0;) workset[i] = w02[i] & w13[i]; setnbhd(g,m,n,workset,pt2); - pc = 0; - for (i = M; --i >= 0;) - { - sw = pt0[i] & pt1[i] & pt2[i]; - if (sw) pc += POPCOUNT(sw); - } + pc = triedges(pt0,pt1,pt2,m); wt = FUZZ1(pc); ACCUM(invar[v0],wt); ACCUM(invar[v1],wt); @@ -1238,6 +1233,20 @@ cliques(graph *g, int *lab, int *ptn, in } } +STATIC_POPCNTFUNC(int,common_edges,(set *ns, const set *gv, int m), +{ + int i,pc; + setword sw; + + pc = 0; + for (i = M; --i >= 0;) + { + ns[i] = gv[i] & workset[i]; + if ((sw = ns[i]) != 0) pc += POPCOUNT(sw); + } + return pc; +}) + /***************************************************************************** * * * cellcliq() assigns to each vertex v a value depending on the number of * @@ -1260,7 +1269,6 @@ cellcliq(graph *g, int *lab, int *ptn, i int *cellstart,*cellsize; int iv,icell,bigcells,cell1,cell2; int pc; - setword sw; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"cellcliq"); @@ -1293,13 +1301,7 @@ cellcliq(graph *g, int *lab, int *ptn, i v[0] = lab[iv]; gv = GRAPHROW(g,v[0],m); ns = (set*)wss; - pc = 0; - - for (i = M; --i >= 0;) - { - ns[i] = gv[i] & workset[i]; - if ((sw = ns[i]) != 0) pc += POPCOUNT(sw); - } + pc = common_edges(ns,gv,m); if (pc <= 1 || pc >= cellsize[icell] - 2) continue; ss = 1; @@ -1333,6 +1335,20 @@ cellcliq(graph *g, int *lab, int *ptn, i } } +STATIC_POPCNTFUNC(int,not_common_edges,(set *ns, const set *gv, int m), +{ + int i,pc; + setword sw; + + pc = 0; + for (i = M; --i >= 0;) + { + ns[i] = ~gv[i] & workset[i]; + if ((sw = ns[i]) != 0) pc += POPCOUNT(sw); + } + return pc; +}) + /***************************************************************************** * * * cellind() assigns to each vertex v a value depending on the number of * @@ -1389,13 +1405,7 @@ cellind(graph *g, int *lab, int *ptn, in v[0] = lab[iv]; gv = GRAPHROW(g,v[0],m); ns = (set*)wss; - pc = 0; - - for (i = M; --i >= 0;) - { - ns[i] = ~gv[i] & workset[i]; - if ((sw = ns[i]) != 0) pc += POPCOUNT(sw); - } + pc = not_common_edges(ns,gv,m); if (pc <= 1 || pc >= cellsize[icell] - 2) continue; ss = 1; @@ -1554,9 +1564,9 @@ nautinv_freedyn(void) * * *****************************************************************************/ -static int -semirefine(graph *g, int *lab, int *ptn, int level, int *numcells, - int strength, set *active, int m, int n) +STATIC_POPCNTFUNC(int,semirefine, + (graph *g, int *lab, int *ptn, int level, int *numcells, + int strength, set *active, int m, int n), { int i,c1,c2,labc1; setword x; @@ -1567,12 +1577,10 @@ semirefine(graph *g, int *lab, int *ptn, set *gptr; int maxcell,maxpos,hint; -#if !MAXN - DYNALLOC1(int,workperm,workperm_sz,n,"refine"); - DYNALLOC1(set,workset,workset_sz,m,"refine"); - DYNALLOC1(int,bucket,bucket_sz,n+2,"refine"); - DYNALLOC1(int,count,count_sz,n,"refine"); -#endif + DEF_DYNINT(workperm,n,"refine"); + DEF_DYNSET(workset,m,"refine"); + DEF_DYNINT(bucket,n+2,"refine"); + DEF_DYNINT(count,n,"refine"); longcode = *numcells; split1 = -1; @@ -1700,7 +1708,7 @@ semirefine(graph *g, int *lab, int *ptn, longcode = MASH(longcode,FUZZ2(*numcells)); return CLEANUP(longcode); -} +}) void refinvar(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, --- a/naututil.c +++ b/naututil.c @@ -134,15 +134,18 @@ static const long fuzz2[] = {2001381726L * * *****************************************************************************/ -int -setinter(set *set1, set *set2, int m) +#if MAXM==1 +POPCNTFUNC(int,setinter,(set *set1, set *set2, int m), { setword x; -#if MAXM==1 if ((x = *set1 & *set2) != 0) return POPCOUNT(x); else return 0; +}) #else +POPCNTFUNC(int,setinter,(set *set1, set *set2, int m), +{ + setword x; int count,i; count = 0; @@ -154,8 +157,8 @@ setinter(set *set1, set *set2, int m) } return count; +}) #endif -} /***************************************************************************** * * @@ -163,14 +166,15 @@ setinter(set *set1, set *set2, int m) * * *****************************************************************************/ -int -setsize(set *set1, int m) -{ - #if MAXM==1 +POPCNTFUNC(int,setsize,(set *set1, int m), +{ if (set1 != 0) return POPCOUNT(*set1); else return 0; +}) #else +POPCNTFUNC(int,setsize,(set *set1, int m), +{ int count,i; setword x; @@ -179,8 +183,8 @@ setsize(set *set1, int m) if ((x = *set1++) != 0) count += POPCOUNT(x); return count; +}) #endif -} /***************************************************************************** * * --- a/nauty-h.in +++ b/nauty-h.in @@ -66,6 +66,7 @@ it is necessary to check they are correc #define HAVE_POPCNTLL @have_popcntll@ #define HAVE_MMPOP32 @have_mmpop32@ #define HAVE_MMPOP64 @have_mmpop64@ +#define RUNTIME_POPCNT @runtime_popcnt@ /*==================================================================*/ @@ -763,7 +764,7 @@ typedef unsigned long nauty_counter; /* Note that, unlike icc, gcc will not use the POPCNT instruction without permission, in which case it defines __POPCNT__ . */ -#ifdef __POPCNT__ +#if defined(__POPCNT__) || RUNTIME_POPCNT #if defined(SETWORD_LONGLONG) && HAVE_POPCNTLL #undef POPCOUNT #define POPCOUNT(x) __builtin_popcountll(x) @@ -779,6 +780,47 @@ typedef unsigned long nauty_counter; #endif #endif +/* Determine popcount support at runtime */ +#if RUNTIME_POPCNT +#if !defined(__x86_64__) && !defined(__i386__) +#error Runtime popcount support is only available on x86 or x86_64. +#endif +#ifndef __GNUC__ +#error Runtime popcount support is only available with GCC. +#endif +#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) +#error Runtime popcount support is only available with GCC 4.6 or later. +#endif +#include + +#define SLOWPOPCNT(type,name,params,...) \ + static type slow_##name params __VA_ARGS__ +#define FASTPOPCNT(type,name,params,...) \ + static type __attribute__((target ("popcnt"))) fast_##name params \ + __VA_ARGS__ +#define POPCNTHDR(type,name,params,...) \ + SLOWPOPCNT(type,name,params,__VA_ARGS__) \ + FASTPOPCNT(type,name,params,__VA_ARGS__) \ + static void __attribute__((optimize ("O0"))) \ + (*resolve_##name (void))(void) { \ + unsigned int eax, ebx, ecx, edx; \ + return (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && \ + (ecx & bit_POPCNT) != 0) \ + ? (void (*)(void))&fast_##name \ + : (void (*)(void))&slow_##name; \ + } +#define POPCNTFUNC(type,name,params,...) \ + POPCNTHDR(type,name,params,__VA_ARGS__) \ + type __attribute__((ifunc ("resolve_" #name))) name params; +#define STATIC_POPCNTFUNC(type,name,params,...) \ + POPCNTHDR(type,name,params,__VA_ARGS__) \ + static type __attribute__((ifunc ("resolve_" #name))) name params; +#else +#define POPCNTFUNC(type,name,params,...) type name params __VA_ARGS__ +#define STATIC_POPCNTFUNC(type,name,params,...) \ + static type name params __VA_ARGS__ +#endif + #ifdef NAUTY_IN_MAGMA #undef POPCOUNT #undef FIRSTBIT @@ -1035,6 +1077,18 @@ extern void free(void*); #define CONDYNFREE(name,name_sz,minsz) \ if (name_sz > (size_t)(minsz)) {DYNFREE(name,name_sz);} +#if MAXN +#define DCL_DYNINT(var) int var[MAXN] +#define DCL_DYNSET(var) setword var[MAXM] +#define DEF_DYNINT(var,n,name) +#define DEF_DYNSET(var,n,name) +#else +#define DCL_DYNINT(var) DYNALLSTAT(int,var,var##_sz) +#define DCL_DYNSET(var) DYNALLSTAT(set,var,var##_sz) +#define DEF_DYNINT(var,n,name) DYNALLOC1(int,var,var##_sz,n,name) +#define DEF_DYNSET(var,n,name) DYNALLOC1(set,var,var##_sz,n,name) +#endif + /* File to write error messages to (used as first argument to fprintf()). */ #define ERRFILE stderr --- a/vcolg.c +++ b/vcolg.c @@ -130,6 +130,22 @@ testmax(int *p, int n, int *abort) /**************************************************************************/ +#ifndef OUTPROC +STATIC_POPCNTFUNC(size_t __attribute__((pure)),compute_degree, +(const graph *g, int m, int n), +{ + const graph *gi; + size_t ne; + + ne = 0; + for (gi = g + m*(size_t)n; --gi >= g; ) + ne += POPCOUNT(*gi); + return ne / 2; +}) +#endif + +/**************************************************************************/ + static int trythisone(grouprec *group, graph *g, int m, int n) /* Try one solution, accept if maximal. */ @@ -174,10 +190,7 @@ trythisone(grouprec *group, graph *g, in #ifdef OUTPROC OUTPROC(outfile,g,col,m,n); #else - ne = 0; - for (gi = g + m*(size_t)n; --gi >= g; ) - ne += POPCOUNT(*gi); - ne /= 2; + ne = compute_degree(g,m,n); fprintf(outfile,"%d %lu",n,(unsigned long)ne); for (i = 0; i < n; ++i) fprintf(outfile," %d",col[i]); --- a/watercluster2.c +++ b/watercluster2.c @@ -557,7 +557,7 @@ void decode_to_nauty(unsigned char *code /****************************************INIT_FOR_G6*****************************/ -void init_for_g6(graph g[],int aantal_toppen, int degree[]) +STATIC_POPCNTFUNC(void,init_for_g6,(graph g[],int aantal_toppen, int degree[]), { int i; @@ -569,7 +569,7 @@ void init_for_g6(graph g[],int aantal_to aantal_gerichte_bogen=0; return; -} +}) /***************************FILL_EDGELIST**************************/ @@ -1202,7 +1202,8 @@ void construct_operations_in(int list[], /**********************************CONSTRUCT_EXTENSIONS**************************/ -void construct_extensions(int still_open[], int orbit[], graph touched, int first_in_orbit, graph sameorbit) +STATIC_POPCNTFUNC(void,construct_extensions, + (int still_open[], int orbit[], graph touched, int first_in_orbit, graph sameorbit), { int top, top2, j, end, list[MAXN], decided[MAXN], error, lowerlimit_outdeg, readylist[MAXN], *readyrun, dummy; int minout, do_double=0, i, mindouble; @@ -1362,7 +1363,7 @@ for (number_operations=0; (top=(*still_o } } return; -} +}) int compare_op(unsigned char *op1, unsigned char *op2) // returns 0 if operations are the same, something negative if op1 @@ -1489,7 +1490,8 @@ void compute_edgeorbits(int edgelist[][2 /******************************CANONICAL****************************/ -int canonical(unsigned char operation[], int vertexorbit[], int *newgroup, int orbitid, graph touched) +STATIC_POPCNTFUNC(int,canonical, + (unsigned char operation[], int vertexorbit[], int *newgroup, int orbitid, graph touched), // checks whether the operation is canonical in vertexorbit. Returns 1 if yes, 0 otherwise. // In newgroup it is stored whether a new group has been computed for this (*newgroup=1) or not @@ -1786,7 +1788,7 @@ int canonical(unsigned char operation[], else { return 0; } -} +}) int all_diff_colours(graph testset, int orbitid) // returns 1 if all elements have some different vertex invariant and 0 otherwise @@ -3728,7 +3730,7 @@ int test_possible(graph globalg[],int gl -void waterclusters (graph g[], int n) +STATIC_POPCNTFUNC(void,waterclusters,(graph g[], int n), { int i, j, k, orbitsize, start, end, fixed_edge, dummy, maxgraphdeg, biggest_orbit; BOOG kleinste_orbit[MAX_BOGEN+1]; /* het is mogelijk dat er maar 1 orbit is */ @@ -3891,7 +3893,7 @@ void waterclusters (graph g[], int n) return; -} +})