Description: enable runtime detection of popcnt-enabled CPU Origin: fedora Author: Jerry James Last-Update: 2021-09-02 --- a/addedgeg.c +++ b/addedgeg.c @@ -74,6 +74,23 @@ } /*************************************************************************/ +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 @@ 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 @@ 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 @@ -51,6 +51,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 @@ -175,10 +186,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 @@ -79,6 +79,9 @@ AC_ARG_ENABLE([popcnt], AS_HELP_STRING([--disable-popcnt], [Disable popcnt extensions]), [enablearg=given], [enablearg=notgiven]) AS_IF([test $enablearg = notgiven || test "x$enable_popcnt" = xyes],[allow_popcnt=1],[allow_popcnt=0]) +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]) dnl --disable-clz disallows clz instructions, otherwise they are tested for AC_ARG_ENABLE([clz], @@ -328,7 +331,7 @@ have_popcntll=0 have_mmpop32=0 have_mmpop64=0 -AS_IF([test $have_hwpopcnt -eq 1], +AS_IF([test $have_hwpopcnt -eq 1 -a $runtime_popcnt -eq 0], [AS_IF([test "$CC" = "icc"], [AC_MSG_CHECKING(if _mm_popcnt_u32() is supported) AC_LINK_IFELSE([AC_LANG_SOURCE([#include @@ -363,6 +366,7 @@ AC_SUBST(have_popcntl) AC_SUBST(have_popcntll) AC_SUBST(have_mmpop32) AC_SUBST(have_mmpop64) +AC_SUBST(runtime_popcnt) # Unless --enable-generic is given to configure, we try to use the -march=native compiler # switch. However, it breaks some versions of gcc on MacOSX due to a compiler bug, so --- a/converseg.c +++ b/converseg.c @@ -39,8 +39,7 @@ /**************************************************************************/ -static boolean -isselfconverse(graph *g, int m, int n) +STATIC_POPCNTFUNC(boolean,isselfconverse,(graph *g, int m, int n), /* Test if self-converse */ { int i,j,deg; @@ -93,7 +92,7 @@ if (h[ij] != hc[ij]) return FALSE; return TRUE; -} + }) /**************************************************************************/ --- 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 @@ 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 @@ 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 @@ -34,6 +34,23 @@ static int outcode; static boolean digraph,dolabel; +/*************************************************************************/ + +STATIC_POPCNTFUNC(boolean,compute_degree, + (const graph *gx, int nx, int mx, int outmindeg), +{ + set *gxi; + int i,j,deg; + + for (i = 0, gxi = (set*)gx; i < nx; ++i, gxi += mx) + { + deg = 0; + for (j = 0; j < mx; ++j) deg += POPCOUNT(gxi[j]); + if (deg < outmindeg) return FALSE; + } + return TRUE; +}) + /**************************************************************************/ static void @@ -42,7 +59,7 @@ /* Delete the stated vertices and write it is mindeg is high enough. * The vertices to delete are del[0] < del[1] < ... < del[ndel-1]. */ { - int i,j,k,nx,mx,deg; + int i,j,k,nx,mx; graph *gi,*gxi,*gq; ssize_t ii; #if MAXN @@ -105,15 +122,8 @@ } } - if (outmindeg > 0) - { - for (i = 0, gxi = (set*)gx; i < nx; ++i, gxi += mx) - { - deg = 0; - for (j = 0; j < mx; ++j) deg += POPCOUNT(gxi[j]); - if (deg < outmindeg) return; - } - } + if (outmindeg > 0 && !compute_degree(gx,nx,mx,outmindeg)) + return; if (dolabel) { @@ -261,6 +271,26 @@ } } +/*************************************************************************/ + +STATIC_POPCNTFUNC(int,check_degree, + (const graph *g, int *okverts, int actmaxv, int iminv, int m, int n, + long mindeg, long maxdeg), +{ + const setword *gv; + int i,v,degv,nvok = 0; + + for (v = 0, gv = g; v < n && v <= actmaxv; ++v, gv += m) + { + if (v < iminv) continue; + degv = 0; + for (i = 0; i < m; ++i) degv += POPCOUNT(gv[i]); + if (degv < mindeg || degv > maxdeg) continue; + okverts[nvok++] = v; + } + return nvok; +}) + /**************************************************************************/ int @@ -270,17 +300,15 @@ FILE *infile; boolean badargs,quiet,dswitch,nswitch,vswitch,mswitch; boolean adj,nonadj,isolates,delrand; - int i,j,m,n,v,argnum; + int i,j,m,n,argnum; int ndel,outmindeg; int codetype; graph *g; nauty_counter nin; char *arg,sw; - setword *gv; long mindeg,maxdeg,irand,numrand; long minv,maxv; int iminv,imaxv,actmaxv,nvok; - int degv; double t; #if MAXN int okverts[MAXN]; @@ -443,15 +471,7 @@ EMPTYSET(avail,m); } - nvok = 0; - for (v = 0, gv = g; v < n && v <= actmaxv; ++v, gv += m) - { - if (v < iminv) continue; - degv = 0; - for (i = 0; i < m; ++i) degv += POPCOUNT(gv[i]); - if (degv < mindeg || degv > maxdeg) continue; - okverts[nvok++] = v; - } + nvok = check_degree(g, okverts, actmaxv, iminv, m, n, mindeg, maxdeg); if (nvok < ndel) { --- a/directg.c +++ b/directg.c @@ -581,6 +581,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 @@ -610,8 +620,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 @@ -475,8 +475,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 */ @@ -508,7 +507,7 @@ distinvar(graph *g, int *invar, int n1, if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; -} +}) /**************************************************************************/ @@ -664,10 +663,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; @@ -800,7 +799,7 @@ refinex(graph *g, int *lab, int *ptn, in } } } -} +}) /**************************************************************************/ @@ -948,9 +947,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; @@ -967,10 +985,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) @@ -990,18 +1006,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; } @@ -1050,12 +1060,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; } @@ -1106,12 +1112,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; } @@ -1127,12 +1129,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; } @@ -1143,25 +1141,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 @@ -620,8 +620,7 @@ return seen == allbits; } -static boolean -connpreprune(graph *g, int n, int maxn) +STATIC_POPCNTFUNC(boolean,connpreprune,(graph *g, int n, int maxn), /* This function speeds up the generation of connected graphs with not many edges. */ { @@ -653,7 +652,7 @@ if (ne - n + nc > maxe - maxn + 1) return TRUE; return FALSE; -} +}) /**********************************************************************/ @@ -720,8 +719,7 @@ /**********************************************************************/ -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 */ { @@ -751,7 +749,7 @@ if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; -} +}) /**************************************************************************/ @@ -965,8 +963,7 @@ /**************************************************************************/ -static void -makeleveldata(boolean restricted) +STATIC_POPCNTFUNC(void,makeleveldata,(boolean restricted), /* make the level data for each level */ { long h; @@ -1072,7 +1069,7 @@ if (xcard[i] > xcard[i-1]) d->xstart[xcard[i]] = i; d->xstart[xcard[nxsets-1]+1] = nxsets; } -} +}) /**************************************************************************/ @@ -1123,9 +1120,9 @@ /**************************************************************************/ -static void -userautomprocb(int count, int *p, int *orbits, - int numorbits, int stabvertex, int n) +STATIC_POPCNTFUNC(void, +userautomprocb,(int count, int *p, int *orbits, + int numorbits, int stabvertex, int n), /* form orbits on powerset of VG called by nauty; operates on data[n] */ { @@ -1189,7 +1186,7 @@ if (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1; else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2; } -} +}) /***************************************************************************** * * @@ -1202,9 +1199,9 @@ * * *****************************************************************************/ -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; @@ -1335,7 +1332,7 @@ } } } -} +}) /**************************************************************************/ @@ -1547,9 +1544,35 @@ } /**************************************************************************/ +#ifdef INSTRUMENT +#define INSTRUMENTED_VAR(var) boolean var = FALSE +#define INSTRUMENT_TRUE(var) var = TRUE +#define INSTRUMENT_VAR(var) ++var +#define INSTRUMENT_VAR_IF(var1,var2) if (var1) ++var2 +#else +#define INSTRUMENTED_VAR(var) +#define INSTRUMENT_TRUE(var) +#define INSTRUMENT_VAR(var) +#define INSTRUMENT_VAR_IF(var1,var2) +#endif -static boolean -accept1(graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid) +#ifdef PREPRUNE +#define DO_PREPRUNE(a,b,c) if (PREPRUNE(a,b,c)) return FALSE +#else +#define DO_PREPRUNE(a,b,c) +#endif + +#ifdef PRUNE +#define DO_PRUNE(a,b,c) if (PRUNE(a,b,c)) return +#define PRUNE_NOT(a,b,c) if (!PRUNE(a,b,c)) +#else +#define DO_PRUNE(a,b,c) +#define PRUNE_NOT(a,b,c) +#endif + + +STATIC_POPCNTFUNC(boolean,accept1, + (graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid), /* decide if n in theta(g+x) - version for n+1 < maxn */ { int i; @@ -1564,9 +1587,7 @@ static TLS_ATTR DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; -#ifdef INSTRUMENT - ++a1calls; -#endif + INSTRUMENT_VAR(a1calls); nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; @@ -1585,9 +1606,7 @@ if (k4free && hask4(gx,n+1,maxn)) return FALSE; if (clawfree && hasclaw(gx,n+1,maxn)) return FALSE; -#ifdef PREPRUNE - if (PREPRUNE(gx,n+1,maxn)) return FALSE; -#endif + DO_PREPRUNE(gx,n+1,maxn); if (connec == 2 && n+2 == maxn && !isconnected(gx,n+1)) return FALSE; if (((connec ==2 && n+2 < maxn) || (connec == 1 && n+2 <= maxn)) && connpreprune(gx,n+1,maxn)) return FALSE; @@ -1619,9 +1638,7 @@ if (numcells == nx) { *rigid = TRUE; -#ifdef INSTRUMENT - ++a1succs; -#endif + INSTRUMENT_VAR(a1succs); return TRUE; } @@ -1630,28 +1647,24 @@ options.userautomproc = userautomproc; active[0] = 0; -#ifdef INSTRUMENT - ++a1nauty; -#endif + INSTRUMENT_VAR(a1nauty); nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,h); if (orbits[lab[n]] == orbits[n]) { *rigid = stats.numorbits == nx; -#ifdef INSTRUMENT - ++a1succs; -#endif + INSTRUMENT_VAR(a1succs); return TRUE; } else return FALSE; -} +}) /**************************************************************************/ -static boolean -accept1b(graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid, - void (*makeh)(graph*,xword*,int)) +STATIC_POPCNTFUNC(boolean,accept1b, + (graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid, + void (*makeh)(graph*,xword*,int)), /* decide if n in theta(g+x) -- version for n+1 < maxn */ { int i,v; @@ -1667,9 +1680,7 @@ static TLS_ATTR DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; -#ifdef INSTRUMENT - ++a1calls; -#endif + INSTRUMENT_VAR(a1calls); nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; @@ -1688,9 +1699,7 @@ if (k4free && hask4(gx,n+1,maxn)) return FALSE; if (clawfree && hasclaw(gx,n+1,maxn)) return FALSE; -#ifdef PREPRUNE - if (PREPRUNE(gx,n+1,maxn)) return FALSE; -#endif + DO_PREPRUNE(gx,n+1,maxn); if (connec == 2 && n+2 == maxn && !isconnected(gx,n+1)) return FALSE; if (((connec ==2 && n+2 < maxn) || (connec == 1 && n+2 <= maxe)) && connpreprune(gx,n+1,maxn)) return FALSE; @@ -1742,9 +1751,7 @@ if (numcells == nx) { *rigid = TRUE; -#ifdef INSTRUMENT - ++a1succs; -#endif + INSTRUMENT_VAR(a1succs); return TRUE; } @@ -1753,27 +1760,23 @@ options.userautomproc = userautomprocb; active[0] = 0; -#ifdef INSTRUMENT - ++a1nauty; -#endif + INSTRUMENT_VAR(a1nauty); nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gc); if (orbits[lab[n]] == orbits[n]) { *rigid = stats.numorbits == nx; -#ifdef INSTRUMENT - ++a1succs; -#endif + INSTRUMENT_VAR(a1succs); return TRUE; } else return FALSE; -} +}) /**************************************************************************/ -static boolean -accept2(graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq) +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; @@ -1791,10 +1794,8 @@ setword workspace[50]; boolean cheapacc; -#ifdef INSTRUMENT - ++a2calls; - if (nuniq) ++a2uniq; -#endif + INSTRUMENT_VAR(a2calls); + INSTRUMENT_VAR_IF(nuniq,a2uniq); nx = n + 1; for (i = 0; i < n; ++i) { @@ -1816,18 +1817,14 @@ if (k4free && hask4(gx,n+1,maxn)) return FALSE; if (clawfree && hasclaw(gx,n+1,maxn)) return FALSE; -#ifdef PREPRUNE - if (PREPRUNE(gx,n+1,maxn)) return FALSE; -#endif + DO_PREPRUNE(gx,n+1,maxn); if (connec == 2 && n+2 == maxn && !isconnected(gx,n+1)) return FALSE; if (((connec ==2 && n+2 < maxn) || (connec == 1 && n+2 <= maxe)) && connpreprune(gx,n+1,maxn)) return FALSE; if (nuniq) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1867,9 +1864,7 @@ { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1912,9 +1907,7 @@ { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1954,9 +1947,7 @@ if (cheapacc) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1965,22 +1956,18 @@ 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; -} +}) /**************************************************************************/ @@ -2025,9 +2012,9 @@ /**************************************************************************/ -static void -spaextend(graph *g, int n, int *deg, int ne, boolean rigid, - int xlb, int xub, void (*makeh)(graph*,xword*,int)) +STATIC_POPCNTFUNC(void,spaextend, + (graph *g, int n, int *deg, int ne, boolean rigid, + int xlb, int xub, void (*makeh)(graph*,xword*,int)), /* extend from n to n+1 -- version for restricted graphs */ { xword x,d,dlow; @@ -2038,12 +2025,8 @@ int degx[MAXN]; boolean rigidx; -#ifdef INSTRUMENT - boolean haschild; - - haschild = FALSE; - if (rigid) ++rigidnodes[n]; -#endif + INSTRUMENTED_VAR(haschild); + INSTRUMENT_VAR_IF(rigid,rigidnodes[n]); ++nodes[n]; nx = n + 1; @@ -2063,9 +2046,7 @@ if (splitgraph && notsplit(g,n,maxn)) return; if (chordal && notchordal(g,n,maxn)) return; if (perfect && notperfect(g,n,maxn)) return; -#ifdef PRUNE - if (PRUNE(g,n,maxn)) return; -#endif + DO_PRUNE(g,n,maxn); xorb = data[n].xorb; xx = data[n].xx; @@ -2091,13 +2072,9 @@ if (splitgraph && notsplit(gx,nx,maxn)) continue; if (chordal && notchordal(gx,nx,maxn)) continue; if (perfect && notperfect(gx,nx,maxn)) continue; -#ifdef PRUNE - if (!PRUNE(gx,nx,maxn)) -#endif + PRUNE_NOT(gx,nx,maxn) { -#ifdef INSTRUMENT - haschild = TRUE; -#endif + INSTRUMENT_TRUE(haschild); ++ecount[ne+xc]; (*outproc)(outfile,canonise ? gcan : gx,nx); } @@ -2130,9 +2107,7 @@ if (xlbx <= xubx && accept1b(g,n,x,gx,degx,&rigidx,makeh)) { -#ifdef INSTRUMENT - haschild = TRUE; -#endif + INSTRUMENT_TRUE(haschild); spaextend(gx,nx,degx,ne+xc,rigidx,xlbx,xubx,makeh); } } @@ -2141,15 +2116,13 @@ && nodes[n] >= multiplicity) --splitlevel; } -#ifdef INSTRUMENT - if (haschild) ++fertilenodes[n]; -#endif -} + INSTRUMENT_VAR_IF(haschild, fertilenodes[n]); +}) /**************************************************************************/ -static void -genextend(graph *g, int n, int *deg, int ne, boolean rigid, int xlb, int xub) +STATIC_POPCNTFUNC(void,genextend, + (graph *g, int n, int *deg, int ne, boolean rigid, int xlb, int xub), /* extend from n to n+1 -- version for general graphs */ { xword x,d,dlow; @@ -2161,12 +2134,8 @@ int degx[MAXN]; boolean rigidx; -#ifdef INSTRUMENT - boolean haschild; - - haschild = FALSE; - if (rigid) ++rigidnodes[n]; -#endif + INSTRUMENTED_VAR(haschild); + INSTRUMENT_VAR_IF(rigid,rigidnodes[n]); ++nodes[n]; nx = n + 1; @@ -2186,9 +2155,7 @@ if (splitgraph && notsplit(g,n,maxn)) return; if (chordal && notchordal(g,n,maxn)) return; if (perfect && notperfect(g,n,maxn)) return; -#ifdef PRUNE - if (PRUNE(g,n,maxn)) return; -#endif + DO_PRUNE(g,n,maxn); imin = data[n].xstart[xlb]; imax = data[n].xstart[xub+1]; @@ -2213,13 +2180,9 @@ if (splitgraph && notsplit(gx,nx,maxn)) continue; if (chordal && notchordal(gx,nx,maxn)) continue; if (perfect && notperfect(gx,nx,maxn)) continue; -#ifdef PRUNE - if (!PRUNE(gx,nx,maxn)) -#endif + PRUNE_NOT(gx,nx,maxn) { -#ifdef INSTRUMENT - haschild = TRUE; -#endif + INSTRUMENT_TRUE(haschild); ++ecount[ne+xc]; (*outproc)(outfile,canonise ? gcan : gx,nx); } @@ -2250,9 +2213,7 @@ data[nx].hi = data[nx].xstart[xubx+1]; if (accept1(g,n,x,gx,degx,&rigidx)) { -#ifdef INSTRUMENT - haschild = TRUE; -#endif + INSTRUMENT_TRUE(haschild); genextend(gx,nx,degx,ne+xc,rigidx,xlbx,xubx); } } @@ -2260,10 +2221,8 @@ if (n == splitlevel-1 && n >= min_splitlevel && nodes[n] >= multiplicity) --splitlevel; -#ifdef INSTRUMENT - if (haschild) ++fertilenodes[n]; -#endif -} + INSTRUMENT_VAR_IF(haschild, fertilenodes[n]); +}) /**************************************************************************/ /**************************************************************************/ --- a/genposetg.c +++ b/genposetg.c @@ -289,9 +289,8 @@ /**********************************************************************************/ - -static boolean refinex(graph *g, int *lab, int *ptn, int *numcells, - int *count, set *active, setword good_vertices, int n) +STATIC_POPCNTFUNC(boolean,refinex,(graph *g, int *lab, int *ptn, int *numcells, + int *count, set *active, setword good_vertices, int n), /* custom version of refine1() which can exit quickly if required. If good_vertices is not 0, a FALSE return is made if it can be determined @@ -427,7 +426,7 @@ } return TRUE; -} + }) /******************************************************************************* @@ -781,7 +780,8 @@ /**********************************AUFSCHREIBEN_2***********************************/ -static void aufschreiben_2(int last_level, graph maxpoints,int relationscounter) +STATIC_POPCNTFUNC(void,aufschreiben_2, + (int last_level, graph maxpoints,int relationscounter), /* Hier werden die Graphen konstruiert, die mit einer Kette von jeweils nur einem Knoten pro Level anfangen. Sie entstehen aus @@ -790,9 +790,6 @@ entsprechender Laenge angehaengt wird. */ { -#if 0 - graph puffer; -#endif graph poset2[MAXN]; char *i2; int i; @@ -812,20 +809,13 @@ if (output) { -#if 0 - puffer=maxpunktzahl; - fwrite(&puffer,sizeof(graph),1,stdout); -#endif memcpy(poset2,poset,sizeof(graph)*punktzahl); poset2[maxpunktzahl-1]=0; for (i=punktzahl; i<(maxpunktzahl-1); i++) poset2[i]=bit[i+1]; FOREACH(i2,all_points_up_to[0]) ADDELEMENT(poset2+(*i2),punktzahl); -#if 0 - fwrite(poset2,sizeof(graph),maxpunktzahl,stdout); -#endif writeposet(poset2,maxpunktzahl); } -} + }) /**********************************AUFSCHREIBEN_3***********************************/ @@ -953,10 +943,20 @@ /**********************************ADD_LAST_POINT******************************************/ +#ifdef COUNT +#define OUTPUT_POSET +#define OUTPUT_NULL +#else +#define OUTPUT_POSET if (output) { poset[punktzahl]=*run; punktzahl++; aufschreiben(); punktzahl--; } +#define OUTPUT_NULL if (output) { aufschreiben(); } +#endif + + /* Fuegt den letzten Punkt hinzu -- wie add_point, nur dass Sachen, die der Weiterfuehrung dienen nicht mehr gemacht werden. Darf nur fuer den letzten Punkt aufgerufen werden ! */ -static void add_last_point (int level, int do_nauty, graph *last_nbs, graph maxpoints, int relationscounter) +STATIC_POPCNTFUNC(void,add_last_point, + (int level, int do_nauty, graph *last_nbs, graph maxpoints, int relationscounter), /* do_nauty ist genau dann 0, wenn nauty gerade ausgefuehrt wurde, um die Kanonizitaet des letzten Knotens zu testen, orbits, generators, etc @@ -1138,10 +1138,7 @@ { dummy=all_ancestors[*run]; relations[relationscounter+POPCOUNT(dummy)]++; minmaxline[POPCOUNT(maxpoints & ~dummy)]++; -#ifndef COUNT - if (output) - { poset[punktzahl]=*run; punktzahl++; aufschreiben(); punktzahl--; } -#endif + OUTPUT_POSET; } } /* ende noch kein Punkt auf dem Level */ @@ -1183,10 +1180,7 @@ { dummy=all_ancestors[*run]; relations[relationscounter+POPCOUNT(dummy)]++; minmaxline[POPCOUNT(maxpoints & ~dummy)]++; -#ifndef COUNT - if (output) - { aufschreiben(); } -#endif + OUTPUT_NULL; } else /* zunaechst noch zwei Heuristiken: Wenn alle mit der gleichen orbitnummer identische Nachbarschaften haben (d.h. nicht verschiedene, die nur im gleichen Orbit liegen), @@ -1201,10 +1195,7 @@ dummy=all_ancestors[*run]; relations[relationscounter+POPCOUNT(dummy)]++; minmaxline[POPCOUNT(maxpoints & ~dummy)]++; -#ifndef COUNT - if (output) - { aufschreiben(); } -#endif + OUTPUT_NULL; } else /* noch ein Sonderfall: Wenn die maximale Orbitgroesse 2 ist und noch kein Knoten mit Nachbarn eines anderen Orbits auf dem Level, so ist der Knoten kanonisch, @@ -1304,10 +1295,7 @@ dummy=all_ancestors[*run]; relations[relationscounter+POPCOUNT(dummy)]++; minmaxline[POPCOUNT(maxpoints & ~dummy)]++; -#ifndef COUNT - if (output) - { aufschreiben(); } -#endif + OUTPUT_NULL; } /* ende akzeptiert mit nauty */ } /* ende halt doch nauty */ @@ -1319,10 +1307,7 @@ dummy=all_ancestors[*run]; relations[relationscounter+POPCOUNT(dummy)]++; minmaxline[POPCOUNT(maxpoints & ~dummy)]++; -#ifndef COUNT - if (output) - { aufschreiben(); } -#endif + OUTPUT_NULL; } } /* else nauty... */ } /* else mit Heuristik... */ @@ -1333,7 +1318,7 @@ local_ptn[punktzahl-1]=0; } /* ende mindestens ein Punkt bereits auf dem Level */ -} +}) @@ -1345,7 +1330,8 @@ /* Fuegt einen weiteren Punkt hinzu */ -static void add_point (int level, int do_nauty, graph *last_nbs, graph maxpoints, int relationscounter) +STATIC_POPCNTFUNC(void,add_point, + (int level, int do_nauty, graph *last_nbs, graph maxpoints, int relationscounter), /* do_nauty ist genau dann 0, wenn nauty gerade ausgefuehrt wurde, um die Kanonizitaet des letzten Knotens zu testen, orbits, generators, etc @@ -1767,7 +1753,7 @@ local_ptn[punktzahl-1]=0; } /* ende mindestens ein Punkt bereits auf dem Level */ -} +}) /***************************************MAIN*******************************************/ --- a/genquarticg.c +++ b/genquarticg.c @@ -222,9 +222,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, tcol, got_one, i, j, numpair1, numdovi, maxdovi, i1, j1, i2, j2, @@ -902,7 +902,7 @@ extend(int n, graph *g, edgestruct *edge } //end for c.. -} +}) /***************************************************************************** * * @@ -1146,9 +1146,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]; @@ -1276,7 +1276,7 @@ refinex(graph *g, int *lab, int *ptn, in } } } -} +}) /*****************************************************************************/ --- a/gentourng.c +++ b/gentourng.c @@ -549,9 +549,9 @@ * * *****************************************************************************/ -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; @@ -683,7 +683,7 @@ } } } -} +}) /**************************************************************************/ @@ -805,8 +805,7 @@ /**************************************************************************/ -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 */ { @@ -829,12 +828,26 @@ 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; @@ -851,10 +864,8 @@ setword workspace[200]; boolean cheapacc; -#ifdef INSTRUMENT - ++a2calls; - if (nuniq) ++a2uniq; -#endif + INSTRUMENT_VAR(a2calls); + INSTRUMENT_UNIQ(a2uniq); nx = n + 1; gxn = 0; @@ -875,15 +886,11 @@ 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; } @@ -922,9 +929,7 @@ { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -967,9 +972,7 @@ { if (j0 == n) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -988,9 +991,7 @@ if (cheapacc) { -#ifdef INSTRUMENT - ++a2succs; -#endif + INSTRUMENT_VAR(a2succs); if (canonise) makecanon(gx,gcan,nx); return TRUE; } @@ -1000,22 +1001,18 @@ options.defaultptn = FALSE; active[0] = 0; -#ifdef INSTRUMENT - ++a2nauty; -#endif + INSTRUMENT_VAR(a2nauty); nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,200,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,13 +60,13 @@ *maxcount = maxdc; *edges = ned / 2; *eulerian = (dor & 1) == 0; -} +}) /**************************************************************************/ -void -degstats3(graph *g, int m, int n, unsigned long *edges, int *mindeg, - int *mincount, int *maxdeg, int *maxcount, int *odddeg) +POPCNTFUNC(void,degstats3, + (graph *g, int m, int n, unsigned long *edges, int *mindeg, + int *mincount, int *maxdeg, int *maxcount, int *odddeg), /* Compute degree-related graph properties. *edges = number of edges *mindeg, *mincount = minimum degree and how many there are @@ -119,16 +119,16 @@ *maxcount = maxdc; *edges = ned / 2; *odddeg = dodd; -} +}) /**************************************************************************/ -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 @@ -300,12 +300,12 @@ if (indeg[i] != outdeg[i]) break; *eulerian = (i == n); } -} +}) /*********************************************************************/ -void -sources_sinks(graph *g, int m, int n, int *sources, int *sinks) +POPCNTFUNC(void,sources_sinks, + (graph *g, int m, int n, int *sources, int *sinks), /* Count the sources and sinks. For an undirected graph, these are just the isolated vertices. For a directed graph, they have their usual meanings. A vertex with a loop is neither a source @@ -315,12 +315,8 @@ setword rowor,wk; int i,j,nsource,nsink; set *gi; -#if MAXM - setword work[MAXM+1]; -#else - DYNALLSTAT(setword,work,work_sz); - DYNALLOC1(setword,work,work_sz,m,"sources_sinks"); -#endif + DCL_DYNSETWORD(work); + DEF_DYNSETWORD(work,m,"sources_sinks"); if (n == 0) { *sources = *sinks = 0; return; } @@ -355,12 +351,11 @@ for (j = 0; j < m; ++j) nsource -= POPCOUNT(work[j]); *sources = nsource; -} + }) /*********************************************************************/ -boolean -isconnected1(graph *g, int n) +POPCNTFUNC(boolean,isconnected1,(graph *g, int n), /* test if g is connected (m=1) */ { setword seen,expanded,toexpand; @@ -379,7 +374,7 @@ } return POPCOUNT(seen) == n; -} +}) /**************************************************************************/ @@ -430,25 +425,19 @@ /**************************************************************************/ -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. */ /* Note that the value for empty subgraphs disagrees with isconnected() */ { 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); @@ -480,7 +469,7 @@ } return tail == subsize; -} +}) /**********************************************************************/ @@ -1143,8 +1132,8 @@ /**************************************************************************/ -static void -maxcsnode1(int *best, graph *g, setword cliq, setword cov, int maxv) +STATIC_POPCNTFUNC(void, +maxcsnode1,(int *best, graph *g, setword cliq, setword cov, int maxv), /* Internal search node. cov has all the vertices outside cliq that * cover all of cliq. maxv is the last vertex of cliq. * *best is the largest clique known so far. @@ -1168,7 +1157,7 @@ maxcsnode1(best,g,cliq|bit[i],cov&g[i]&~bit[i],i); } } -} +}) int maxcliquesize(graph *g, int m, int n) --- a/gutil2.c +++ b/gutil2.c @@ -58,8 +58,7 @@ /**************************************************************************/ -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. */ { @@ -80,7 +79,7 @@ } return count; -} +}) /**************************************************************************/ @@ -124,8 +123,7 @@ /**************************************************************************/ -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. */ @@ -146,7 +144,7 @@ } return count; -} +}) /**************************************************************************/ @@ -192,8 +190,7 @@ /**************************************************************************/ -long -numind3sets1(graph *g, int n) +POPCNTFUNC(long,numind3sets1,(graph *g, int n), /* The number of triangles in g; undirected only */ { int i,j; @@ -213,7 +210,7 @@ } return total; -} + }) /**************************************************************************/ @@ -229,8 +226,7 @@ /**************************************************************************/ -long -numtriangles1(graph *g, int n) +POPCNTFUNC(long,numtriangles1,(graph *g, int n), /* The number of triangles in g; undirected only */ { int i,j; @@ -250,12 +246,11 @@ } 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; undirected only */ { int i,j,k,kw; @@ -280,7 +275,7 @@ } return total; -} +}) /**************************************************************************/ @@ -338,9 +333,8 @@ /**************************************************************************/ -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. @@ -387,7 +381,7 @@ *maxadj = maxa; *minnon = minn; *maxnon = maxn; -} +}) /**************************************************************************/ @@ -456,8 +450,7 @@ 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 */ { @@ -608,7 +601,7 @@ v2 = conncontent(h,m,n-1); return v1 - v2; -} +}) boolean stronglyconnected(graph *g, int m, int n) @@ -673,8 +666,7 @@ /**************************************************************************/ -long -numsquares(graph *g, int m, int n) +POPCNTFUNC(long,numsquares,(graph *g, int m, int n), /* Number of 4-cycles. Undirected graphs only, loops ok. */ { setword w,bitij; @@ -716,12 +708,11 @@ } return (long)(total / 2); } -} + }) /**************************************************************************/ -long -numdiamonds(graph *g, int m, int n) +POPCNTFUNC(long,numdiamonds,(graph *g, int m, int n), /* Number of diamonds (squares with diagonal). Undirected only, no loops. */ { int i,j,k; @@ -759,4 +750,4 @@ } return ans; -} + }) --- a/listg.c +++ b/listg.c @@ -253,8 +253,8 @@ /**************************************************************************/ -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; @@ -266,7 +266,7 @@ fprintf(f,"Graph %lu has %d vertices and %lu edges.\n",id,n, (digraph?ne:ne/2)); -} +}) /**************************************************************************/ @@ -326,8 +326,8 @@ /**************************************************************************/ -static void -putbliss(FILE *f, unsigned long id, boolean qswitch, graph *g, int m, int n) +STATIC_POPCNTFUNC(void,putbliss, + (FILE *f, unsigned long id, boolean qswitch, graph *g, int m, int n), /* Write the graph in Bliss format, according to * http://www.tcs.hut.fi/Software/bliss/fileformat.shtml */ { @@ -347,7 +347,7 @@ 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); -} +}) /**************************************************************************/ @@ -437,9 +437,9 @@ /**************************************************************************/ -static void -putLaplacianMagma(FILE *outfile, graph *g, int linelength, boolean signless, - int m, int n, long index) +STATIC_POPCNTFUNC(void,putLaplacianMagma, + (FILE *outfile, graph *g, int linelength, boolean signless, + int m, int n, long index), { int i,j,j0,d,e; set *gi; @@ -466,13 +466,13 @@ if (i < n-1) fprintf(outfile,",\n"); else fprintf(outfile,"]);\n"); } -} +}) /**************************************************************************/ -static void -putLaplacianMaple(FILE *outfile, graph *g, int linelength, boolean signless, - int m, int n, long index) +STATIC_POPCNTFUNC(void,putLaplacianMaple, + (FILE *outfile, graph *g, int linelength, boolean signless, + int m, int n, long index), { int i,j,d,e; set *gi; @@ -508,7 +508,7 @@ if (i != n-1) fprintf(outfile,",\n"); } fprintf(outfile,"]);\n"); -} +}) /**************************************************************************/ /**************************************************************************/ --- a/multig.c +++ b/multig.c @@ -517,6 +517,18 @@ /**************************************************************************/ +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) @@ -544,8 +556,7 @@ 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; @@ -716,8 +727,7 @@ 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) weight[i] = -i-1; --- a/naugraph.c +++ b/naugraph.c @@ -175,16 +175,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; @@ -194,11 +195,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; @@ -326,7 +325,7 @@ refine(graph *g, int *lab, int *ptn, int longcode = MASH(longcode,*numcells); *code = CLEANUP(longcode); -} +}) #endif /* else case of MAXM==1 */ /***************************************************************************** @@ -338,9 +337,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; @@ -350,10 +348,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; @@ -476,7 +472,7 @@ refine1(graph *g, int *lab, int *ptn, in longcode = MASH(longcode,*numcells); *code = CLEANUP(longcode); -} +}) /***************************************************************************** * * --- a/nausparse.c +++ b/nausparse.c @@ -1487,8 +1487,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; @@ -1526,7 +1525,7 @@ nauty_to_sg(graph *g, sparsegraph *sg, i } return sg; -} +}) /***************************************************************************** * * --- a/nautinv.c +++ b/nautinv.c @@ -221,6 +221,19 @@ } } +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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ { 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } +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 @@ 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 @@ 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 @@ } } +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 @@ 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 @@ * * *****************************************************************************/ -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 @@ 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 @@ 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,8 +134,7 @@ * * *****************************************************************************/ -int -setinter(set *set1, set *set2, int m) +POPCNTFUNC(int,setinter,(set *set1, set *set2, int m), { setword x; int count,i; @@ -149,7 +148,7 @@ } return count; -} +}) /***************************************************************************** * * @@ -157,8 +156,7 @@ * * *****************************************************************************/ -int -setsize(set *set1, int m) +POPCNTFUNC(int,setsize,(set *set1, int m), { int count,i; setword x; @@ -169,7 +167,7 @@ for (i = m; --i >= 0;) count += POPCOUNT(set1[i]); return count; -} +}) /***************************************************************************** * * --- a/nauty-h.in +++ b/nauty-h.in @@ -88,6 +88,7 @@ #define HAVE_POPCNTLL @have_popcntll@ #define HAVE_MMPOP32 @have_mmpop32@ #define HAVE_MMPOP64 @have_mmpop64@ +#define RUNTIME_POPCNT @runtime_popcnt@ /*==================================================================*/ @@ -843,6 +844,46 @@ #ifndef FIRSTBITNZ /* Can be defined outside */ +/* 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 !__clang__ && (__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 type (*resolve_##name (void)) params { \ + unsigned int eax, ebx, ecx, edx; \ + return (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && \ + (ecx & bit_POPCNT) != 0) \ + ? &fast_##name \ + : &slow_##name; \ + } +#define POPCNTFUNC(type,name,params,...) \ + type __attribute__((ifunc ("resolve_" #name))) name params; \ + POPCNTHDR(type,name,params,__VA_ARGS__) +#define STATIC_POPCNTFUNC(type,name,params,...) \ + static type __attribute__((ifunc ("resolve_" #name))) name params; \ + POPCNTHDR(type,name,params,__VA_ARGS__) +#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 #define FIRSTBITNZ(x) bs_firstbit(x) @@ -955,7 +996,7 @@ /* Note that, unlike icc, gcc will not use the POPCNT instruction without permission, in which case it defines __POPCNT__ except on Apple M1 hardware. */ -#elif defined(__POPCNT__) || IS_ARM64 +#elif defined(__POPCNT__) || IS_ARM64 || RUNTIME_POPCNT #if defined(SETWORD_LONGLONG) && HAVE_POPCNTLL #define POPCOUNT(x) __builtin_popcountll(x) #elif defined(SETWORD_LONG) && HAVE_POPCNTL @@ -1216,6 +1257,25 @@ #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 +#if MAXM +#define DCL_DYNSETWORD(var) setword var[MAXM+1] +#define DEF_DYNSETWORD(var,n,name) +#else +#define DCL_DYNSETWORD(var) DYNALLSTAT(setword,var,var##_sz) +#define DEF_DYNSETWORD(var,n,name) DYNALLOC1(setword,var,var##_sz,n,name) +#endif + /* File to write error messages to (used as first argument to fprintf()). */ #define ERRFILE stderr --- a/nbrhoodg.c +++ b/nbrhoodg.c @@ -54,6 +54,15 @@ /**************************************************************************/ +STATIC_POPCNTFUNC(int,compute_degree,(setword *gv, int m), +{ + int i, degv = 0; + for (i = 0; i < m; ++i) degv += POPCOUNT(gv[i]); + return degv; + }) + +/**************************************************************************/ + int main(int argc, char *argv[]) { @@ -195,8 +204,7 @@ for (v = minvert, gv = GRAPHROW(g,minvert,m); v < n && v <= maxvert; ++v, gv += m) { - degv = 0; - for (i = 0; i < m; ++i) degv += POPCOUNT(gv[i]); + degv = compute_degree(gv,m); if (degv < mindeg || degv > maxdeg) continue; if (Cswitch) --- a/vcolg.c +++ b/vcolg.c @@ -144,6 +144,22 @@ if (col[i] == 1) DELELEMENT(gi,i); } +#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; +}) +#endif + +/**************************************************************************/ + static int trythisone(grouprec *group, graph *g, boolean digraph, int m, int n) /* Try one solution, accept if maximal. */ @@ -192,9 +208,7 @@ #ifdef OUTPROC OUTPROC(outfile,g,col,m,n); #else - ne = 0; - for (gi = g + m*(size_t)n; --gi >= g; ) - ne += POPCOUNT(*gi); + ne = compute_degree(g,m,n); if (!digraph) { for (i = 0, gi = g; i < n; ++i, gi += m) @@ -542,10 +556,24 @@ /**************************************************************************/ +STATIC_POPCNTFUNC(void,update_degree,(graph *g, long *deg, int m, int n), +{ + graph *gi; + int i, j; + + for (i = 0, gi = g; i < n; ++i, gi += m) + { + deg[i] = 0; + for (j = 0; j < m; ++j) deg[i] += POPCOUNT(gi[j]); + } +}) + +/**************************************************************************/ + int main(int argc, char *argv[]) { - graph *g,*gi; + graph *g; int m,n,codetype; int argnum,i,j,nfixed; char *arg,sw; @@ -753,11 +781,7 @@ if (oswitch && loopcount(g,m,n) > 0) gt_abort(">E vcolg: loops in input are not allowed for -o\n"); - for (i = 0, gi = g; i < n; ++i, gi += m) - { - deg[i] = 0; - for (j = 0; j < m; ++j) deg[i] += POPCOUNT(gi[j]); - } + update_degree(g,deg,m,n); if (!digraph) colourgraph(g,nfixed,mincols,maxcols,colcount, --- a/watercluster2.c +++ b/watercluster2.c @@ -593,7 +593,7 @@ /****************************************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; @@ -605,7 +605,7 @@ aantal_gerichte_bogen=0; return; -} +}) /***************************FILL_EDGELIST**************************/ @@ -1238,7 +1238,8 @@ /**********************************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; @@ -1398,7 +1399,7 @@ } } return; -} +}) int compare_op(unsigned char *op1, unsigned char *op2) // returns 0 if operations are the same, something negative if op1 @@ -1525,7 +1526,8 @@ /******************************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 @@ -1822,7 +1824,7 @@ else { return 0; } -} +}) int all_diff_colours(graph testset, int orbitid) // returns 1 if all elements have some different vertex invariant and 0 otherwise @@ -3764,7 +3766,7 @@ -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 */ @@ -3927,7 +3929,7 @@ return; -} +})