nauty/nauty-popcnt.patch

1804 lines
55 KiB
Diff

Description: enable runtime detection of popcnt-enabled CPU
Origin: fedora
Author: Jerry James <loganjerry@gmail.com>
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 +332,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 +350,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 <cpuid.h>
+
+#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;
-}
+})