nauty24r2/0002700000604200001440000000000011427225073011303 5ustar bdmusersnauty24r2/gutil1.c0000600000604200001440000002773011274163463012671 0ustar bdmusers/* gutil1.c: Some graph utilities. */ #include "gtools.h" #include "gutils.h" /**************************************************************************/ 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 *maxdeg, *maxcount = maximum degree and how many there are *eulerian = whether the graph has only even degrees */ { setword *pg; int i,j,d,dor; int mind,mindc,maxd,maxdc; unsigned long ned; mind = n; mindc = 0; maxd = 0; maxdc = 0; ned = 0; dor = 0; pg = (setword*)g; for (i = 0; i < n; ++i) { d = 0; for (j = 0; j < m; ++j, ++pg) if (*pg) d += POPCOUNT(*pg); if (d == mind) ++mindc; else if (d < mind) { mind = d; mindc = 1; } if (d == maxd) ++maxdc; else if (d > maxd) { maxd = d; maxdc = 1; } dor |= d; ned += d; } *mindeg = mind; *mincount = mindc; *maxdeg = maxd; *maxcount = maxdc; *edges = ned / 2; *eulerian = (dor & 1) == 0; } /*********************************************************************/ boolean isconnected1(graph *g, int n) /* test if g is connected (m=1) */ { setword seen,expanded,toexpand; int i; seen = bit[0]; expanded = 0; while ((toexpand = (seen & ~expanded)) != 0) { i = FIRSTBIT(toexpand); expanded |= bit[i]; seen |= g[i]; } return POPCOUNT(seen) == n; } /**************************************************************************/ boolean isconnected(graph *g, int m, int n) /* Test if g is connected */ { int i,head,tail,w; set *gw; #if MAXN int queue[MAXN],visited[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,visited,visited_sz); #endif if (m == 1) return isconnected1(g,n); #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"isconnected"); DYNALLOC1(int,visited,visited_sz,n,"isconnected"); #endif for (i = 0; i < n; ++i) visited[i] = 0; queue[0] = 0; visited[0] = 1; head = 0; tail = 1; while (head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (!visited[i]) { visited[i] = 1; queue[tail++] = i; } } } return tail == n; } /**************************************************************************/ 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); DYNALLOC1(int,queue,queue_sz,n,"issubconnected"); DYNALLOC1(int,visited,visited_sz,n,"issubconnected"); DYNALLOC1(set,subw,subw_sz,m,"issubconnected"); #endif subsize = 0; for (i = 0; i < m; ++i) subsize += (sub[i] ? POPCOUNT(sub[i]) : 0); if (subsize <= 1) return TRUE; for (i = 0; i < n; ++i) visited[i] = 0; i = nextelement(sub,m,-1); queue[0] = i; visited[i] = 1; head = 0; tail = 1; while (head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); for (i = 0; i < m; ++i) subw[i] = gw[i] & sub[i]; for (i = -1; (i = nextelement(subw,m,i)) >= 0;) { if (!visited[i]) { visited[i] = 1; queue[tail++] = i; } } } return tail == subsize; } /**********************************************************************/ boolean isbiconnected1(graph *g, int n) /* Test if g is biconnected; version for m=1. */ { int sp,v,w; setword sw; int numvis; setword visited; int num[WORDSIZE],lp[WORDSIZE],stack[WORDSIZE]; if (n <= 2) return FALSE; visited = bit[0]; stack[0] = 0; num[0] = 0; lp[0] = 0; numvis = 1; sp = 0; v = 0; for (;;) { if ((sw = g[v] & ~visited)) /* not "==" */ { w = v; v = FIRSTBIT(sw); /* visit next child */ stack[++sp] = v; visited |= bit[v]; lp[v] = num[v] = numvis++; sw = g[v] & visited & ~bit[w]; while (sw) { w = FIRSTBIT(sw); sw &= ~bit[w]; if (num[w] < lp[v]) lp[v] = num[w]; } } else { w = v; /* back up to parent */ if (sp <= 1) return numvis == n; v = stack[--sp]; if (lp[w] >= num[v]) return FALSE; if (lp[w] < lp[v]) lp[v] = lp[w]; } } } /**********************************************************************/ boolean isbiconnected(graph *g, int m, int n) /* test if g is biconnected */ { int sp,v,vc; int numvis; set *gv; #if MAXN int num[MAXN],lp[MAXN],stack[MAXN]; #else DYNALLSTAT(int,num,num_sz); DYNALLSTAT(int,lp,lp_sz); DYNALLSTAT(int,stack,stack_sz); #endif if (n <= 2) return FALSE; if (m == 1) return isbiconnected1(g,n); #if !MAXN DYNALLOC1(int,num,num_sz,n,"isbiconnected"); DYNALLOC1(int,lp,lp_sz,n,"isbiconnected"); DYNALLOC1(int,stack,stack_sz,n,"isbiconnected"); #endif num[0] = 0; for (v = 1; v < n; ++v) num[v] = -1; lp[0] = 0; numvis = 1; sp = 0; v = 0; vc = -1; gv = (set*)g; for (;;) { vc = nextelement(gv,m,vc); if (vc < 0) { if (sp <= 1) return numvis == n; vc = v; v = stack[--sp]; gv = GRAPHROW(g,v,m); if (lp[vc] >= num[v]) return FALSE; if (lp[vc] < lp[v]) lp[v] = lp[vc]; } else if (num[vc] < 0) { stack[++sp] = vc; v = vc; gv = GRAPHROW(g,v,m); vc = -1; lp[v] = num[v] = numvis++; } else if (vc != v) { if (num[vc] < lp[v]) lp[v] = num[vc]; } } } /**************************************************************************/ boolean twocolouring(graph *g, int *colour, int m, int n) /* If g is bipartite, set colour[*] to 0 or 1 to indicate an example of 2-colouring and return TRUE. Otherwise return FALSE. Colour 0 is assigned to the first vertex of each component. */ { int i,head,tail,v,w,need; set *gw; #if MAXN int queue[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); #endif #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"twocolouring"); #endif for (i = 0; i < n; ++i) colour[i] = -1; for (v = 0; v < n; ++v) if (colour[v] < 0) { queue[0] = v; colour[v] = 0; head = 0; tail = 1; while (head < tail) { w = queue[head++]; need = 1 - colour[w]; gw = GRAPHROW(g,w,m); for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (colour[i] < 0) { colour[i] = need; queue[tail++] = i; } else if (colour[i] != need) return FALSE; } } } return TRUE; } /**************************************************************************/ boolean isbipartite(graph *g, int m, int n) /* Test if g is bipartite */ { int i,head,tail,v,w,need; set *gw; #if MAXN int colour[MAXN]; #else DYNALLSTAT(int,colour,colour_sz); #endif /* if (m == 1) return isbipartite1(g,n); */ #if !MAXN DYNALLOC1(int,colour,colour_sz,n,"isbipartite"); #endif return twocolouring(g,colour,m,n); } /**************************************************************************/ int girth(graph *g, int m, int n) /* Find the girth of graph g. 0 means acyclic. */ { int i,head,tail,v,w; int best,c,dw1; set *gw; #if MAXN int dist[MAXN],queue[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,dist,dist_sz); DYNALLOC1(int,queue,queue_sz,n,"girth"); DYNALLOC1(int,dist,dist_sz,n,"girth"); #endif best = n+1; for (v = 0; v < n; ++v) { for (i = 0; i < n; ++i) dist[i] = -1; queue[0] = v; dist[v] = 0; head = 0; tail = 1; while (head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); dw1 = dist[w] + 1; for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (dist[i] < 0) { dist[i] = dw1; queue[tail++] = i; } else if (dist[i] >= dist[w]) { c = dw1 + dist[i]; if (c < best) best = c; if ((c & 1) != 0 || c > best) break; } } if (i >= 0) break; } if (best == 3) return 3; } return (best > n ? 0 : best); } /**************************************************************************/ void find_dist(graph *g, int m, int n, int v, int *dist) /* Put in dist[0..n-1] the distance of each vertex from v. Vertices in a different component are given the distance n. */ { int i,head,tail,w; set *gw; #if MAXN int queue[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); #endif #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"isconnected"); #endif for (i = 0; i < n; ++i) dist[i] = n; queue[0] = v; dist[v] = 0; head = 0; tail = 1; while (tail < n && head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (dist[i] == n) { dist[i] = dist[w] + 1; queue[tail++] = i; } } } } /**************************************************************************/ void diamstats(graph *g, int m, int n, int *radius, int *diameter) /* Find the radius and diameter. Both -1 if g is disconnected. We use an O(mn) algorithm, which is pretty disgraceful. */ { int v,i,head,tail,w; int ecc,diam,rad; set *gw; #if MAXN int queue[MAXN],dist[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,dist,dist_sz); #endif /* if (m == 1) {diamstats1(g,n,radius,diameter); return; } */ #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"isconnected"); DYNALLOC1(int,dist,dist_sz,n,"isconnected"); #endif diam = -1; rad = n; for (v = 0; v < n; ++v) { for (i = 0; i < n; ++i) dist[i] = -1; queue[0] = v; dist[v] = 0; head = 0; tail = 1; while (tail < n && head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (dist[i] < 0) { dist[i] = dist[w] + 1; queue[tail++] = i; } } } if (tail < n) { *diameter = *radius = -1; return; } ecc = dist[queue[n-1]]; if (ecc > diam) diam = ecc; if (ecc < rad) rad = ecc; } *diameter = diam; *radius = rad; } nauty24r2/callgeng.c0000600000604200001440000000226311274163463013232 0ustar bdmusers/* This is a sample of how to call geng as a procedure rather than * running it as a separate process. The basic idea is to construct * an argument list for geng's main() function. At compile time, * assign a name to the macros OUTPROC and GENG_MAIN. A typical * Unix-style compilation command would be: gcc -o callgeng -O3 -DMAXN=32 -DOUTPROC=outproc -DGENG_MAIN=geng_main \ callgeng.c geng.c gtools.o nauty1.o nautil1.o naugraph1.o */ #include "gtools.h" static unsigned long counter; void OUTPROC(FILE *outfile, graph *g, int n) { /* This will be called for each graph. */ ++counter; } int main(int argc, char *argv[]) { int geng_argc; char *geng_argv[6]; /* Set up geng argument list. The 0-th argument is the command name. * There must be a NULL at the end. This example is for connected * bipartite graphs of order 10 and maximum degree at most 4. */ geng_argv[0] = "geng"; geng_argv[1] = "-q"; geng_argv[2] = "-cb"; geng_argv[3] = "-D4"; geng_argv[4] = "10"; geng_argv[5] = NULL; geng_argc = 5; counter = 0; GENG_MAIN(geng_argc,geng_argv); printf("Number of graphs = %lu.\n",counter); return 0; } nauty24r2/README0000600000604200001440000002627511274163463012203 0ustar bdmusers README file for nauty 2.4 Brendan McKay, bdm@cs.anu.edu.au ------------------------------------------------------------ The most recent distribution of nauty can be found at http://cs.anu.edu.au/~bdm/nauty . The manual nug.pdf is available at that site and is also included in the distribution package. Note that nauty is copyright but free to use for most purposes. The details are in the file nauty.h. The code in the file planarity.c (used by the planarg program) is copyright to the Magma project. ------------------------------------------------------------ INSTALLATION. The first step is to unpack the archive. On Unix-ish systems you can use one of these commands: tar xzf nauty24.tar.gz or gunzip -c nauty24.tar.gz | tar xf - This will write all the files into the subdirectory nauty24. Go to that directory. If you have a working shell, and make, you can run ./configure followed by make all to compile nauty for your system. If that succeeds without problem, you will have have the program dreadnaut ready to run. If you have problems during compilation, it may be that the configuration scripts are inadequate for your system. Usually it is because of some missing system header, incompatible typedef, or similar. Please send the details to the author. If you don't have a shell or make, manually edit the files nauty.h, naututil.h and gtools.h as distributed. The parts between the lines ======= near the start are the main things to look at. After this manual editing, you can use makefile as a guide to compilation. Programs which use an older version of nauty need to be recompiled (** not just relinked **). Make sure they use the DEFAULTOPTIONS_GRAPH or DEFAULTOPTIONS_SPARSEGRAPH macro to define the fields of the options parameter. See below for compiling on a PC under DJGPP. If you are using Windows in an environment that needs Windows line endings (which is a configuration option in Cygwin, for example), then you might prefer to use nauty24.zip rather than nauty24.tar.gz. ------------------------------------------------------------ TESTING. After compiling nauty successfully, it is recommended that you run the included test programs. The simplest way is make checks ------------------------------------------------------------ MAILING LIST. There is a mailing list for announcements and discussion about nauty and related topics. You can subscribe at http://dcsmail.anu.edu.au/cgi-bin/mailman/listinfo/nauty-list ------------------------------------------------------------ OTHER FILES IN THE PACKAGE. A few additional goodies are included. sumlines.c - This is a program designed to digest the outputs from multiple runs of a program (such as a computation split into multiple parts). Lines matching given patterns can be counted and checked, and numbers appearing in them can be accumulated. Instructions appear in the source file. See the option GMP near the head of the program before trying to compile. naugroup.h, naugroup.c - These define procedures for exhaustively listing a group found by nauty. This is done in a space-efficient way. A sample program appears in nautyex3.c, but so far there is no complete documentation. ------------------------------------------------------------ DJGPP. The Unix-like environment DJGPP can be used to run nauty and gtools on DOS/Win computers. DJGPP is available at http://www.delorie.com/djgpp . The program shortg does not work since DJGPP does not provide a working pipe() system call. Using the bash shell is recommended. In DOS, Windows NT and early Windows editions, you will need to convert all long file names to the 8+3 limits. Thanks to Guenter Sterntenbrink for helping with this. If configure gives an error message similar to this: can not guess host type: you must specify one then try ./configure --host=i686 or use i586 for Pentium 2. If all of those fail, try ./configure --host=unknown ------------------------------------------------------------ RECENT CHANGES. Here we list substantive changes made since the first 2.2 release. Nov 16, 2002: Replaced rng.c after communication with Don Knuth. The previous version had a bug (mine!) when there was no explicit initialization done by the user. It appears the error had no impact on nauty (which only uses rng.c for the "s" command in dreadnaut, and for genrang, but both always initialize). No change to the nauty version number but beta=2. Nov 18, 2000: Adjusted the makefile and countg/testg to work in the DOS/Win environment DJGPPP (see the previous section). May 1, 2003: Fixed PRUNE feature of genbg. May 3, 2003: Added utility directg for making all orientations of graphs. Oct 4, 2003: Added options -a, -Z, -d, -z to genbg. Also, the -l (canonical label) option now preserves the colouring. Nov 17, 2003: Renamed INFINITY to NAUTY_INFINITY since many C header libraries define INFINITY. If INFINITY is not defined by the system, you can still use it. Nov 19, 2003: Added program biplabg to relabel bipartite graphs with the colour classes contiguous. Feb 13, 2004: Revised C options for solaris on pentium Mar 1, 2004: dretog knows !...\n type of comment May 7, 2004: geng can be called from another program (see instructions in geng.c.) May 29, 2004: added definition of SETWORD_FORMAT used to write a setword with printf( ) - see nauty.h Sep 11, 2004: Added utility multig for making multigraphs based on provided simple graphs; similar to directg Oct 16, 2004: To avoid problems caused by system-dependent handling of external declarations, nauty() no longer accepts NULL as the value of options.dispatch. To get the previous behaviour, use the value &graph_dispatch. This will be handled automatically if programs calling nauty use DEFAULTOPTIONS to declare options and are recompiled. Even better is to use DEFAULTOPTIONS_GRAPH. May 5, 2005: A bug in the writing of sparse6 was found and fixed. This is procedure ntos6() in gtools.c, which is invoked by writes6(). The bug could only happen if all the following are true: 1. n = 2, 4, 8 or 16 (for n=2, only if the graph has loops) 2. Vertex n-2 has non-zero degree, but vertex n-1 has zero degree. These conditions never happen for graphs generated by geng or genbg, nor for regular graphs or connected graphs, nor for graphs canonically labelled by nauty (except maybe with some unusual vertex colouring or invariant). If the conditions do happen, the buggy routine may (with some probability) add a spurious loop to vertex n-1. In the package is a utility checks6: Usage: checks6 [-w] [infile [outfile]] Check a file of graphs, optionally write corrected version -w Write corrected graphs (default is not to write) ------now we start version 2.3 (not released) and 2.4------ Nov 10, 2004: Use faster routine getc_unlocked() for reading graphs if available. It can make a surprising difference. Nov 17, 2004: If putenv() or setenv() are available, we set LC_COLLATE to "C" before executing "sort" in shortg. This should alleviate collation issues with sort. However, note that many utilities use the locale these days so you are advised to have LC_COLLATE defined to be "C" always when you are dealing with files of graphs. Six counters in statsblk became "unsigned long" instead of "long". nauty doesn't actually use these, but we might as well give them twice as long before they overflow. Nov 24, 2004: Made geng faster for generating trees. The output labelling may be different from before. A very much faster tree generator is in the works. Jan 17, 2005: Added two items to dispatch vectors: init : used for initialising something at the start cleanup : used for doing something at the end, such as freeing space allocated by init() See the manual for calling sequences. May 20, 2005: Update graph6 and sparse6 formats to allow much large sizes. The limit is now 68719476735 vertices (best of luck getting close to that!). Nov 12, 2005: Changed NAUTY_INFINITY to 2^30+2 in BIGNAUTY case 2006 various: Procedures for sparse graphs implemented. New program planarg to test for planarity and find planar embeddings: planarg -help for details. The planarity code was written by Paulette Lieby for the Magma project and used with permission. labelg got -S to use sparse graphs. genbg -N changed to genbg -n (only Gordon uses this). genrang gained -R switch for regular graphs in text format. gtools.c has code for reading and writing planarcode. listg got a compile time option to select "Matrix" or "array" for Maple output. pickg/countg got -T for counting triangles Better configuration for MacOSX. Nov 22, 2006: Removed usertcellproc from options. Greater functionality is now available using the new targetcell field in the dispatch vector. The u8 command has gone from dreadnaut. Changed bestcell to targetcell in dispatch vector. Nov 29, 2006: Added extraoptions field (currently unused) to optionblk Dec 9, 2006: Added an invariant adjacencies_sg(), recommended for digraphs when using sparse representation. Dec 10, 2006: Remove BIGNAUTY, whose usefulness has passed. Now the types shortish and permutation are synonymous with int always. The limit on the number of vertices is 2^30 unless int has only 16 bits (still any of them around?) in which case it is 2^15-3. Programs previously linked with files like nautyB.o can now be linked with nauty.o. Alternatively, "make bigs" will create files like nautyB.o by copying. June 26, 2007: Fixed an error in listg -s reported by Evan Heidtmann. July 12, 2007: Added -f option to directg. Aug 14, 2007: Added -i,-I,-K options to shortg, parallel to labelg. Since -k is used in labelg in place of -I, changed labelg to use -I also, with -k remaining as an undocumented compatibility feature. Aug-Sep 2007: Minor things: * naututil-h.in now defines CPUTIME=0.0 as a last resort * gtools.c now implements EDGECODE (not used anywhere yet) * fixed definition of SG_FREE in nausparse.h (not used) * geng favours space over time for n > 28 Oct 14, 2007: Added -T switch to shortg to specify scratch directory. Mar 3, 2008: Fixed makefile for compilation in a 64-bit environment. Oct 11, 2008: Added -l and -m to genrang Nov 29, 2008: Slightly improved -c for geng and genbg Added tournament generator gentourng. Mar 3, 2009: Added -V to directg. nauty24r2/nautaux.h0000600000604200001440000000340711274163463013151 0ustar bdmusers/***************************************************************************** * * * This is the header file for version 2.3 of nautaux.c. * * * * Copyright (1984-2005) Brendan McKay. All rights reserved. * * Subject to the waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 26-Apr-89 : initial creation for version 1.5. * * 14-Oct-90 : renamed as version 1.6 (no changes to this file) * * 5-Jun-93 : renamed as version 1.7+ (no changes to this file) * * 18-Aug-93 : renamed as version 1.8 (no changes to this file) * * 17-Sep-93 : renamed as version 1.9 (no changes to this file) * * 19-Apr-95 : added prototype wrapper for C++ * * 16-Nov-00 : made changes listed in nauty.h. * * 3-Nov-04 : declared nautaux_freedyn and nautaux_check * * * *****************************************************************************/ #include "nauty.h" /* which includes stdio.h */ #ifdef __cplusplus extern "C" { #endif extern int component(graph*,int,set*,int,int); extern boolean equitable(graph*,nvector*,nvector*,int,int,int); extern long ptncode(graph*,nvector*,nvector*,int,int,int); extern void nautaux_freedyn(void); extern void nautaux_check(int,int,int,int); #ifdef __cplusplus } #endif nauty24r2/testg.c0000600000604200001440000005554411274163463012616 0ustar bdmusers/* testg.c : Find properties of graphs. This is the source file for both pickg (select by property) and countg (count by property). Version of Nov 19, 2003. */ /* TODO - write a header if input has one */ /* TODO - USERDEF should be long, not int */ #define USAGE \ "[pickg|countg] [-fp#:#q -V] [--keys] [-constraints -v] [ifile [ofile]]" #define HELPTEXT \ " countg : Count graphs according to their properties.\n\ pickg : Select graphs according to their properties.\n\ \n\ ifile, ofile : Input and output files.\n\ '-' and missing names imply stdin and stdout.\n\ \n\ Miscellaneous switches:\n\ -p# -p#:# Specify range of input lines (first is 1)\n\ -f With -p, assume input lines of fixed length\n\ (only used with a file in graph6 format)\n\ -v Negate all constraints\n\ -V List properties of every input matching constraints.\n\ -q Suppress informative output.\n\ \n\ Constraints:\n\ Numerical constraints (shown here with following #) can take\n\ a single integer value, or a range like #:#, #:, or :#. Each\n\ can also be preceded by '~', which negates it. (For example,\n\ -~D2:4 will match any maximum degree which is _not_ 2, 3, or 4.)\n\ Constraints are applied to all input graphs, and only those\n\ which match all constraints are counted or selected.\n\ \n\ -n# number of vertices -e# number of edges\n\ -d# minimum degree -D# maximum degree\n\ -r regular -b bipartite\n\ -z# radius -Z# diameter\n\ -g# girth (0=acyclic) -Y# total number of cycles\n\ -T# number of triangles\n\ -E Eulerian (all degrees are even, connectivity not required)\n\ -a# group size -o# orbits -F# fixed points -t vertex-transitive\n\ -c# connectivity (only implemented for 0,1,2).\n\ -i# min common nbrs of adjacent vertices; -I# maximum\n\ -j# min common nbrs of non-adjacent vertices; -J# maximum\n\ \n\ Sort keys:\n\ Counts are made for all graphs passing the constraints. Counts\n\ are given separately for each combination of values occuring for\n\ the properties listed as sort keys. A sort key is introduced by\n\ '--' and uses one of the letters known as constraints. These can\n\ be combined: --n --e --r is the same as --ne --r and --ner.\n\ The order of sort keys is significant.\n" #include "gtools.h" #include "gutils.h" /* How to add a new property: 1. Add entries to constraint[], following the examples there. If several things are computed at the same time, link them together such as for z and Z. It doesn't matter which is first provided the prereq field points to the first one. 2. Add code to compute() to compute the value(s) of the parameter. Probably this means calling an external procedure then setting some VAL() and COMPUTED() values. 3. Update HELPTEXT. External user-defined parameters: A general integer-valued parameter can be compiled into this program if USERDEF is defined as the function name at compile time. In this case the parameter is selected using the letter 'Q'. The name of the parameter is "userdef" unless USERDEFNAME is defined. The function is called with the parameters (graph *g, int m, int n) and must return an integer value. */ #ifdef USERDEF int USERDEF(graph*,int,int); #endif #ifndef USERDEFNAME #define USERDEFNAME "userdef" #endif /**********************************************************************/ #define BOOLTYPE 0 #define INTTYPE 1 #define GROUPSIZE 2 #define INTVECTOR 3 #undef CMASK #define CMASK(i) (1L << (i)) static struct constraint_st /* Table of Constraints */ { char symbol; int needed; /* 1 = sortkey, 2 = constraint; 3 = both */ boolean computed; boolean inverse; unsigned long prereq; /* Must be earlier, must be <= bits in long */ long lo,hi; char *id; int valtype; long val; /* Might be a cast pointer */ } constraint[] = { #define I_n 0 {'n',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"n",INTTYPE,0}, /* always known */ #define I_e 1 {'e',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"e",INTTYPE,0}, #define I_d 2 {'d',0,FALSE,FALSE,CMASK(I_e),-NOLIMIT,NOLIMIT,"mindeg",INTTYPE,0}, #define I_D 3 {'D',0,FALSE,FALSE,CMASK(I_e),-NOLIMIT,NOLIMIT,"maxdeg",INTTYPE,0}, #define I_E 4 {'E',0,FALSE,FALSE,CMASK(I_e),-NOLIMIT,NOLIMIT,"eulerian",BOOLTYPE,0}, #define I_r 5 {'r',0,FALSE,FALSE,CMASK(I_e),-NOLIMIT,NOLIMIT,"regular",BOOLTYPE,0}, #define I_b 6 {'b',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"bipartite",BOOLTYPE,0}, #define I_z 7 {'z',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"radius",INTTYPE,0}, #define I_Z 8 {'Z',0,FALSE,FALSE,CMASK(I_z),-NOLIMIT,NOLIMIT,"diameter",INTTYPE,0}, #define I_a 9 {'a',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"groupsize",GROUPSIZE,0}, #define I_o 10 {'o',0,FALSE,FALSE,CMASK(I_a),-NOLIMIT,NOLIMIT,"orbits",INTTYPE,0}, #define I_t 11 {'t',0,FALSE,FALSE,CMASK(I_o),-NOLIMIT,NOLIMIT,"transitive",BOOLTYPE,0}, #define I_c 12 {'c',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"connectivity",INTTYPE,0}, #define I_F 13 {'F',0,FALSE,FALSE,CMASK(I_a),-NOLIMIT,NOLIMIT,"fixedpts",INTTYPE,0}, #define I_g 14 {'g',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"girth",INTTYPE,0}, #define I_Y 15 {'Y',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"cycles",INTTYPE,0}, #define I_i 16 {'i',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"minadjcn",INTTYPE,0}, #define I_I 17 {'I',0,FALSE,FALSE,CMASK(I_i),-NOLIMIT,NOLIMIT,"maxadjcn",INTTYPE,0}, #define I_j 18 {'j',0,FALSE,FALSE,CMASK(I_i),-NOLIMIT,NOLIMIT,"minnoncn",INTTYPE,0}, #define I_J 19 {'J',0,FALSE,FALSE,CMASK(I_i),-NOLIMIT,NOLIMIT,"maxnoncn",INTTYPE,0}, #define I_T 20 {'T',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,"triang",INTTYPE,0}, #define I_Q 21 #ifdef USERDEF {'Q',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,USERDEFNAME,INTTYPE,0} #else {' ',0,FALSE,FALSE,0,-NOLIMIT,NOLIMIT,USERDEFNAME,INTTYPE,0} #endif }; #define NUMCONSTRAINTS (sizeof(constraint)/sizeof(struct constraint_st)) #define SYMBOL(i) (constraint[i].symbol) #define ISNEEDED(i) (constraint[i].needed > 0) #define NEEDED(i) (constraint[i].needed) #define ISKEY(i) ((constraint[i].needed & 1) != 0) #define ISCONSTRAINT(i) (constraint[i].needed > 1) #define INVERSE(i) (constraint[i].inverse) #define COMPUTED(i) (constraint[i].computed) #define PREREQ(i) (constraint[i].prereq) #define LO(i) (constraint[i].lo) #define HI(i) (constraint[i].hi) #define VAL(i) (constraint[i].val) #define VALTYPE(i) (constraint[i].valtype) #define ID(i) (constraint[i].id) #define INBOUNDS0(i) ((LO(i) == -NOLIMIT || VAL(i) >= LO(i)) \ && (HI(i) == NOLIMIT || VAL(i) <= HI(i))) #define INBOUNDS(i) (VALTYPE(i) == GROUPSIZE \ ? group_in_range((group_node*)VAL(i),LO(i),HI(i)) \ : INBOUNDS0(i)) static boolean docount,dofilter; #define MAXKEYS 20 /* Maximum number of keys to sort by */ /* splay_st is the generic structure of a splay tree node. The data[] field has varying lengths according to need. This program uses two splay trees: one for counts and one for large data items. */ typedef struct splay_st { struct splay_st *left,*right,*parent; long data[1]; } splay_node; typedef struct node_st /* variant for count tree */ { struct splay_st *left,*right,*parent; unsigned long count; long val[MAXKEYS]; } count_node; typedef struct value_st /* variant for value tree */ { struct splay_st *left,*right,*parent; size_t size; long data[1]; } value_node; #define TOSPLAY(p) ((SPLAYNODE*)(p)) #define TOVALUE(p) ((value_node*)(p)) #define TOCOUNT(p) ((count_node*)(p)) #define SPLAYNODE splay_node #define SPLAYNODESIZE new_val_sz #define SCAN_ARGS , FILE *f #define ACTION(p) {fprintf(f,"%9ld graphs : ",TOCOUNT(p)->count); \ printkeyvals(f,TOCOUNT(p)->val); fprintf(f,"\n");} #define INSERT_ARGS , boolean isvalue, SPLAYNODE *new_val, size_t new_val_sz #define COMPARE(p) (isvalue ? \ compare_value_node(TOVALUE(new_val),TOVALUE(p)) \ : compare_count_node(TOCOUNT(new_val),TOCOUNT(p))) #define PRESENT(p) {if (!isvalue) ++TOCOUNT(p)->count;} #define NOT_PRESENT(p) {memcpy((void*)p,(void*)new_val,SPLAYNODESIZE); \ if (!isvalue) TOCOUNT(p)->count = 1;} static void printkeyvals(FILE*,long*); static int compare_count_node(count_node*,count_node*); static int compare_value_node(value_node*,value_node*); static splay_node *count_root = NULL; static splay_node *value_root = NULL; static int key[MAXKEYS]; static int numkeys; #include "splay.c" /* Procedures for splay tree management */ typedef struct grpsize_st { struct splay_st *left,*right,*parent; size_t size; double groupsize1; long groupsize2; } group_node; /**********************************************************************/ static int compare_count_node(count_node *a, count_node *b) /* Usual type of comparison */ { int i; group_node *sza,*szb; for (i = 0; i < numkeys; ++i) { if (VALTYPE(key[i]) == GROUPSIZE) { sza = (group_node*)a->val[i]; szb = (group_node*)b->val[i]; if (sza->groupsize2 < szb->groupsize2) return -1; else if (sza->groupsize2 > szb->groupsize2) return 1; else if (sza->groupsize1 < szb->groupsize1) return -1; else if (sza->groupsize1 > szb->groupsize1) return 1; } else if (a->val[i] < b->val[i]) return -1; else if (a->val[i] > b->val[i]) return 1; } return 0; } /**********************************************************************/ static int compare_value_node(value_node *a, value_node *b) /* Usual type of comparison */ { size_t minsize; int cmp; if (a->size < b->size) minsize = a->size; else minsize = b->size; cmp = memcmp(a->data,b->data,minsize); if (cmp != 0) return cmp; if (a->size < minsize) return -1; else if (a->size > minsize) return 1; else return 0; } /**********************************************************************/ static void write_group_size(FILE *f, group_node *sz) { double sz1; int sz2; sz1 = sz->groupsize1; sz2 = sz->groupsize2; if (sz2 == 0) fprintf(f,"%.0f",sz1+0.1); else { while (sz1 >= 10.0) { sz1 /= 10.0; ++sz2; } fprintf(f,"%12.10fe%d",sz1,sz2); } } /**********************************************************************/ static void add_one(void) /* Add current graph to count. */ { int i; count_node new_val; for (i = 0; i < numkeys; ++i) new_val.val[i] = VAL(key[i]); splay_insert(&count_root,FALSE,TOSPLAY(&new_val), sizeof(splay_node)+numkeys*sizeof(long)); } /**********************************************************************/ static void printthesevals(FILE *f) { int i,ki; for (i = 0; i < numkeys; ++i) { ki = key[i]; if (i > 0) fprintf(f,"; "); if (VALTYPE(ki) == BOOLTYPE) { if (!VAL(ki)) fprintf(f,"not %s",ID(ki)); else fprintf(f,ID(ki)); } else if (VALTYPE(ki) == GROUPSIZE) { fprintf(f,"%s=",ID(ki)); write_group_size(f,(group_node*)VAL(ki)); } else fprintf(f,"%s=%ld",ID(ki),VAL(ki)); } } /**********************************************************************/ static void printkeyvals(FILE *f, long *val) { int i,ki; for (i = 0; i < numkeys; ++i) { ki = key[i]; if (i > 0) fprintf(f,"; "); if (VALTYPE(ki) == BOOLTYPE) { if (!val[i]) fprintf(f,"not %s",ID(ki)); else fprintf(f,ID(ki)); } else if (VALTYPE(ki) == GROUPSIZE) { fprintf(f,"%s=",ID(ki)); write_group_size(f,(group_node*)val[i]); } else fprintf(f,"%s=%ld",ID(ki),val[i]); } } /**********************************************************************/ static void groupstats(graph *g, int m, int n, group_node *sz, int *numorbits, int *fixedpts) /* Find the automorphism group of the undirected graph g. Return the group size and number of orbits and fixed points. */ { #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; permutation count[MAXN]; set active[MAXM]; setword workspace[4*MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(permutation,count,count_sz); DYNALLSTAT(set,active,active_sz); DYNALLSTAT(setword,workspace,workspace_sz); #endif int i; int fixed; int numcells,code; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if !MAXN DYNALLOC1(int,lab,lab_sz,n,"groupstats"); DYNALLOC1(int,ptn,ptn_sz,n,"groupstats"); DYNALLOC1(int,orbits,orbits_sz,n,"groupstats"); DYNALLOC1(permutation,count,count_sz,n,"groupstats"); DYNALLOC1(set,active,active_sz,m,"groupstats"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"groupstats"); #endif EMPTYSET(active,m); ADDELEMENT(active,0); numcells = 1; for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n-1] = 0; if (m == 1) refine1(g,lab,ptn,0,&numcells,count,active,&code,1,n); else refine(g,lab,ptn,0,&numcells,count,active,&code,m,n); if (numcells >= n-1) { *numorbits = numcells; *fixedpts = (numcells == n ? n : n-2); sz->groupsize1 = n + 1.0 - numcells; sz->groupsize2 = 0; } else { options.getcanon = FALSE; options.defaultptn = FALSE; EMPTYSET(active,m); nauty(g,lab,ptn,active,orbits,&options,&stats, workspace,4*m,m,n,NULL); *numorbits = stats.numorbits; sz->groupsize1 = stats.grpsize1; sz->groupsize2 = stats.grpsize2; for (i = 0; i < n; ++i) count[i] = 0; fixed = stats.numorbits; for (i = 0; i < n; ++i) if (++count[orbits[i]] == 2) --fixed; *fixedpts = fixed; } } /**********************************************************************/ static void compute(graph *g, int m, int n, int code) /* Compute property i assuming the prerequisites are known. */ { int mind,maxd,mincount,maxcount; int rad,diam; unsigned long ned; boolean eul; group_node sz; int norbs,fixedpts; int minadj,maxadj,minnon,maxnon; switch (code) { case I_e: degstats(g,m,n,&ned,&mind,&mincount,&maxd,&maxcount,&eul); VAL(I_e) = ned; VAL(I_d) = mind; VAL(I_D) = maxd; VAL(I_E) = eul; VAL(I_r) = mind == maxd; COMPUTED(I_e) = COMPUTED(I_d) = COMPUTED(I_D) = TRUE; COMPUTED(I_E) = COMPUTED(I_r) = TRUE; break; case I_b: VAL(I_b) = isbipartite(g,m,n); COMPUTED(I_b) = TRUE; break; case I_g: VAL(I_g) = girth(g,m,n); COMPUTED(I_g) = TRUE; break; case I_z: case I_Z: diamstats(g,m,n,&rad,&diam); VAL(I_z) = rad; VAL(I_Z) = diam; COMPUTED(I_z) = COMPUTED(I_Z) = TRUE; break; case I_a: groupstats(g,m,n,&sz,&norbs,&fixedpts); sz.size = sizeof(long) + sizeof(double); splay_insert(&value_root,TRUE,TOSPLAY(&sz),sizeof(group_node)); VAL(I_a) = (long)value_root; VAL(I_o) = norbs; VAL(I_t) = norbs == 1; VAL(I_F) = fixedpts; COMPUTED(I_a) = COMPUTED(I_o) = TRUE; COMPUTED(I_F) = COMPUTED(I_t) = TRUE; break; case I_c: if (isbiconnected(g,m,n)) VAL(I_c) = 2; else if (isconnected(g,m,n)) VAL(I_c) = 1; else VAL(I_c) = 0; COMPUTED(I_c) = TRUE; break; case I_n: case I_d: case I_D: case I_E: case I_r: case I_o: case I_t: fprintf(stderr,">E Property %d should be known already\n",code); exit(1); case I_Y: VAL(I_Y) = cyclecount(g,m,n); COMPUTED(I_Y) = TRUE; break; case I_T: VAL(I_T) = numtriangles(g,m,n); COMPUTED(I_T) = TRUE; break; case I_i: case I_I: case I_j: case I_J: commonnbrs(g,&minadj,&maxadj,&minnon,&maxnon,m,n); VAL(I_i) = minadj; VAL(I_I) = maxadj; VAL(I_j) = minnon; VAL(I_J) = maxnon; COMPUTED(I_i) = COMPUTED(I_I) = TRUE; COMPUTED(I_j) = COMPUTED(I_J) = TRUE; break; #ifdef USERDEF case I_Q: VAL(I_Q) = USERDEF(g,m,n); COMPUTED(I_Q) = TRUE; break; #endif default: fprintf(stderr,">E Property %d is uncomputable\n",code); exit(1); } } /**********************************************************************/ static boolean group_in_range(group_node *sz, long lo, long hi) /* Test if the group size is in the given range */ { double sz1; int sz2; if (lo != -NOLIMIT) { sz1 = sz->groupsize1; sz2 = sz->groupsize2; while (sz2 >= 0 && sz1 < lo) { --sz2; sz1 *= 10.0; } if (sz2 < 0) return FALSE; } if (hi != NOLIMIT) { sz1 = sz->groupsize1; sz2 = sz->groupsize2; while (sz2 >= 0 && sz1 <= hi) { --sz2; sz1 *= 10.0; } if (sz2 >= 0) return FALSE; } return TRUE; } /**********************************************************************/ static boolean selected(graph *g, int m, int n) /* See if g is selected by the constraints */ { int i; VAL(I_n) = n; COMPUTED(I_n) = TRUE; for (i = 0; i < NUMCONSTRAINTS; ++i) if (ISNEEDED(i)) { if (!COMPUTED(i)) compute(g,m,n,i); if (ISCONSTRAINT(i)) { if (INBOUNDS(i)) { if (INVERSE(i)) return FALSE; } else { if (!INVERSE(i)) return FALSE; } } } return TRUE; } /**********************************************************************/ static void decodekeys(char *s) /* Extract key symbols from -- string */ { int i,j,k; for (i = 0; s[i] != '\0'; ++i) { for (j = 0; j < NUMCONSTRAINTS; ++j) if (s[i] == SYMBOL(j)) break; if (j == NUMCONSTRAINTS) { fprintf(stderr,">E unknown sort key %c\n",s[i]); exit(1); } for (k = 0; k < numkeys; ++k) if (key[k] == j) break; if (k == numkeys) { if (numkeys == MAXKEYS) { fprintf(stderr, ">E too many sort keys, increase MAXKEYS\n"); exit(1); } key[numkeys++] = j; NEEDED(j) |= 1; } } } /**********************************************************************/ int main(int argc, char *argv[]) { graph *g; int m,n,codetype; char *infilename,*outfilename; FILE *infile,*outfile,*countfile; int outcode; long nin,nout; int argnum,i,j; char *arg,sw,*baseptr,*bp; boolean badargs; long pval1,pval2,maxin; boolean fswitch,pswitch,Vswitch,vswitch,qswitch; unsigned long cmask; boolean havecon,neg; double t; HELP; if (sizeof(void*) > sizeof(long)) { fprintf(stderr,">E %s cannot run on this machine.\n",argv[0]); exit(1); } vswitch = qswitch = fswitch = pswitch = FALSE; Vswitch = FALSE; infilename = outfilename = NULL; numkeys = 0; havecon = FALSE; baseptr = argv[0]; for (bp = baseptr; *bp != '\0'; ++bp) if (*bp == '/' || *bp == '\\') baseptr = bp+1; docount = strncmp("countg",baseptr,6) == 0; dofilter = !docount; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('q',qswitch) else SWBOOLEAN('f',fswitch) else SWBOOLEAN('v',vswitch) else SWBOOLEAN('V',Vswitch) else SWRANGE('p',":-",pswitch,pval1,pval2,"-p") else if (sw == '-') { docount = TRUE; decodekeys(arg); while (*arg != '\0') ++arg; } else { if (sw == '~') { neg = TRUE; sw = *arg++; } else neg = FALSE; for (i = 0; i < NUMCONSTRAINTS; ++i) if (sw == SYMBOL(i)) { NEEDED(i) |= 2; if (VALTYPE(i) == INTTYPE || VALTYPE(i) == GROUPSIZE) arg_range(&arg,":-",&LO(i),&HI(i),ID(i)); else LO(i) = HI(i) = 1; if (neg) INVERSE(i) = TRUE; havecon = TRUE; break; } if (i == NUMCONSTRAINTS) badargs = TRUE; } } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (vswitch && !havecon) { fprintf(stderr,">E -v is illegal with no constraints\n"); exit(1); } for (j = NUMCONSTRAINTS; --j >= 0;) if (ISNEEDED(j)) { cmask = PREREQ(j); for (i = 0; cmask != 0; ++i, cmask >>= 1) if (cmask & 1) NEEDED(i) |= 1; } if (vswitch) { for (j = 0; j < NUMCONSTRAINTS; ++j) if (ISCONSTRAINT(j)) INVERSE(j) = !INVERSE(j); } if (!qswitch) { fprintf(stderr,">A %s",argv[0]); if (fswitch || pswitch) fprintf(stderr," -"); if (fswitch) fprintf(stderr,"f"); if (pswitch) writerange(stderr,'p',pval1,pval2); if (numkeys > 0) { fprintf(stderr," --"); for (j = 0; j < numkeys; ++j) fprintf(stderr,"%c",SYMBOL(key[j])); } if (havecon) fprintf(stderr," -"); for (j = 0; j < NUMCONSTRAINTS; ++j) if (ISCONSTRAINT(j)) { if (INVERSE(j)) fprintf(stderr,"~"); if (VALTYPE(j) == BOOLTYPE) fprintf(stderr,"%c",SYMBOL(j)); else writerange(stderr,(int)SYMBOL(j),LO(j),HI(j)); } if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,fswitch, pswitch ? pval1 : 1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (dofilter) countfile = stderr; else countfile = outfile; if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; nin = nout = 0; if (!pswitch || pval2 == NOLIMIT) maxin = NOLIMIT; else if (pval1 < 1) maxin = pval2; else maxin = pval2 - pval1 + 1; t = CPUTIME; while (nin < maxin || maxin == NOLIMIT) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; for (j = 0; j < NUMCONSTRAINTS; ++j) COMPUTED(j) = FALSE; if (selected(g,m,n)) { if (dofilter) writelast(outfile); if (Vswitch) { fprintf(countfile,"Graph %6ld : ",nin); printthesevals(countfile); fprintf(countfile,"\n"); } else if (docount) add_one(); ++nout; } FREES(g); } t = CPUTIME - t; if (docount && !Vswitch) { splay_scan(count_root,countfile); if (qswitch || !dofilter) { fprintf(countfile,"%9ld graphs altogether",nout); if (nin != nout) fprintf(countfile," from %ld read",nin); fprintf(countfile,"; cpu=%.3f sec\n",t); } } if (!qswitch && dofilter) fprintf(stderr, ">Z %ld graphs read from %s; %ld written to %s; %.3f sec\n", nin,infilename,nout,outfilename,t); exit(0); } nauty24r2/configure0000700000604200001440000072042711405400216013212 0ustar bdmusers#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="dreadnaut.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GREP EGREP header_stddef_h header_unistd_h header_stdlib_h header_string_h header_signal_h header_sys_wait_h header_sys_types_h header_errno_h have_pid_t malloc_dec ftell_dec fdopen_dec popen_dec putenv_dec setenv_dec has_math_inf ac_cv_sizeof_int ac_cv_sizeof_long ac_cv_sizeof_long_long MORECFLAGS lok testprogs have_const have_isatty have_times have_time have_gettimeofday have_getrusage have_perror have_pipe have_wait have_popen have_putenv have_setenv stdio_nolock sort_prog sort_newparams_ok LIBOBJS LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} { (exit 1); exit 1; }; } fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} { (exit 1); exit 1; }; } { echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6; } if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 echo "$as_me: error: invalid value of canonical build" >&2;} { (exit 1); exit 1; }; };; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6; } if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} { (exit 1); exit 1; }; } fi fi { echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 echo "$as_me: error: invalid value of canonical host" >&2;} { (exit 1); exit 1; }; };; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac user_cflags="$CFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CFLAGS=$user_cflags MORECFLAGS="" if test x"$user_cflags" = x"" ; then { echo "$as_me:$LINENO: checking if $CC supports -O4 flags" >&5 echo $ECHO_N "checking if $CC supports -O4 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-O4" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -O4" else : fi; if test x"$ac_cv_try_cflags_ok" = x"no"; then { echo "$as_me:$LINENO: checking if $CC supports -O3 flags" >&5 echo $ECHO_N "checking if $CC supports -O3 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-O3" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -O3" else : fi; if test x"$ac_cv_try_cflags_ok" = x"no"; then { echo "$as_me:$LINENO: checking if $CC supports -O2 flags" >&5 echo $ECHO_N "checking if $CC supports -O2 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-O2" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -O2" else CFLAGS="$CFLAGS -O" fi; fi fi if test "$CC" = "gcc" ; then gccver=`gcc --version 2>/dev/null || echo 0.0.0` else gccver=0.0.0 fi case "$host" in *pentium*solaris*) ;; *pentium4*) { echo "$as_me:$LINENO: checking if $CC supports -march=pentium4 flags" >&5 echo $ECHO_N "checking if $CC supports -march=pentium4 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-march=pentium4" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -march=pentium4" else : fi;; *pentium3*|*i686*|*athlon*|x86*) { echo "$as_me:$LINENO: checking if $CC supports -march=i686 flags" >&5 echo $ECHO_N "checking if $CC supports -march=i686 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-march=i686" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -march=i686" else : fi;; *pentium2*|*i586*) { echo "$as_me:$LINENO: checking if $CC supports -march=i586 flags" >&5 echo $ECHO_N "checking if $CC supports -march=i586 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-march=i586" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -march=i586" else : fi;; *powerpc*) machtype=`/usr/bin/machine 2>/dev/null || echo unknown` case "$machtype" in ppc740?) { echo "$as_me:$LINENO: checking if $CC supports -mcpu=7400 flags" >&5 echo $ECHO_N "checking if $CC supports -mcpu=7400 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-mcpu=7400" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -mcpu=7400" else : fi { echo "$as_me:$LINENO: checking if $CC supports -mtune=7400 flags" >&5 echo $ECHO_N "checking if $CC supports -mtune=7400 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-mtune=7400" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -mtune=7400" else : fi;; ppc745?) { echo "$as_me:$LINENO: checking if $CC supports -mcpu=7450 flags" >&5 echo $ECHO_N "checking if $CC supports -mcpu=7450 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-mcpu=7450" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -mcpu=7450" else : fi { echo "$as_me:$LINENO: checking if $CC supports -mtune=7450 flags" >&5 echo $ECHO_N "checking if $CC supports -mtune=7450 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-mtune=7450" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -mtune=7450" else : fi case "$gccver" in *\ 4.[0-9].[0-9]\ *) { echo "$as_me:$LINENO: checking if $CC supports $CFLAGS -fast flags" >&5 echo $ECHO_N "checking if $CC supports $CFLAGS -fast flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fast" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then MORECFLAGS="$MORECFLAGS -fast" else : fi;; esac;; ppc970) { echo "$as_me:$LINENO: checking if $CC supports -mcpu=g5 flags" >&5 echo $ECHO_N "checking if $CC supports -mcpu=g5 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-mcpu=g5" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -mcpu=g5" else : fi { echo "$as_me:$LINENO: checking if $CC supports -mtune=g5 flags" >&5 echo $ECHO_N "checking if $CC supports -mtune=g5 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-mtune=g5" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -mtune=g5" else : fi { echo "$as_me:$LINENO: checking if $CC supports -fast flags" >&5 echo $ECHO_N "checking if $CC supports -fast flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-fast" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$MORECFLAGS -fast" else : fi;; *) { echo "$as_me:$LINENO: checking if $CC supports -mpowerpc flags" >&5 echo $ECHO_N "checking if $CC supports -mpowerpc flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-mpowerpc" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -mpowerpc" else : fi;; esac;; *osf*) { echo "$as_me:$LINENO: checking if $CC supports -fast flags" >&5 echo $ECHO_N "checking if $CC supports -fast flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-fast" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -fast" else : fi;; *sparcv8*|*sparcv9*) { echo "$as_me:$LINENO: checking if $CC supports -msupersparc flags" >&5 echo $ECHO_N "checking if $CC supports -msupersparc flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-msupersparc" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -msupersparc" else : fi if test x"$ac_cv_try_cflags_ok" = x"no"; then { echo "$as_me:$LINENO: checking if $CC supports -cg92 flags" >&5 echo $ECHO_N "checking if $CC supports -cg92 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-cg92" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -cg92" else : fi if test x"$ac_cv_try_cflags_ok" = x"no"; then { echo "$as_me:$LINENO: checking if $CC supports -xcg92 flags" >&5 echo $ECHO_N "checking if $CC supports -xcg92 flags... $ECHO_C" >&6; } SAVE_CFLAGS="$CFLAGS" CFLAGS="-xcg92" if test "$cross_compiling" = yes; then ac_cv_try_cflags_ok=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ main(){exit(0);} _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_try_cflags_ok=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_try_cflags_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$SAVE_CFLAGS" { echo "$as_me:$LINENO: result: $ac_cv_try_cflags_ok" >&5 echo "${ECHO_T}$ac_cv_try_cflags_ok" >&6; } if test x"$ac_cv_try_cflags_ok" = x"yes"; then CFLAGS="$CFLAGS -xcg92" else : fi fi fi;; esac fi echo CFLAGS=$CFLAGS echo MORECFLAGS=$MORECFLAGS { echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_sys_wait_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_WAIT_H 1 _ACEOF fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in stddef.h unistd.h sys/types.h sys/wait.h stdlib.h string.h errno.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test x"$ac_cv_header_stddef_h" = x"yes"; then header_stddef_h=1 else header_stddef_h=0 fi if test x"$ac_cv_header_unistd_h" = x"yes"; then header_unistd_h=1 else header_unistd_h=0 fi if test x"$ac_cv_header_stdlib_h" = x"yes"; then header_stdlib_h=1 else header_stdlib_h=0 fi if test x"$ac_cv_header_string_h" = x"yes"; then header_string_h=1 else header_string_h=0 fi if test x"$ac_cv_header_signal_h" = x"yes"; then header_signal_h=1 else header_signal_h=0 fi if test x"$ac_cv_header_sys_wait_h" = x"yes"; then header_sys_wait_h=1 else header_sys_wait_h=0 fi if test x"$ac_cv_header_sys_types_h" = x"yes"; then header_sys_types_h=1 else header_sys_types_h=0 fi if test x"$ac_cv_header_errno_h" = x"yes"; then header_errno_h=1 else header_errno_h=0 fi { echo "$as_me:$LINENO: checking for pid_t" >&5 echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; } if test "${ac_cv_type_pid_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef pid_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_pid_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_pid_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 echo "${ECHO_T}$ac_cv_type_pid_t" >&6; } if test $ac_cv_type_pid_t = yes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi if test x"$ac_cv_type_pid_t" = x"yes"; then have_pid_t=1 else have_pid_t=0 fi { echo "$as_me:$LINENO: checking if malloc is declared in stdlib.h or malloc.h" >&5 echo $ECHO_N "checking if malloc is declared in stdlib.h or malloc.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])malloc[^a-zA-Z_0-9]" >/dev/null 2>&1; then malloc_dec=1 else malloc_dec=0 fi rm -f conftest* if test $malloc_dec -eq 0; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])malloc[^a-zA-Z_0-9]" >/dev/null 2>&1; then malloc_dec=2 else malloc_dec=0 fi rm -f conftest* fi { echo "$as_me:$LINENO: result: $malloc_dec" >&5 echo "${ECHO_T}$malloc_dec" >&6; } { echo "$as_me:$LINENO: checking if ftell is declared in stdio.h" >&5 echo $ECHO_N "checking if ftell is declared in stdio.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])ftell[^a-zA-Z_0-9]" >/dev/null 2>&1; then ftell_dec=1 else ftell_dec=0 fi rm -f conftest* { echo "$as_me:$LINENO: result: $ftell_dec" >&5 echo "${ECHO_T}$ftell_dec" >&6; } { echo "$as_me:$LINENO: checking if fdopen is declared in stdio.h" >&5 echo $ECHO_N "checking if fdopen is declared in stdio.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])fdopen[^a-zA-Z_0-9]" >/dev/null 2>&1; then fdopen_dec=1 else fdopen_dec=0 fi rm -f conftest* { echo "$as_me:$LINENO: result: $fdopen_dec" >&5 echo "${ECHO_T}$fdopen_dec" >&6; } { echo "$as_me:$LINENO: checking if popen is declared in stdio.h" >&5 echo $ECHO_N "checking if popen is declared in stdio.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])popen[^a-zA-Z_0-9]" >/dev/null 2>&1; then popen_dec=1 else popen_dec=0 fi rm -f conftest* { echo "$as_me:$LINENO: result: $popen_dec" >&5 echo "${ECHO_T}$popen_dec" >&6; } { echo "$as_me:$LINENO: checking if putenv is declared in stdlib.h" >&5 echo $ECHO_N "checking if putenv is declared in stdlib.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])putenv[^a-zA-Z_0-9]" >/dev/null 2>&1; then putenv_dec=1 else putenv_dec=0 fi rm -f conftest* { echo "$as_me:$LINENO: result: $putenv_dec" >&5 echo "${ECHO_T}$putenv_dec" >&6; } { echo "$as_me:$LINENO: checking if setenv is declared in stdlib.h" >&5 echo $ECHO_N "checking if setenv is declared in stdlib.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])setenv[^a-zA-Z_0-9]" >/dev/null 2>&1; then setenv_dec=1 else setenv_dec=0 fi rm -f conftest* { echo "$as_me:$LINENO: result: $setenv_dec" >&5 echo "${ECHO_T}$setenv_dec" >&6; } { echo "$as_me:$LINENO: checking if INFINITY is declared in math.h" >&5 echo $ECHO_N "checking if INFINITY is declared in math.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #ifdef INFINITY yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then has_math_inf=1 else has_math_inf=0 fi rm -f conftest* { echo "$as_me:$LINENO: result: $has_math_inf" >&5 echo "${ECHO_T}$has_math_inf" >&6; } { echo "$as_me:$LINENO: checking for int" >&5 echo $ECHO_N "checking for int... $ECHO_C" >&6; } if test "${ac_cv_type_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_int=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_int=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 echo "${ECHO_T}$ac_cv_type_int" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of int" >&5 echo $ECHO_N "checking size of int... $ECHO_C" >&6; } if test "${ac_cv_sizeof_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_int=$ac_lo;; '') if test "$ac_cv_type_int" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int=0 fi ;; esac else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_int=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_int" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 echo "${ECHO_T}$ac_cv_sizeof_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF { echo "$as_me:$LINENO: checking for long" >&5 echo $ECHO_N "checking for long... $ECHO_C" >&6; } if test "${ac_cv_type_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 echo "${ECHO_T}$ac_cv_type_long" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of long" >&5 echo $ECHO_N "checking size of long... $ECHO_C" >&6; } if test "${ac_cv_sizeof_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long=$ac_lo;; '') if test "$ac_cv_type_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long=0 fi ;; esac else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF { echo "$as_me:$LINENO: checking for long long" >&5 echo $ECHO_N "checking for long long... $ECHO_C" >&6; } if test "${ac_cv_type_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_long_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 echo "${ECHO_T}$ac_cv_type_long_long" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of long long" >&5 echo $ECHO_N "checking size of long long... $ECHO_C" >&6; } if test "${ac_cv_sizeof_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long_long=$ac_lo;; '') if test "$ac_cv_type_long_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long_long=0 fi ;; esac else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_long_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long_long=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long _ACEOF lok=0 testprogs="dreadtest dreadtestS dreadtestS1 dreadtest4K" testprogs="$testprogs dreadtest1 dreadtestW1" if test $ac_cv_sizeof_long_long -eq 8; then lok=1 testprogs="$testprogs dreadtestL1 dreadtestL" else if test $ac_cv_sizeof_long -eq 8; then lok=1 fi fi { echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi if test x"$ac_cv_c_const" = x"yes"; then have_const=1 else have_const=0 fi { echo "$as_me:$LINENO: checking for isatty" >&5 echo $ECHO_N "checking for isatty... $ECHO_C" >&6; } if test "${ac_cv_func_isatty+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define isatty to an innocuous variant, in case declares isatty. For example, HP-UX 11i declares gettimeofday. */ #define isatty innocuous_isatty /* System header to define __stub macros and hopefully few prototypes, which can conflict with char isatty (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef isatty /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char isatty (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_isatty || defined __stub___isatty choke me #endif int main () { return isatty (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_isatty=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_isatty=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_isatty" >&5 echo "${ECHO_T}$ac_cv_func_isatty" >&6; } if test $ac_cv_func_isatty = yes; then have_isatty=1 else have_isatty=0 fi { echo "$as_me:$LINENO: checking for times" >&5 echo $ECHO_N "checking for times... $ECHO_C" >&6; } if test "${ac_cv_func_times+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define times to an innocuous variant, in case declares times. For example, HP-UX 11i declares gettimeofday. */ #define times innocuous_times /* System header to define __stub macros and hopefully few prototypes, which can conflict with char times (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef times /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char times (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_times || defined __stub___times choke me #endif int main () { return times (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_times=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_times=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_times" >&5 echo "${ECHO_T}$ac_cv_func_times" >&6; } if test $ac_cv_func_times = yes; then have_times=1 else have_times=0 fi { echo "$as_me:$LINENO: checking for time" >&5 echo $ECHO_N "checking for time... $ECHO_C" >&6; } if test "${ac_cv_func_time+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define time to an innocuous variant, in case declares time. For example, HP-UX 11i declares gettimeofday. */ #define time innocuous_time /* System header to define __stub macros and hopefully few prototypes, which can conflict with char time (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef time /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char time (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_time || defined __stub___time choke me #endif int main () { return time (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_time=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_time=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_time" >&5 echo "${ECHO_T}$ac_cv_func_time" >&6; } if test $ac_cv_func_time = yes; then have_time=1 else have_time=0 fi { echo "$as_me:$LINENO: checking for gettimeofday" >&5 echo $ECHO_N "checking for gettimeofday... $ECHO_C" >&6; } if test "${ac_cv_func_gettimeofday+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gettimeofday to an innocuous variant, in case declares gettimeofday. For example, HP-UX 11i declares gettimeofday. */ #define gettimeofday innocuous_gettimeofday /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gettimeofday (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef gettimeofday /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gettimeofday (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_gettimeofday || defined __stub___gettimeofday choke me #endif int main () { return gettimeofday (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_gettimeofday=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gettimeofday=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_gettimeofday" >&5 echo "${ECHO_T}$ac_cv_func_gettimeofday" >&6; } if test $ac_cv_func_gettimeofday = yes; then have_gettimeofday=1 else have_gettimeofday=0 fi { echo "$as_me:$LINENO: checking for times" >&5 echo $ECHO_N "checking for times... $ECHO_C" >&6; } if test "${ac_cv_func_times+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define times to an innocuous variant, in case declares times. For example, HP-UX 11i declares gettimeofday. */ #define times innocuous_times /* System header to define __stub macros and hopefully few prototypes, which can conflict with char times (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef times /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char times (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_times || defined __stub___times choke me #endif int main () { return times (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_times=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_times=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_times" >&5 echo "${ECHO_T}$ac_cv_func_times" >&6; } if test $ac_cv_func_times = yes; then have_times=1 else have_times=0 fi { echo "$as_me:$LINENO: checking for getrusage" >&5 echo $ECHO_N "checking for getrusage... $ECHO_C" >&6; } if test "${ac_cv_func_getrusage+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define getrusage to an innocuous variant, in case declares getrusage. For example, HP-UX 11i declares gettimeofday. */ #define getrusage innocuous_getrusage /* System header to define __stub macros and hopefully few prototypes, which can conflict with char getrusage (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef getrusage /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getrusage (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_getrusage || defined __stub___getrusage choke me #endif int main () { return getrusage (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_getrusage=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_getrusage=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_getrusage" >&5 echo "${ECHO_T}$ac_cv_func_getrusage" >&6; } if test $ac_cv_func_getrusage = yes; then have_getrusage=1 else have_getrusage=0 fi { echo "$as_me:$LINENO: checking for perror" >&5 echo $ECHO_N "checking for perror... $ECHO_C" >&6; } if test "${ac_cv_func_perror+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define perror to an innocuous variant, in case declares perror. For example, HP-UX 11i declares gettimeofday. */ #define perror innocuous_perror /* System header to define __stub macros and hopefully few prototypes, which can conflict with char perror (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef perror /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char perror (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_perror || defined __stub___perror choke me #endif int main () { return perror (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_perror=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_perror=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_perror" >&5 echo "${ECHO_T}$ac_cv_func_perror" >&6; } if test $ac_cv_func_perror = yes; then have_perror=1 else have_perror=0 fi { echo "$as_me:$LINENO: checking for pipe" >&5 echo $ECHO_N "checking for pipe... $ECHO_C" >&6; } if test "${ac_cv_func_pipe+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define pipe to an innocuous variant, in case declares pipe. For example, HP-UX 11i declares gettimeofday. */ #define pipe innocuous_pipe /* System header to define __stub macros and hopefully few prototypes, which can conflict with char pipe (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef pipe /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pipe (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_pipe || defined __stub___pipe choke me #endif int main () { return pipe (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_pipe=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_pipe=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_pipe" >&5 echo "${ECHO_T}$ac_cv_func_pipe" >&6; } if test $ac_cv_func_pipe = yes; then have_pipe=1 else have_pipe=0 fi { echo "$as_me:$LINENO: checking for wait" >&5 echo $ECHO_N "checking for wait... $ECHO_C" >&6; } if test "${ac_cv_func_wait+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define wait to an innocuous variant, in case declares wait. For example, HP-UX 11i declares gettimeofday. */ #define wait innocuous_wait /* System header to define __stub macros and hopefully few prototypes, which can conflict with char wait (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef wait /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char wait (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_wait || defined __stub___wait choke me #endif int main () { return wait (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_wait=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_wait=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_wait" >&5 echo "${ECHO_T}$ac_cv_func_wait" >&6; } if test $ac_cv_func_wait = yes; then have_wait=1 else have_wait=0 fi { echo "$as_me:$LINENO: checking for popen" >&5 echo $ECHO_N "checking for popen... $ECHO_C" >&6; } if test "${ac_cv_func_popen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define popen to an innocuous variant, in case declares popen. For example, HP-UX 11i declares gettimeofday. */ #define popen innocuous_popen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char popen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef popen /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char popen (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_popen || defined __stub___popen choke me #endif int main () { return popen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_popen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_popen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_popen" >&5 echo "${ECHO_T}$ac_cv_func_popen" >&6; } if test $ac_cv_func_popen = yes; then have_popen=1 else have_popen=0 fi { echo "$as_me:$LINENO: checking for putenv" >&5 echo $ECHO_N "checking for putenv... $ECHO_C" >&6; } if test "${ac_cv_func_putenv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define putenv to an innocuous variant, in case declares putenv. For example, HP-UX 11i declares gettimeofday. */ #define putenv innocuous_putenv /* System header to define __stub macros and hopefully few prototypes, which can conflict with char putenv (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef putenv /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char putenv (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_putenv || defined __stub___putenv choke me #endif int main () { return putenv (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_putenv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_putenv=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_putenv" >&5 echo "${ECHO_T}$ac_cv_func_putenv" >&6; } if test $ac_cv_func_putenv = yes; then have_putenv=1 else have_putenv=0 fi { echo "$as_me:$LINENO: checking for setenv" >&5 echo $ECHO_N "checking for setenv... $ECHO_C" >&6; } if test "${ac_cv_func_setenv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define setenv to an innocuous variant, in case declares setenv. For example, HP-UX 11i declares gettimeofday. */ #define setenv innocuous_setenv /* System header to define __stub macros and hopefully few prototypes, which can conflict with char setenv (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef setenv /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char setenv (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_setenv || defined __stub___setenv choke me #endif int main () { return setenv (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_setenv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_setenv=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_setenv" >&5 echo "${ECHO_T}$ac_cv_func_setenv" >&6; } if test $ac_cv_func_setenv = yes; then have_setenv=1 else have_setenv=0 fi { echo "$as_me:$LINENO: checking for getc_unlocked" >&5 echo $ECHO_N "checking for getc_unlocked... $ECHO_C" >&6; } if test "${ac_cv_func_getc_unlocked+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define getc_unlocked to an innocuous variant, in case declares getc_unlocked. For example, HP-UX 11i declares gettimeofday. */ #define getc_unlocked innocuous_getc_unlocked /* System header to define __stub macros and hopefully few prototypes, which can conflict with char getc_unlocked (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef getc_unlocked /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getc_unlocked (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_getc_unlocked || defined __stub___getc_unlocked choke me #endif int main () { return getc_unlocked (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_getc_unlocked=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_getc_unlocked=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_getc_unlocked" >&5 echo "${ECHO_T}$ac_cv_func_getc_unlocked" >&6; } if test $ac_cv_func_getc_unlocked = yes; then have_getc_unlocked=1 else have_getc_unlocked=0 fi { echo "$as_me:$LINENO: checking for flockfile" >&5 echo $ECHO_N "checking for flockfile... $ECHO_C" >&6; } if test "${ac_cv_func_flockfile+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define flockfile to an innocuous variant, in case declares flockfile. For example, HP-UX 11i declares gettimeofday. */ #define flockfile innocuous_flockfile /* System header to define __stub macros and hopefully few prototypes, which can conflict with char flockfile (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef flockfile /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char flockfile (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_flockfile || defined __stub___flockfile choke me #endif int main () { return flockfile (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_flockfile=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_flockfile=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_flockfile" >&5 echo "${ECHO_T}$ac_cv_func_flockfile" >&6; } if test $ac_cv_func_flockfile = yes; then have_flockfile=1 else have_flockfile=0 fi if test $have_getc_unlocked -a $have_flockfile; then stdio_nolock=1 else stdio_nolock=0 fi for ac_prog in gsort sort do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_sort_prog+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$sort_prog"; then ac_cv_prog_sort_prog="$sort_prog" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_sort_prog="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi sort_prog=$ac_cv_prog_sort_prog if test -n "$sort_prog"; then { echo "$as_me:$LINENO: result: $sort_prog" >&5 echo "${ECHO_T}$sort_prog" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$sort_prog" && break done test -n "$sort_prog" || sort_prog="no_sort_found" { echo "$as_me:$LINENO: checking if sort supports the -k switch" >&5 echo $ECHO_N "checking if sort supports the -k switch... $ECHO_C" >&6; } if { $sort_prog -k 2,3 /dev/null 2>&1 ; } ; then sort_newparams_ok=1 else sort_newparams_ok=0 fi { echo "$as_me:$LINENO: result: $sort_newparams_ok" >&5 echo "${ECHO_T}$sort_newparams_ok" >&6; } ac_config_files="$ac_config_files makefile:makefile.in nauty.h:nauty-h.in naututil.h:naututil-h.in gtools.h:gtools-h.in" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "makefile") CONFIG_FILES="$CONFIG_FILES makefile:makefile.in" ;; "nauty.h") CONFIG_FILES="$CONFIG_FILES nauty.h:nauty-h.in" ;; "naututil.h") CONFIG_FILES="$CONFIG_FILES naututil.h:naututil-h.in" ;; "gtools.h") CONFIG_FILES="$CONFIG_FILES gtools.h:gtools-h.in" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim build!$build$ac_delim build_cpu!$build_cpu$ac_delim build_vendor!$build_vendor$ac_delim build_os!$build_os$ac_delim host!$host$ac_delim host_cpu!$host_cpu$ac_delim host_vendor!$host_vendor$ac_delim host_os!$host_os$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim header_stddef_h!$header_stddef_h$ac_delim header_unistd_h!$header_unistd_h$ac_delim header_stdlib_h!$header_stdlib_h$ac_delim header_string_h!$header_string_h$ac_delim header_signal_h!$header_signal_h$ac_delim header_sys_wait_h!$header_sys_wait_h$ac_delim header_sys_types_h!$header_sys_types_h$ac_delim header_errno_h!$header_errno_h$ac_delim have_pid_t!$have_pid_t$ac_delim malloc_dec!$malloc_dec$ac_delim ftell_dec!$ftell_dec$ac_delim fdopen_dec!$fdopen_dec$ac_delim popen_dec!$popen_dec$ac_delim putenv_dec!$putenv_dec$ac_delim setenv_dec!$setenv_dec$ac_delim has_math_inf!$has_math_inf$ac_delim ac_cv_sizeof_int!$ac_cv_sizeof_int$ac_delim ac_cv_sizeof_long!$ac_cv_sizeof_long$ac_delim ac_cv_sizeof_long_long!$ac_cv_sizeof_long_long$ac_delim MORECFLAGS!$MORECFLAGS$ac_delim lok!$lok$ac_delim testprogs!$testprogs$ac_delim have_const!$have_const$ac_delim have_isatty!$have_isatty$ac_delim have_times!$have_times$ac_delim have_time!$have_time$ac_delim have_gettimeofday!$have_gettimeofday$ac_delim have_getrusage!$have_getrusage$ac_delim have_perror!$have_perror$ac_delim have_pipe!$have_pipe$ac_delim have_wait!$have_wait$ac_delim have_popen!$have_popen$ac_delim have_putenv!$have_putenv$ac_delim have_setenv!$have_setenv$ac_delim stdio_nolock!$stdio_nolock$ac_delim sort_prog!$sort_prog$ac_delim sort_newparams_ok!$sort_newparams_ok$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 94; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi nauty24r2/directg.c0000600000604200001440000003444511274163463013106 0ustar bdmusers/* directg.c version 1.3; B D McKay, march 3, 2009 */ #define USAGE \ "directg [-q] [-u|-T|-G] [-V] [-o] [-f#] [-e#|-e#:#] [infile [outfile]]" #define HELPTEXT \ " Read undirected graphs and orient their edges in all possible ways.\n\ Edges can be oriented in either or both directions (3 possibilities).\n\ Isomorphic directed graphs derived from the same input are suppressed.\n\ If the input graphs are non-isomorphic then the output graphs are also.\n\ \n\ -e# | -e#:# specify a value or range of the total number of arcs\n\ -o orient each edge in only one direction, never both\n\ -f# Use only the subgroup that fixes the first # vertices setwise\n\ \n\ -T use a simple text output format (nv ne edges) instead of digraph6\n\ -G like -T but includes group size as third item (if less than 10^10)\n\ The group size does not include exchange of isolated vertices.\n\ -V only output graphs with nontrivial groups (including exchange of\n\ isolated vertices). The -f option is respected.\n\ -u no output, just count them\n\ -q suppress auxiliary information\n" /*************************************************************************/ #include "gtools.h" #include "naugroup.h" typedef struct { long hi,lo; } bigint; #define ZEROBIG(big) big.hi = big.lo = 0L #define ADDBIG(big,extra) if ((big.lo += (extra)) >= 1000000000L) \ { ++big.hi; big.lo -= 1000000000L;} #define PRINTBIG(file,big) if (big.hi == 0) \ fprintf(file,"%ld",big.lo); else fprintf(file,"%ld%09ld",big.hi,big.lo) static bigint nin,ngen,nout; FILE *outfile; #define MAXNV 128 #define MAXNE 1024 static int v0[MAXNE],v1[MAXNE]; static int edgeno[MAXNV][MAXNV]; #define MAXME ((2*MAXNE+WORDSIZE-1)/WORDSIZE) static set x[MAXME]; static int ix[2*MAXNE],nix; static boolean first; static int me; static permutation lastreject[MAXNV]; static boolean lastrejok; static int rejectlevel; static unsigned long groupsize; static unsigned long newgroupsize; static boolean Gswitch,Vswitch,ntgroup,ntisol; /* DEGPRUNE feature * * If DEGPRUNE is defined it must have a value equal to the name of a * procedure to be supplied by the user and linked to this program. * The prototype must be * int DEGPRUNE(int *indeg, int outdeg*, int v, int n) * Here n is the number of vertices altogether, and v (0..n-1) is the * number of one vertex. At this point in the program, some directed * edges have been inserted, and the indegrees and outdegrees have the * values given in indeg[] and outdeg[]. Moreover, it is known that * no further edges will be added to or from v, so indeg[v] and outdeg[v] * are final. If DEGPRUNE returns a non-zero value, this branch of the * search will be abandoned. * Before any graph is output, DEGPRUNE will have been called for every * vertex, but it cannot be assumed that DEGPRUNE will be called in order * of vertex number. */ #ifdef DEGPRUNE static int lastlev[MAXNV],indeg[MAXNV],outdeg[MAXNV]; extern int DEGPRUNE(int*,int*,int,int); #endif /* #define GROUPTEST */ #ifdef GROUPTEST static long long totallab; #endif /**************************************************************************/ void writeautom(permutation *p, int n) /* Called by allgroup. */ { int i; for (i = 0; i < n; ++i) printf(" %2d",p[i]); printf("\n"); } /**************************************************************************/ static boolean ismax(permutation *p, int n) /* test if x^p <= x */ { int i,j,k; set px[MAXME]; EMPTYSET(px,me); for (j = 0; j < nix; ++j) { i = ix[j]; k = i >> 1; if (i & 1) ADDELEMENT(px,edgeno[p[v1[k]]][p[v0[k]]]); else ADDELEMENT(px,edgeno[p[v0[k]]][p[v1[k]]]); if (px[0] > x[0]) { rejectlevel = k; return FALSE; } } rejectlevel = MAXNE+1; if (px[0] < x[0]) return TRUE; for (i = 1; i < me; ++i) if (px[i] > x[i]) return FALSE; else if (px[i] < x[i]) return TRUE; ++newgroupsize; ntgroup = TRUE; return TRUE; } /**************************************************************************/ void testmax(permutation *p, int n, int *abort) /* Called by allgroup2. */ { int i; if (first) { /* only the identity */ first = FALSE; return; } if (!ismax(p,n)) { *abort = 1; for (i = 0; i < n; ++i) lastreject[i] = p[i]; lastrejok = TRUE; } } /**************************************************************************/ static int trythisone(grouprec *group, int ne, int n) { int i,k; boolean accept; first = TRUE; ADDBIG(ngen,1); nix = ne; newgroupsize = 1; ntgroup = FALSE; if (!group || groupsize == 1) accept = TRUE; else if (lastrejok && !ismax(lastreject,n)) accept = FALSE; else if (lastrejok && groupsize == 2) accept = TRUE; else { newgroupsize = 1; ntgroup = FALSE; if (allgroup2(group,testmax) == 0) accept = TRUE; else accept = FALSE; } if (accept) { #ifdef GROUPTEST if (groupsize % newgroupsize != 0) gt_abort("group size error\n"); totallab += groupsize/newgroupsize; #endif if (Vswitch && !ntisol && !ntgroup) return MAXNE+1; ADDBIG(nout,1); if (outfile) { fprintf(outfile,"%d %d",n,ne); if (Gswitch) fprintf(outfile," %lu",newgroupsize); for (i = -1; (i = nextelement(x,me,i)) >= 0; ) { k = i >> 1; if (i & 1) fprintf(outfile," %d %d",v1[k],v0[k]); else fprintf(outfile," %d %d",v0[k],v1[k]); } fprintf(outfile,"\n"); } return MAXNE+1; } else return rejectlevel; } /**************************************************************************/ static int scan(int level, int ne, int minarcs, int maxarcs, int sofar, boolean oriented, grouprec *group, int n) /* Main recursive scan; returns the level to return to. */ { int k,retlev; #ifdef DEGPRUNE int w0,w1; w0 = v0[level]; w1 = v1[level]; #endif if (level == ne) { retlev = trythisone(group,sofar,n); return retlev; } if (oriented || sofar + 1 + 2*(ne - level - 1) >= minarcs) { k = 2*level; ADDELEMENT(x,k); ix[sofar] = k; #ifdef DEGPRUNE ++outdeg[w0]; ++indeg[w1]; if (lastlev[w0] == level && DEGPRUNE(indeg,outdeg,w0,n) || lastlev[w1] == level && DEGPRUNE(indeg,outdeg,w1,n)) retlev = level; else #endif retlev = scan(level+1,ne,minarcs,maxarcs,sofar+1,oriented,group,n); DELELEMENT(x,k); #ifdef DEGPRUNE --outdeg[w0]; --indeg[w1]; #endif if (retlev < level) return retlev; ++k; ADDELEMENT(x,k); ix[sofar] = k; #ifdef DEGPRUNE ++outdeg[w1]; ++indeg[w0]; if (lastlev[w0] == level && DEGPRUNE(indeg,outdeg,w0,n) || lastlev[w1] == level && DEGPRUNE(indeg,outdeg,w1,n)) retlev = level; else #endif retlev = scan(level+1,ne,minarcs,maxarcs,sofar+1,oriented,group,n); DELELEMENT(x,k); #ifdef DEGPRUNE --outdeg[w1]; --indeg[w0]; #endif if (retlev < level) return retlev; } if (!oriented && sofar + 2 + ne - level - 1 <= maxarcs) { k = 2*level; ADDELEMENT(x,k); ADDELEMENT(x,k+1); ix[sofar] = k; ix[sofar+1] = k+1; #ifdef DEGPRUNE ++indeg[w0]; ++indeg[w1]; ++outdeg[w0]; ++outdeg[w1]; if (lastlev[w0] == level && DEGPRUNE(indeg,outdeg,w0,n) || lastlev[w1] == level && DEGPRUNE(indeg,outdeg,w1,n)) retlev = level; else #endif retlev = scan(level+1,ne,minarcs,maxarcs,sofar+2,oriented,group,n); DELELEMENT(x,k+1); DELELEMENT(x,k); #ifdef DEGPRUNE --indeg[w0]; --indeg[w1]; --outdeg[w0]; --outdeg[w1]; #endif if (retlev < level) return retlev; } return level-1; } /**************************************************************************/ static void direct(graph *g, int nfixed, long minarcs, long maxarcs, boolean oriented, int m, int n) { static DEFAULTOPTIONS_GRAPH(options); statsblk stats; setword workspace[100]; grouprec *group; long ne; int i,j,k,j0,j1,deg; int isol0,isol1; /* isolated vertices before and after nfixed */ set *gi; int lab[MAXNV],ptn[MAXNV],orbits[MAXNV]; set active[(MAXNV+WORDSIZE-1)/WORDSIZE]; nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); j0 = -1; /* last vertex with degree 0 */ j1 = n; /* first vertex with degree > 0 */ isol0 = isol1 = 0; ne = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { deg = 0; for (j = 0; j < m; ++j) deg += POPCOUNT(gi[j]); if (deg == 0) { lab[++j0] = i; if (i < nfixed) ++isol0; else ++isol1; } else lab[--j1] = i; ne += deg; } ne /= 2; ntisol = (isol0 >= 2 || isol1 >= 2); me = (2*ne + WORDSIZE - 1) / WORDSIZE; if (me == 0) me = 1; EMPTYSET(x,me); if (ne == 0 && minarcs <= 0 && (!Vswitch || ntisol)) { trythisone(NULL,0,n); return; } if (oriented) { if (maxarcs < ne || minarcs > ne) return; } else { if (maxarcs < ne || minarcs > 2*ne) return; } if (n > MAXNV || ne > MAXNE) { fprintf(stderr,">E directg: MAXNV or MAXNE exceeded\n"); exit(1); } for (i = 0; i < n; ++i) ptn[i] = 1; ptn[n-1] = 0; EMPTYSET(active,m); ADDELEMENT(active,0); for (i = 0; i <= j0; ++i) { if (i < n-1) ADDELEMENT(active,i+1); ptn[i] = 0; } for (i = j0+1; i < n; ++i) if (lab[i] < nfixed) break; if (i != j0+1 && i != n) { ptn[i-1] = 0; ADDELEMENT(active,i); } options.defaultptn = FALSE; options.userautomproc = groupautomproc; options.userlevelproc = grouplevelproc; nauty(g,lab,ptn,active,orbits,&options,&stats,workspace,100,m,n,NULL); if (stats.grpsize2 == 0) groupsize = stats.grpsize1 + 0.1; else groupsize = 0; if (Vswitch && groupsize == 1 && !ntisol) return; group = groupptr(FALSE); makecosetreps(group); #ifdef DEGPRUNE for (i = 0; i < n; ++i) indeg[i] = outdeg[i] = 0; for (i = 0; i <= j0; ++i) if (DEGPRUNE(indeg,outdeg,lab[i],n)) return; #endif k = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { for (j = i; (j = nextelement(gi,m,j)) >= 0; ) { v0[k] = i; v1[k] = j; #ifdef DEGPRUNE lastlev[i] = lastlev[j] = k; #endif edgeno[i][j] = 2*k; edgeno[j][i] = 2*k+1; ++k; } } lastrejok = FALSE; scan(0,ne,minarcs,maxarcs,0,oriented,group,n); } /**************************************************************************/ main(int argc, char *argv[]) { graph *g; int m,n,codetype; int argnum,j,outcode,nfixed; char *arg,sw,*fmt; boolean badargs; boolean Tswitch,uswitch,eswitch,qswitch,oswitch,fswitch; long minarcs,maxarcs; double t; char *infilename,*outfilename; FILE *infile; char msg[201]; int msglen; HELP; nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); Tswitch = Gswitch = fswitch = Vswitch = FALSE; uswitch = eswitch = oswitch = qswitch = FALSE; infilename = outfilename = NULL; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('o',oswitch) else SWBOOLEAN('q',qswitch) else SWBOOLEAN('u',uswitch) else SWBOOLEAN('T',Tswitch) else SWBOOLEAN('G',Gswitch) else SWBOOLEAN('V',Vswitch) else SWINT('f',fswitch,nfixed,"directg -f") else SWRANGE('e',":-",eswitch,minarcs,maxarcs,"directg -e") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if ((Gswitch!=0) + (Tswitch!=0) + (uswitch!=0) >= 2) gt_abort(">E directg: -G, -T and -u are incompatible\n"); if (!Tswitch && !Gswitch && !uswitch) gt_abort( ">E directg: digraph6 output is unimplemented; use -T or -G\n"); if (!eswitch) { minarcs = 0; maxarcs = NOLIMIT; } if (!fswitch) nfixed = 0; if (!qswitch) { msg[0] = '\0'; CATMSG0(">A directg"); if (eswitch || oswitch || uswitch || fswitch) CATMSG0(" -"); if (oswitch) CATMSG0("o"); if (uswitch) CATMSG0("u"); if (Tswitch) CATMSG0("T"); if (Gswitch) CATMSG0("G"); if (Vswitch) CATMSG0("V"); if (fswitch) CATMSG1("f%d",nfixed); if (eswitch) CATMSG2("e%ld:%ld",minarcs,maxarcs); msglen = strlen(msg); if (argnum > 0) msglen += strlen(infilename); if (argnum > 1) msglen += strlen(outfilename); if (msglen >= 196) { fputs(msg,stderr); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); } else { if (argnum > 0) CATMSG1(" %s",infilename); if (argnum > 1) CATMSG1(" %s",outfilename); CATMSG0("\n"); fputs(msg,stderr); } fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (uswitch) outfile = NULL; else { if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } } ZEROBIG(nin); ZEROBIG(ngen); ZEROBIG(nout); t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ADDBIG(nin,1); direct(g,nfixed,minarcs,maxarcs,oswitch,m,n); FREES(g); } t = CPUTIME - t; if (!qswitch) { fprintf(stderr,">Z "); PRINTBIG(stderr,nin); fprintf(stderr," graphs read from %s",infilename); /* fprintf(stderr,"; "); PRINTBIG(stderr,ngen); fprintf(stderr,"; %lu digraphs tested",ngen); */ fprintf(stderr,"; "); PRINTBIG(stderr,nout); if (!uswitch) fprintf(stderr," digraphs written to %s",outfilename); else fprintf(stderr," digraphs generated"); fprintf(stderr,"; %.2f sec\n",t); } #ifdef GROUPTEST fprintf(stderr,"Group test = %lld\n",totallab); #endif exit(0); } nauty24r2/gtools.h0000600000604200001440000001620611405400216012756 0ustar bdmusers/***************************************************************************** * This is the main header file for gtools. nauty version 2.4. * * gtools.h. Generated from gtools-h.in by configure. *****************************************************************************/ /* The parts between the ==== lines are modified by configure when creating gtools.h out of gtools-h.in. If configure is not being used, it is necessary to check they are correct. ====================================================================*/ #ifndef _GTOOLS_H_ /* only process this file once */ #define _GTOOLS_H_ #define HAVE_ERRNO_H 1 /* exists */ #define HAVE_PERROR 1 /* perror() exists */ #define HAVE_PIPE 1 /* pipe() exists */ #define HAVE_WAIT 1 /* wait() exists */ #define HAVE_POPEN 1 /* popen() and pclose() exist */ #define POPEN_DEC 1 /* popen() is declared in stdio.h */ #define FTELL_DEC 1 /* ftell() is declared in stdio.h */ #define FDOPEN_DEC 1 /* fdopen() is declared in stdio.h */ #define SORTPROG "gsort" /* name of sort program */ #define SORT_NEWKEY 1 /* if -k is supported */ #define HAVE_PID_T 1 /* pid_t is defined */ #define PUTENV_DEC 1 /* putenv() is declared in stdlib.h */ #define SETENV_DEC 1 /* setenv() is declared in stdlib.h */ #define HAVE_PUTENV 1 /* putenv() exists */ #define HAVE_SETENV 1 /* setenv() exists */ /* @edit_msg@ */ /*==================================================================*/ #ifndef MAXN #define MAXN 0 #endif #define SIZELEN(n) ((n)<=SMALLN?1:((n)<=SMALLISHN?4:8)) /* length of size code in bytes */ #define G6LEN(n) (((n)*((n)-1)/2+5)/6+SIZELEN(n)) /* exactly graph6 string length excluding \n\0 */ #include "naututil.h" /* which includes stdio.h */ #include "nausparse.h" #if HAVE_ERRNO_H #include #else extern int errno; #endif #if HAVE_PERROR #define ABORT(msg) do {if (errno != 0) perror(msg); exit(1);} while(0) #else #define ABORT(msg) do {exit(1);} while(0) #endif #if PUTENV_DEC && HAVE_PUTENV #define SET_C_COLLATION putenv("LC_COLLATE=C") #elif SETENV_DEC && HAVE_SETENV #define SET_C_COLLATION setenv("LC_COLLATE","C",1) #elif HAVE_PUTENV int putenv(char*); #define SET_C_COLLATION putenv("LC_COLLATE=C") #elif HAVE_SETENV int setenv(const char*,const char*,int); #define SET_C_COLLATION setenv("LC_COLLATE","C",1) #else #define SET_C_COLLATION #endif #if HAS_STDIO_UNLOCK && !defined(NAUTY_IN_MAGMA) && !defined(IS_JAVA) #define FLOCKFILE(f) flockfile(f) #define FUNLOCKFILE(f) funlockfile(f) #define GETC(f) getc_unlocked(f) #undef PUTC #define PUTC(c,f) putc_unlocked(c,f) #else #define FLOCKFILE(f) #define FUNLOCKFILE(f) #define GETC(f) getc(f) #undef PUTC #define PUTC(c,f) putc(c,f) #endif #define BIAS6 63 #define MAXBYTE 126 #define SMALLN 62 #define SMALLISHN 258047 #define TOPBIT6 32 #define C6MASK 63 #define GRAPH6_HEADER ">>graph6<<" #define SPARSE6_HEADER ">>sparse6<<" #define PLANARCODE_HEADER ">>planar_code<<" #define PLANARCODELE_HEADER ">>planar_code le<<" #define PLANARCODEBE_HEADER ">>planar_code be<<" #define EDGECODE_HEADER ">>edge_code<<" #define GRAPH6 1 #define SPARSE6 2 #define PLANARCODE 4 #define PLANARCODELE 8 #define PLANARCODEBE 16 #define EDGECODE 32 #define PLANARCODEANY (PLANARCODE|PLANARCODELE|PLANARCODEBE) #define UNKNOWN_TYPE 256 #define HAS_HEADER 512 #define ARG_OK 0 #define ARG_MISSING 1 #define ARG_TOOBIG 2 #define ARG_ILLEGAL 3 #define MAXARG 2000000000L #define NOLIMIT (MAXARG+31L) #define SWBOOLEAN(c,bool) if (sw==c) bool=TRUE; #define SWINT(c,bool,val,id) if (sw==c) \ {bool=TRUE;arg_int(&arg,&val,id);} #define SWLONG(c,bool,val,id) if (sw==c) \ {bool=TRUE;arg_long(&arg,&val,id);} #define SWRANGE(c,sep,bool,val1,val2,id) if (sw==c) \ {bool=TRUE;arg_range(&arg,sep,&val1,&val2,id);} #ifdef HELPTEXT2 #define PUTHELPTEXT printf("\nUsage: %s\n\n%s",USAGE,HELPTEXT1);\ printf("%s",HELPTEXT2); #else #define PUTHELPTEXT printf("\nUsage: %s\n\n%s",USAGE,HELPTEXT) #endif #define HELP if (argc > 1 && (strcmp(argv[1],"-help")==0 \ || strcmp(argv[1],"/?")==0 \ || strcmp(argv[1],"--help")==0)) \ { PUTHELPTEXT; return 0;} #define GETHELP \ fprintf(stderr," Use %s -help to see more detailed instructions.\n",argv[0]) #define alloc_error gt_abort #define CATMSG0(fmt) sprintf(msg+strlen(msg),fmt) #define CATMSG1(fmt,x1) sprintf(msg+strlen(msg),fmt,x1) #define CATMSG2(fmt,x1,x2) sprintf(msg+strlen(msg),fmt,x1,x2) #define CATMSG3(fmt,x1,x2,x3) sprintf(msg+strlen(msg),fmt,x1,x2,x3) #define CATMSG4(fmt,x1,x2,x3,x4) sprintf(msg+strlen(msg),fmt,x1,x2,x3,x4) #define CATMSG5(fmt,x1,x2,x3,x4,x5) sprintf(msg+strlen(msg),fmt,x1,x2,x3,x4,x5) #define CATMSG6(fmt,x1,x2,x3,x4,x5,x6) \ sprintf(msg+strlen(msg),fmt,x1,x2,x3,x4,x5,x6) /************************************************************************/ #ifdef __cplusplus extern "C" { #endif extern void gtools_check(int,int,int,int); extern FILE *opengraphfile(char*,int*,boolean,long); extern void writeline(FILE*,char*); extern char *gtools_getline(FILE*); extern int graphsize(char*); extern void stringcounts(char*,int*,size_t*); extern void stringtograph(char*,graph*,int); extern size_t edgecount(char*); extern graph *readg(FILE*,graph*,int,int*,int*); extern char *ntog6(graph*,int,int); extern char *ntos6(graph*,int,int); extern char *sgtos6(sparsegraph*); extern void writeg6(FILE*,graph*,int,int); extern void writes6(FILE*,graph*,int,int); extern void writes6_sg(FILE*,sparsegraph*); extern void writepc_sg(FILE*,sparsegraph*); extern void stringtosparsegraph(char*,sparsegraph*,int*); extern sparsegraph *read_sg(FILE*,sparsegraph*); extern sparsegraph *read_sg_loops(FILE*,sparsegraph*,int*); extern sparsegraph *readpc_sg(FILE*,sparsegraph*); extern sparsegraph *readpcle_sg(FILE*,sparsegraph*); extern sparsegraph *read_ec(FILE*,sparsegraph*); extern void writeec_sg(FILE*,sparsegraph*); extern void writelast(FILE*); extern int longval(char**,long*); extern void arg_int(char**,int*,char*); extern void arg_long(char**,long*,char*); extern void arg_range(char**,char*,long*,long*,char*); extern void writerange(FILE*,int,long,long); extern void gt_abort(char*); extern char *stringcopy(char*); extern boolean strhaschar(char*,int); extern void fcanonise(graph*,int,int,graph*,char*,boolean); extern void fcanonise_inv (graph*,int,int,graph*,char*,void(*)(graph*,int*,int*,int, int,int,permutation*,int,boolean,int,int),int,int,int,boolean); extern void fcanonise_inv_sg (sparsegraph*,int,int,sparsegraph*,char*,void(*)(graph*,int*,int*, int,int,int,permutation*,int,boolean,int,int),int,int,int,boolean); extern void fgroup(graph*,int,int,char*,int*,int*); extern void fgroup_inv (graph*,int,int,char*,int*,int*,void(*)(graph*,int*,int*,int, int,int,permutation*,int,boolean,int,int),int,int,int); extern int istransitive(graph*,int,int,graph*); extern void tg_canonise(graph*,graph*,int,int); extern int readg_code; extern char *readg_line; extern size_t ogf_linelen; extern boolean is_pipe; #ifdef __cplusplus } #endif #ifdef CPUDEFS CPUDEFS #endif /* @edit_msg@ */ #endif /* _GTOOLS_H_ */ nauty24r2/dretog.c0000600000604200001440000001237411405400216012730 0ustar bdmusers/* dretog.c version 1.0; B D McKay, Jan 1997. */ #define USAGE "dretog [-n#o#sghq] [infile [outfile]]" #define HELPTEXT \ " Read graphs in dreadnaut format.\n\ \n\ -o# Label vertices starting at # (default 0). \n\ This can be overridden in the input.\n\ -n# Set the initial graph order to # (no default). \n\ This can be overridden in the input.\n\ -g Use graph6 format (default).\n\ -s Use sparse6 format.\n\ -h Write a header (according to -g or -s).\n\ \n\ Input consists of a sequence of dreadnaut commands restricted to:\n\ \n\ n=# set number of vertices (no default)\n\ The = is optional.\n\ $=# set label of first vertex (default 0)\n\ The = is optional.\n\ $$ return origin to initial value (see -o#)\n\ \"..\" and !..\\n comments to ignore\n\ g specify graph to follow (as dreadnaut format)\n\ Can be omitted if first character of graph is a digit or ';'.\n\ q exit (optional)\n" /*************************************************************************/ #include "gtools.h" /* which includes nauty.h and stdio.h */ extern int labelorg; /**************************************************************************/ /**************************************************************************/ int main(int argc, char *argv[]) { int m,n,c; int argnum,j,outcode,initorg; char *arg,sw; boolean badargs,prompt; boolean sswitch,gswitch,oswitch,nswitch,hswitch,qswitch; char *infilename,*outfilename; FILE *infile,*outfile; long nin; char s[10]; #if MAXN graph g[MAXN*MAXM]; #else DYNALLSTAT(graph,g,g_sz); #endif HELP; sswitch = gswitch = oswitch = FALSE; qswitch = nswitch = hswitch = FALSE; infilename = outfilename = NULL; initorg = 0; n = -1; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('s',sswitch) else SWBOOLEAN('g',gswitch) else SWBOOLEAN('h',hswitch) else SWBOOLEAN('q',qswitch) else SWINT('o',oswitch,initorg,">E dretog -o") else SWINT('n',nswitch,n,">E dretog -n") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (sswitch && gswitch) gt_abort(">E dretog: -s and -g are incompatible\n"); if (labelorg < 0) gt_abort(">E dretog: negative origin forbidden\n"); if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!infilename || infilename[0] == '-') { infilename = "stdin"; infile = stdin; } else if ((infile = fopen(infilename,"r")) == NULL) { fprintf(stderr,"Can't open input file %s\n",infilename); gt_abort(NULL); } if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (sswitch) outcode = SPARSE6; else outcode = GRAPH6; if (hswitch) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } #if HAVE_ISATTY prompt = isatty(fileno(infile)) && isatty(fileno(outfile)); #else prompt = (infile == stdin); #endif /* perform scanning required */ labelorg = initorg; nin = 0; while (fscanf(infile,"%1s",s) == 1) { if (s[0] == 'n') { if (fscanf(infile,"%1s",s) == 1 && s[0] != '=') ungetc(s[0],infile); if (fscanf(infile,"%d",&n) != 1) { fprintf(stderr,">E dretog: invalid n=# command\n"); gt_abort(NULL); } if (n <= 0) gt_abort(">E dretog: n can't be <= 0\n"); } else if (s[0] == '"') { while ((c = getc(infile)) != '"' && c != EOF) {} } else if (s[0] == '!') { while ((c = getc(infile)) != '\n' && c != EOF) {} } else if (s[0] == '$') { if ((s[0] = getc(infile)) == '$') labelorg = initorg; else { if (s[0] != '=') ungetc(s[0],infile); if (fscanf(infile,"%d",&labelorg) != 1) gt_abort(">E dretog: invalid $=# command\n"); if (labelorg < 0) gt_abort(">E dretog: must have labelorg >= 0\n"); } } else if (s[0] == 'g' || (s[0] >= '0' && s[0] <= '9') || s[0] == ';') { if (n < 0) gt_abort(">E dretog: g command before n is defined\n"); if (s[0] != 'g') ungetc(s[0],infile); m = (n + WORDSIZE - 1) / WORDSIZE; #if MAXN if (n > MAXN || m > MAXM) gt_abort(">E n or m too big\n"); #else DYNALLOC2(graph,g,g_sz,n,m,"dretog"); #endif ++nin; readgraph(infile,g,FALSE,prompt,FALSE,78,m,n); if (outcode == SPARSE6) writes6(outfile,g,m,n); else writeg6(outfile,g,m,n); } else if (s[0] == 'q') exit(0); else { fprintf(stderr,">E dretog: invalid command \"%c\"\n",s[0]); gt_abort(NULL); } } if (!qswitch) fprintf(stderr,">Z %ld graphs converted from %s to %s\n", nin,infilename,outfilename); exit(0); } nauty24r2/splay.c0000600000604200001440000002321411274163463012605 0ustar bdmusers/* splay.c - code for splay trees Version of August 18, 2001. This file is not meant to be compiled separately, but to be #included into other programs. Use it like this: 1. Define a node type SPLAYNODE. It must be a structure that contains at least the pointer fields left, right and parent of type SPLAYNODE*. Also define a macro SPLAYNODESIZE giving the size of an object of type SPLAYNODE, unless sizeof(SPLAYNODE) is adequate. 2. Declare a variable of type SPLAYNODE* to point to the root of the tree, and initialise it to NULL. 3. Declare SCAN_ARGS to be the additional arguments needed for splay_scan(), including a leading comma. 4. Declare ACTION(p) for what splay_scan() should do for node p. 5. Declare INSERT_ARGS to be the additional arguments needed for splay_insert(), including a leading comma. 6. Declare COMPARE(p) to compare INSERT_ARGS or LOOKUP_ARGS to the contents of node p. <0, 0, >0 if INSERT_ARGS is greater, equal, less, than p. This has to be an expression with a value, so you will need to make it a procedure call if the comparison is complicated. If you are using something like strcmp, the correct order is strcmp( INSERT_ARGS, p ). 7. Declare PRESENT(p) for what to do if INSERT_ARGS is already present, in node p. There is a spare int variable i available. Typically, this might update some data in the node p. 8. Declare NOT_PRESENT(p) for what to do if INSERT_ARGS is not in the tree and p is a fresh node to hold it. No need to set the left, right, and parent fields. Use i here too if you like. Typically, this might initialise the data in node p. PRESENT(p) and NOT_PRESENT(p) should not manipulate the tree pointers. However, each of them can include a return if you don't want to change the tree. In the case of NOT_PRESENT(p), do free(p) before returning. In the case of PRESENT(p), it is also legal to delete the node from the tree using SCAN_DELETE(to_root,p). In that case you MUST return immediately afterwards. 9. Declare LOOKUP_ARGS to be the additional arguments needed for splay_lookup(), including a leading comma. The default for LOOKUP_ARGS is to be the same as INSERT_ARGS. 10. #include "splay.c" Calls: Suppose "root" is name of the variable described in step 2. There is no need to initialise the tree. Step 2 did that already. To insert something in the tree: splay_insert(&root, ...stuff...) where "stuff" is the stuff you want to insert, declared as INSERT_ARGS. If the key (some part of the stuff decided by you) is present in an existing tree node p, PRESENT(p) is executed. Otherwise, a new tree node p is created and NOT_PRESENT(p) is executed. To look up something in the tree: splay_lookup(&root, ...stuff...) where "stuff" is the stuff you want to find, declared as LOOKUP_ARGS. It will return a pointer to the tree node with the right key, or NULL if there is no such tree node. To do something for each node of the tree: splay_scan(root, ...stuff...) where "stuff" is anything you like (including nothing). This will execute ACTION(p) for each node p in inorder. To delete the node p (which MUST be in the tree: splay_delete(&root, p) Nothing happens if p is NULL, so you can use splay_delete(&root, splay_lookup(&root, ...stuff...)) to delete a node, if any, containing stuff. It is possible to have splay trees of several types in the same program. Just include "splay.c" several times, with the procedure names SPLAY, SPLAY_SCAN, SPLAY_LOOKUP, SPLAY_INSERT, SPLAY_DELETE defined to distinct names. You have to redefine them all even if you aren't using them all. */ #define S_A 0 #define S_L 1 #define S_R 2 #define S_LL 3 #define S_LR 4 #define S_RL 5 #define S_RR 6 #ifndef SPLAYNODESIZE #define SPLAYNODESIZE sizeof(SPLAYNODE) #endif #ifndef LOOKUP_ARGS #define LOOKUP_ARGS INSERT_ARGS #endif #ifndef SPLAY #define SPLAY splay #define SPLAY_SCAN splay_scan #define SPLAY_LOOKUP splay_lookup #define SPLAY_INSERT splay_insert #define SPLAY_DELETE splay_delete #endif /*********************************************************************/ void SPLAY_SCAN(SPLAYNODE *root SCAN_ARGS) /* Do ACTION(p) for each node of the tree, in inorder. Nonrecursive! */ { int code; SPLAYNODE *p; p = root; code = S_A; while (p) { switch (code) /* deliberate flow-ons */ { case S_A: if (p->left) { p = p->left; break; } case S_L: ACTION(p); if (p->right) { p = p->right; code = S_A; break; } case S_R: if (p->parent && p->parent->left == p) code = S_L; else code = S_R; p = p->parent; break; } } } /*********************************************************************/ static void SPLAY(SPLAYNODE *p) /* Splay the node p. It becomes the new root. */ { SPLAYNODE *q,*r,*s; SPLAYNODE *a,*b,*c; int code; #define LCHILD(x,y) {(x)->left = y; if (y) (y)->parent = x;} #define RCHILD(x,y) {(x)->right = y; if (y) (y)->parent = x;} while (p->parent) { a = p->left; b = p->right; q = p->parent; if (q->left == p) { code = S_L; c = q->right; } else { code = S_R; c = q->left; } r = q->parent; if (r) { if (r->left == q) code = (code == S_L ? S_LL : S_LR); else code = (code == S_L ? S_RL : S_RR); s = r->parent; p->parent = s; if (s) { if (s->left == r) s->left = p; else s->right = p; } } else { p->parent = NULL; } switch (code) { case S_L: RCHILD(p,q); LCHILD(q,b); break; case S_R: LCHILD(p,q); RCHILD(q,a); break; case S_LL: RCHILD(p,q); RCHILD(q,r); LCHILD(q,b); LCHILD(r,c); break; case S_RR: LCHILD(p,q); LCHILD(q,r); RCHILD(r,c); RCHILD(q,a); break; case S_LR: LCHILD(p,q); RCHILD(p,r); RCHILD(q,a); LCHILD(r,b); break; case S_RL: LCHILD(p,r); RCHILD(p,q); RCHILD(r,a); LCHILD(q,b); break; } } } /*********************************************************************/ void SPLAY_INSERT(SPLAYNODE **to_root INSERT_ARGS) /* Do insertion operation. On return, the object being inserted is at the root of the tree regardless of whether a new node needed to be created for it. */ { int i,cmp; SPLAYNODE *p,*ppar,*new_node; p = *to_root; cmp = 0; while (p != NULL) { cmp = COMPARE(p); if (cmp == 0) { PRESENT(p); SPLAY(p); *to_root = p; return; } else if (cmp < 0) { ppar = p; p = p->left; } else { ppar = p; p = p->right; } } if ((new_node = (SPLAYNODE*)malloc(SPLAYNODESIZE)) == NULL) { fprintf(stderr,">E malloc failed in splay_insert()\n"); exit(1); } NOT_PRESENT(new_node); new_node->left = new_node->right = NULL; if (cmp == 0) { *to_root = new_node; new_node->parent = NULL; } else if (cmp < 0) { ppar->left = new_node; new_node->parent = ppar; } else { ppar->right = new_node; new_node->parent = ppar; } SPLAY(new_node); *to_root = new_node; } /*********************************************************************/ SPLAYNODE* SPLAY_LOOKUP(SPLAYNODE **to_root LOOKUP_ARGS) /* Do a look-up operation. If found, return a pointer to the node containing it. If not, return NULL. */ { int i,cmp; SPLAYNODE *p; p = *to_root; cmp = 0; while (p != NULL) { cmp = COMPARE(p); if (cmp == 0) { SPLAY(p); *to_root = p; return p; } else if (cmp < 0) p = p->left; else p = p->right; } return NULL; } /*********************************************************************/ void SPLAY_DELETE(SPLAYNODE **to_root, SPLAYNODE *p) /* Remove node p from the tree and free it. */ { SPLAYNODE *q; if (p == NULL) return; SPLAY(p); *to_root = p; /* Now we have to delete the root. */ /* No right child (includes no children). */ if (!p->right) { *to_root = p->left; if (p->left) p->left->parent = NULL; free(p); return; } /* right child but no left child */ if (!p->left) { *to_root = p->right; p->right->parent = NULL; free(p); return; } /* both children exist */ for (q = p->left; q->right; q = q->right) {} if (q->left) q->left->parent = q->parent; if (q->parent == p) q->parent->left = q->left; else q->parent->right = q->left; q->left = p->left; q->right = p->right; q->parent = NULL; if (p->left) p->left->parent = q; if (p->right) p->right->parent = q; *to_root = q; free(p); } /*********************************************************************/ /* The following shows the tree structure for debugging purposes. If you define SPLAY_DUMP you must also define DUMP_ARGS, DUMP_LEFT, DUMP_RIGHT and DUMP_ACTION(p). */ #ifdef SPLAY_DUMP void SPLAY_DUMP(SPLAYNODE *p DUMP_ARGS) { int i; if (p == NULL) return; if (p->right && p->right->parent != p) fprintf(stderr,"parent misaligned at %p-%p ************\n",p,p->right); if (p->left && p->left->parent != p) fprintf(stderr,"parent misaligned at %p-%p ************\n",p,p->left); SPLAY_DUMP(p->right DUMP_RIGHT); DUMP_ACTION(p); SPLAY_DUMP(p->left DUMP_LEFT); } #endif nauty24r2/nautyex2.c0000600000604200001440000000612711274163463013240 0ustar bdmusers/* This program prints generators for the automorphism group of an n-vertex polygon, where n is a number supplied by the user. It needs to be linked with nauty.c, nautil.c and naugraph.c. This version uses dynamic allocation. */ #include "nauty.h" /* which includes */ /* MAXN=0 is defined by nauty.h, which implies dynamic allocation */ int main(int argc, char *argv[]) { /* DYNALLSTAT declares a pointer variable (to hold an array when it * is allocated) and a size variable to remember how big the array is. * Nothing is allocated yet. */ DYNALLSTAT(graph,g,g_sz); DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(setword,workspace,workspace_sz); static DEFAULTOPTIONS_GRAPH(options); statsblk stats; int n,m,v; set *gv; /* Default options are set by the DEFAULTOPTIONS_GRAPH macro above. * Here we change those options that we want to be different from the * defaults. writeautoms=TRUE causes automorphisms to be written. */ options.writeautoms = TRUE; while (1) { printf("\nenter n : "); if (scanf("%d",&n) == 1 && n > 0) { /* The nauty parameter m is a value such that an array of * m setwords is sufficient to hold n bits. The type setword * is defined in nauty.h. The number of bits in a setword is * WORDSIZE, which is 16, 32 or 64. Here we calculate * m = ceiling(n/WORDSIZE). */ m = (n + WORDSIZE - 1) / WORDSIZE; /* The following optional call verifies that we are linking * to compatible versions of the nauty routines. */ nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); /* Now that we know how big the graph will be, we allocate * space for the graph and the other arrays we need. */ DYNALLOC2(graph,g,g_sz,m,n,"malloc"); DYNALLOC1(setword,workspace,workspace_sz,5*m,"malloc"); DYNALLOC1(int,lab,lab_sz,n,"malloc"); DYNALLOC1(int,ptn,ptn_sz,n,"malloc"); DYNALLOC1(int,orbits,orbits_sz,n,"malloc"); for (v = 0; v < n; ++v) { gv = GRAPHROW(g,v,m); EMPTYSET(gv,m); ADDELEMENT(gv,(v+n-1)%n); ADDELEMENT(gv,(v+1)%n); } printf("Generators for Aut(C[%d]):\n",n); nauty(g,lab,ptn,NULL,orbits,&options,&stats, workspace,5*m,m,n,NULL); /* The size of the group is returned in stats.grpsize1 and * stats.grpsize2. See dreadnaut.c for code that will write the * value in a sensible format; here we will take advantage of * knowing that the size cannot be very large. Adding 0.1 is * just in case the floating value is truncated instead of rounded, * but that shouldn't be. */ printf("Automorphism group size = %.0f",stats.grpsize1+0.1); } else break; } exit(0); } nauty24r2/amtog.c0000600000604200001440000001623211405400216012550 0ustar bdmusers/* amtog.c version 1.0; B D McKay, Jan 1997. */ #define USAGE "amtog [-n#sghq] [infile [outfile]]" #define HELPTEXT \ " Read graphs in matrix format.\n\ \n\ -n# Set the initial graph order to # (no default).\n\ This can be overridden in the input.\n\ -g Write the output in graph6 format (default).\n\ -s Write the output in sparse6 format.\n\ -h Write a header (according to -g or -s).\n\ -q Suppress auxiliary information.\n\ \n\ Input consists of a sequence of commands restricted to:\n\ \n\ n=# set number of vertices (no default)\n\ The = is optional.\n\ m Matrix to follow (01 any spacing or no spacing)\n\ An 'm' is also assumed if 0 or 1 is encountered.\n\ M Complement of matrix to follow (as m)\n\ t Upper triangle of matrix to follow, row by row\n\ excluding the diagonal. (01 in any or no spacing)\n\ T Complement of upper trangle to follow (as t)\n\ q exit (optional)\n" /*************************************************************************/ #include "gtools.h" /* which includes nauty.h and stdio.h */ extern int labelorg; /**************************************************************************/ /**************************************************************************/ int main(int argc, char *argv[]) { int m,n; int argnum,i,j,outcode,val; char *arg,sw; boolean badargs; boolean nswitch,sswitch,gswitch,hswitch,qswitch; boolean loop,unsymm,compl,triangle; char *infilename,*outfilename; FILE *infile,*outfile; unsigned long nin; char s[10]; #if MAXN graph g[MAXN*MAXM]; #else DYNALLSTAT(graph,g,g_sz); #endif HELP; sswitch = gswitch = FALSE; qswitch = nswitch = hswitch = FALSE; infilename = outfilename = NULL; n = -1; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('s',sswitch) else SWBOOLEAN('g',gswitch) else SWBOOLEAN('h',hswitch) else SWBOOLEAN('q',qswitch) else SWINT('n',nswitch,n,">E amtog -n") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (sswitch && gswitch) gt_abort(">E amtog: -s and -g are incompatible\n"); if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!infilename || infilename[0] == '-') { infilename = "stdin"; infile = stdin; } else if ((infile = fopen(infilename,"r")) == NULL) { fprintf(stderr,"Can't open input file %s\n",infilename); gt_abort(NULL); } if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (sswitch) outcode = SPARSE6; else outcode = GRAPH6; if (hswitch) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } #if MAXN if (nswitch && n > MAXN) { gt_abort(">E amtog: value of -n too large\n"); exit(2); } #else if (nswitch) { m = (n + WORDSIZE - 1) / WORDSIZE; DYNALLOC2(graph,g,g_sz,n,m,"amtog"); } #endif /* perform scanning required */ nin = 0; while (fscanf(infile,"%1s",s) == 1) { if (s[0] == 'n') { if (fscanf(infile,"=%d",&n) != 1) { gt_abort(">E amtog: invalid n=# command\n"); exit(2); } m = (n + WORDSIZE - 1) / WORDSIZE; #if MAXN if (n < 1 || n > MAXN || m > MAXM) gt_abort(">E amtog: n<0 or n,m too big\n"); #else DYNALLOC2(graph,g,g_sz,n,m,"amtog"); #endif } else if (s[0] == 'm' || s[0] == 'M' || s[0] == 't' || s[0] == 'T' || s[0] == '0' || s[0] == '1') { if (n < 0) { fprintf(stderr, ">E amtog: matrix found before n is defined\n"); exit(2); } if (s[0] == '0' || s[0] == '1') ungetc(s[0],infile); m = (n + WORDSIZE - 1) / WORDSIZE; EMPTYSET(g,m*(size_t)n); loop = unsymm = FALSE; triangle = (s[0] == 't') || (s[0] == 'T'); compl = (s[0] == 'M') || (s[0] == 'T'); ++nin; for (i = 0; i < n; ++i) for (j = (triangle ? i+1 : 0); j < n; ++j) { if (fscanf(infile,"%1s",s) != 1) { fprintf(stderr,">E amtog: incomplete matrix\n"); ABORT(">E amtog"); } if (s[0] == '0' || s[0] == '1') { if (i == j) { if (s[0] == '1') loop = TRUE; } else { val = compl ^ (s[0] == '1'); if (val == 1) { if (triangle) { ADDELEMENT(GRAPHROW(g,i,m),j); ADDELEMENT(GRAPHROW(g,j,m),i); } else { if (j < i && !ISELEMENT(GRAPHROW(g,j,m),i)) unsymm = TRUE; ADDELEMENT(GRAPHROW(g,i,m),j); } } else if (j < i && ISELEMENT(GRAPHROW(g,j,m),i)) unsymm = TRUE; } } else { fprintf(stderr, ">E amtog: illegal character in matrix: \"%c\"\n", s[0]); exit(2); } } if (loop) fprintf(stderr, ">E amtog: warning, loop in graph %lu\n",nin); if (unsymm) fprintf(stderr, ">E amtog: warning, graph %lu is unsymmetric\n",nin); if (outcode == SPARSE6) writes6(outfile,g,m,n); else writeg6(outfile,g,m,n); } else if (s[0] == 'q') { exit(0); } else { fprintf(stderr,">E amtog: invalid command \"%c\"\n",s[0]); exit(2); } } if (!qswitch) fprintf(stderr,">Z %lu graphs converted from %s to %s.\n", nin,infilename,outfilename); exit(0); } nauty24r2/genbg.c0000600000604200001440000014073711274163463012551 0ustar bdmusers/* genbg.c : version 1.7; B D McKay, Nov 29, 2008. */ /* TODO: consider colour swaps */ #define USAGE \ "genbg [-c -ugsn -vq -lzF] [-Z#] [-d#|-d#:#] [-D#|-D#:#] n1 n2 \n\ [mine[:maxe]] [res/mod] [file]" #define HELPTEXT \ " Find all bicoloured graphs of a specified class.\n\ \n\ n1 : the number of vertices in the first class\n\ n2 : the number of vertices in the second class\n\ mine:maxe : a range for the number of edges\n\ #:0 means '# or more' except in the case 0:0\n\ res/mod : only generate subset res out of subsets 0..mod-1\n\ file : the name of the output file (defailt stdout)\n\ -c : only write connected graphs\n\ -z : all the vertices in the second class must have\n\ different neighbourhoods\n\ -F : the vertices in the second class must have at least two\n\ neighbours of degree at least 2\n\ -L : there is no vertex in the first class whose removal leaves\n\ the vertices in the second class unreachable from each other\n\ -Z# : two vertices in the second class may have at most # common nbrs\n\ -D# : specify an upper bound for the maximum degree.\n\ Example: -D6. You can also give separate maxima for the\n\ two parts, for example: -D5:6\n\ -d# : specify a lower bound for the minimum degree.\n\ Again, you can specify it separately for the two parts: -d1:2\n\ -n : use nauty format for output\n\ -g : use graph6 format for output (default)\n\ -s : use sparse6 format for output\n\ -a : use Greechie diagram format for output\n\ -u : do not output any graphs, just generate and count them\n\ -v : display counts by number of edges to stderr\n\ -l : canonically label output graphs (using the 2-part colouring)\n\ \n\ -q : suppress auxiliary output\n\ \n\ See program text for much more information.\n" /* Output formats. If -n is absent, any output graphs are written in graph6 format. If -n is present, any output graphs are written in nauty format. For a graph of n vertices, the output consists of n+1 long ints (even if a setword is shorter than a long int). The first contains n, and the others contain the adjacency matrix. Long int i of the adjacency matrix (0 <= i <= n-1) is the set of neighbours of vertex i, cast from setword to long int. PRUNE feature. By defining the C preprocessor variables PRUNE1 and/or PRUNE2 at compile time, you can filter the output of the program efficiently. The value of the variable is a function name with parameter list (graph *g, int *deg, int n1, int n2, int maxn2) The function will be called for each intermediate graph generated by the program, including output graphs. The parameters are: g = the graph in nauty format deg = an array giving the degrees of the vertices n1 = the number of vertices in the first colour class (same as the n1 parameter on the command line) n2 = the number of vertices in the second colour class maxn2 = the value of n2 on the command line If n2=maxn2, the graph has the output size. If the function returns a non-zero value, neither this graph nor any of its descendants will be written to the output. PRUNE1 and PRUNE2 are functionally equivalent, but placed at different points in the program. Essentially, use PRUNE1 for fast tests that eliminate many cases and PRUNE2 for slow tests that eliminate few. If in doubt, try it both ways and choose the fastest. You can use both PRUNE1 and PRUNE2 if you wish, in which case note that the PRUNE1 test has already been passed before PRUNE2 is applied. Vertices 0..n1-1 are always present. The program works by successively adding one more vertex to the second colour class. Vertex n1+n2-1 is always the last one that has been added, and (except for n2=1) the subgraph formed by deleting n1+n2-1 has previously been passed by the pruning function. If -c is specified, the connectivity test has NOT been performed yet at the time the pruning function is called. However the simplicity test indicated by -z HAS been performed if -z is specified. OUTPROC feature. By defining the C preprocessor variable OUTPROC at compile time (for Unix the syntax is -DOUTPROC=procname on the cc command), genbg can be made to call a procedure of your manufacture with each output graph instead of writing anything. Your procedure needs to have type void and the argument list (FILE *f, graph *g, int n1, int n2). f is a stream open for writing (in fact, in the current version it is always stdout), g is the graph in nauty format, and n1,n2 are the numbers of vertices on each side. Your procedure can be in a separate file so long as it is linked with genbg. The global variables nooutput, nautyformat and canonise (all type boolean) can be used to test for the presence of the flags -u, -n and -l, respectively. For backward compatibility, it is possible to instead define OUTPROC1 to be the name of a procedure with argument list (FILE *f, graph *g, int n). INSTRUMENT feature. If the C preprocessor variable INSTRUMENT is defined at compile time, extra code is inserted to collect statistics during execution, and more information is written to stderr at termination. ************************************************************************** Author: B. D. McKay, Oct 1994. bdm@cs.anu.edu.au Copyright B. McKay (1994-2008). All rights reserved. This software is subject to the conditions and waivers detailed in the file nauty.h. 1 May 2003 : fixed PRUNE feature 13 Sep 2003 : added Greechie output, all outprocs have n1,n2 9 Oct 2003 : changed -l to respect partition 11 Apr 2007 : make >A line more atomic 29 Aug 2008 : include PLUGIN insertion 29 Nov 2008 : slight improvement of connectivity testing **************************************************************************/ #define NAUTY_PGM 2 /* 1 = geng, 2 = genbg, 3 = gentourng */ #undef MAXN #define MAXN WORDSIZE #ifndef MAXN1 #define MAXN1 24 /* not more than 30 */ #endif #define ONE_WORD_SETS #include "gtools.h" /* which includes nauty.h and stdio.h */ static void (*outproc)(FILE*,graph*,int,int); #ifdef OUTPROC extern void OUTPROC(FILE*,graph*,int,int); #endif static FILE *outfile; /* file for output graphs */ static boolean connec; /* presence of -c */ static boolean verbose; /* presence of -v */ static boolean simple; /* presence of -z */ boolean nautyformat; /* presence of -n */ boolean nooutput; /* presence of -u */ boolean canonise; /* presence of -l */ boolean graph6; /* presence of -g */ boolean sparse6; /* presence of -s */ boolean greout; /* presence of -a */ boolean quiet; /* presence of -q */ boolean footfree; /* presence of -F */ boolean cutfree; /* presence of -L */ int class1size; /* same as n1 */ int maxcommon; /* -1 or value of -Z */ static int maxdeg1,maxdeg2,n1,maxn2,mine,maxe,nprune,mod,res,curres; static int mindeg1,mindeg2; static graph gcan[MAXN]; static int xval[MAXN]; /* x-bit version of second class, xval[0..] */ #if MAXN1 <= 16 static int xbit[] = {0x0001,0x0002,0x0004,0x0008, 0x0010,0x0020,0x0040,0x0080, 0x0100,0x0200,0x0400,0x0800, 0x1000,0x2000,0x4000,0x8000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : 15-leftbit[((x)>>8)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] + bytecount[(x)&0xFF]) #elif MAXN1 <= 24 static int xbit[] = {0x000001,0x000002,0x000004,0x000008, 0x000010,0x000020,0x000040,0x000080, 0x000100,0x000200,0x000400,0x000800, 0x001000,0x002000,0x004000,0x008000, 0x010000,0x020000,0x040000,0x080000, 0x100000,0x200000,0x400000,0x800000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : \ (x)&0xFF00 ? 15-leftbit[((x)>>8)&0xFF] : 23-leftbit[((x)>>16)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] \ + bytecount[((x)>>16)&0xFF] + bytecount[(x)&0xFF]) #else static int xbit[] = {0x00000001,0x00000002,0x00000004,0x00000008, 0x00000010,0x00000020,0x00000040,0x00000080, 0x00000100,0x00000200,0x00000400,0x00000800, 0x00001000,0x00002000,0x00004000,0x00008000, 0x00010000,0x00020000,0x00040000,0x00080000, 0x00100000,0x00200000,0x00400000,0x00800000, 0x01000000,0x02000000,0x04000000,0x08000000, 0x10000000,0x20000000,0x40000000,0x80000000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : \ (x)&0xFF00 ? 15-leftbit[((x)>>8)&0xFF] : \ (x)&0xFF0000 ? 23-leftbit[((x)>>16)&0xFF] : \ 31-leftbit[((x)>>24)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] \ + bytecount[((x)>>16)&0xFF] + \ + bytecount[((x)>>24)&0xFF] + bytecount[(x)&0xFF]) #endif typedef struct { int ne,dmax; /* values used for xlb,xub calculation */ int xlb,xub; /* saved bounds on extension degree */ int lo,hi; /* work purposes for orbit calculation */ int *xorb; /* min orbit representative */ } leveldata; typedef struct { long hi,lo; } bigint; #define ZEROBIG(big) big.hi = big.lo = 0L #define ISZEROBIG(big) (big.lo == 0 && big.hi == 0) #define SETBIG(big,value) {big.hi = 0L; big.lo = (value);} #define ADDBIG(big,extra) if ((big.lo += (extra)) >= 1000000000L) \ { ++big.hi; big.lo -= 1000000000L;} #define PRINTBIG(file,big) if (big.hi == 0) \ fprintf(file,"%ld",big.lo); else fprintf(file,"%ld%09ld",big.hi,big.lo) #define BIGTODOUBLE(big) (big.hi * 1000000000.0 + big.lo) #define SUMBIGS(big1,big2) {if ((big1.lo += big2.lo) >= 1000000000L) \ {big1.lo -= 1000000000L; big1.hi += big2.hi + 1L;} \ else big1.hi += big2.hi;} #define SUBBIGS(big1,big2) {if ((big1.lo -= big2.lo) < 0L) \ {big1.lo += 1000000000L; big1.hi -= big2.hi + 1L;} \ else big1.hi -= big2.hi;} /* Note: SUBBIGS must not allow the value to go negative. SUMBIGS and SUBBIGS both permit big1 and big2 to be the same bigint. */ #define ISEQBIG(big1,big2) (big1.lo == big2.lo && big1.hi == big2.hi) #define ISASBIG(big,value) (big.hi > 0 || big.lo >= (value)) #define IFLE1BITS(ww) if (!((ww)&((ww)-1))) static leveldata data[MAXN]; /* data[n] is data for n -> n+1 */ static bigint ecount[1+MAXN*MAXN/4]; /* counts by number of edges */ static int xstart[MAXN+1]; /* index into xset[] for each cardinality */ static int *xset; /* array of all x-sets in card order */ static int *xcard; /* cardinalities of all x-sets */ static int *xinv; /* map from x-set to index in xset */ #ifdef INSTRUMENT static long nodes[MAXN],rigidnodes[MAXN],fertilenodes[MAXN]; static long a1calls,a1nauty,a1succs; static long a2calls,a2nauty,a2uniq,a2succs; #endif #ifdef SPLITTEST static unsigned long splitcases = 0; #endif #ifdef PLUGIN #include PLUGIN #endif /************************************************************************/ void writeny(FILE *f, graph *g, int n1, int n2) /* write graph g (n1+n2 vertices) to file f in y format */ { static char ybit[] = {32,16,8,4,2,1}; char s[(MAXN*(MAXN-1)/2 + 5)/6 + 4]; int i,j,k; char y,*sp; int n; n = n1 + n2; sp = s; *(sp++) = 0x40 | n; y = 0x40; k = -1; for (j = 1; j < n; ++j) for (i = 0; i < j; ++i) { if (++k == 6) { *(sp++) = y; y = 0x40; k = 0; } if (g[i] & bit[j]) y |= ybit[k]; } if (n >= 2) *(sp++) = y; *(sp++) = '\n'; *sp = '\0'; if (fputs(s,f) == EOF || ferror(f)) { fprintf(stderr,">E writeny : error on writing file\n"); exit(2); } } /************************************************************************/ void writeg6x(FILE *f, graph *g, int n1, int n2) /* write graph g (n1+n2 vertices) to file f in graph6 format */ { writeg6(f,g,1,n1+n2); } /************************************************************************/ void writes6x(FILE *f, graph *g, int n1, int n2) /* write graph g (n1+n2 vertices) to file f in graph6 format */ { writes6(f,g,1,n1+n2); } /************************************************************************/ void writegre(FILE *f, graph *g, int n1, int n2) /* write graph g (n1+n2 vertices) to file f in Greechie diagram format */ { static char atomname[] = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz!\"#$%&'()*-/:;<=>?@[\\]^_`{|}~"; char grestr[MAXN*MAXN+MAXN+5]; int i,j,k; setword gi; k = 0; for (i = n1; i < n1+n2; ++i) { if (i > n1) grestr[k++] = ','; gi = g[i]; while (gi) { TAKEBIT(j,gi); grestr[k++] = atomname[j]; } } grestr[k++] = '.'; grestr[k++] = '\n'; grestr[k] = '\0'; if (fputs(grestr,f) == EOF || ferror(f)) { fprintf(stderr,">E genbg : error on writing file\n"); gt_abort("genbg"); } } /***********************************************************************/ static void nullwrite(FILE *f, graph *g, int n1, int n2) /* don't write graph g (n1+n2 vertices) to file f */ { } /***********************************************************************/ #ifdef OUTPROC1 static void write12(FILE *f, graph *g, int n1, int n2) /* pass to OUTPROC1 */ { OUTPROC1(f,g,1,n1+n2); } #endif /***********************************************************************/ void writenauty(FILE *f, graph *g, int n1, int n2) /* write graph g (n1+n2 vertices) to file f in nauty format */ { long buffer[MAXN+1]; int i; int n; n = n1 + n2; buffer[0] = n; for (i = 0; i < n; ++i) buffer[i+1] = g[i]; if (fwrite((char*)buffer,sizeof(long),n+1,f) != n+1) { fprintf(stderr,">E writenauty : error on writing file\n"); exit(2); } } /*********************************************************************/ static void fragments(int *x, int nx, int *frag, int *nfrag) /* For each v in union(x[0..nx-1]), find the components of the hypergraph x - v and add them to frag if there are more than one. */ /* This implementation is shocking. Improve it! */ { int allx,i,j,v; int vbit,nw,w[MAXN]; boolean done; allx = 0; for (i = 0; i < nx; ++i) allx |= x[i]; *nfrag = 0; while (allx) { v = XNEXTBIT(allx); vbit = xbit[v]; allx &= ~vbit; for (i = 0; i < nx; ++i) w[i] = x[i] & ~vbit; nw = nx; done = FALSE; while (!done && nw > 1) { done = TRUE; for (i = 0; i < nw-1; ++i) for (j = i+1; j < nw; ) if ((w[i] & w[j]) != 0) { w[i] |= w[j]; w[j] = w[nw-1]; --nw; done = FALSE; } else ++j; } if (nw > 1) for (i = 0; i < nw; ++i) frag[(*nfrag)++] = w[i]; } } /*********************************************************************/ static boolean isconnected(graph *g, int n) /* test if g is connected */ { setword seen,expanded,toexpand,allbits; int i; allbits = ALLMASK(n); expanded = bit[n-1]; seen = expanded | g[n-1]; while (seen != allbits && (toexpand = (seen & ~expanded))) /* not == */ { i = FIRSTBIT(toexpand); expanded |= bit[i]; seen |= g[i]; } return seen == allbits; } /**************************************************************************/ static 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 */ { int w,n; setword workset,frontier; setword sofar; int inv,d,v; n = n1 + n2; for (v = n-1; v >= n1; --v) { inv = 0; sofar = frontier = bit[v]; for (d = 1; frontier != 0; ++d) { workset = 0; inv += POPCOUNT(frontier) ^ (0x57 + d); while (frontier) { w = FIRSTBIT(frontier); frontier &= ~bit[w]; workset |= g[w]; } frontier = workset & ~sofar; sofar |= frontier; } invar[v] = inv; if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; } /**************************************************************************/ static void makeleveldata(void) /* make the level data for each level */ { int i,j,h; int nn,nxsets,tttn; long ncj; leveldata *d; int xw,cw; nn = maxdeg2 <= n1 ? maxdeg2 : n1; ncj = nxsets = 1; for (j = 1; j <= nn; ++j) { ncj = (ncj * (n1 - j + 1)) / j; nxsets += ncj; } tttn = 1 << n1; xset = (int*) ALLOCS(nxsets,sizeof(int)); xcard = (int*) ALLOCS(nxsets,sizeof(int)); xinv = (int*) ALLOCS(tttn,sizeof(int)); if (xset==NULL || xcard==NULL || xinv==NULL) { fprintf(stderr,">E genbg: malloc failed in makeleveldata()\n"); exit(2); } j = 0; for (i = 0; i < tttn; ++i) if ((h = XPOPCOUNT(i)) <= maxdeg2) { xset[j] = i; xcard[j] = h; ++j; } if (j != nxsets) { fprintf(stderr,">E genbg: j=%d mxsets=%d\n",j,nxsets); exit(2); } h = 1; do h = 3 * h + 1; while (h < nxsets); do { for (i = h; i < nxsets; ++i) { xw = xset[i]; cw = xcard[i]; for (j = i; xcard[j-h] > cw || xcard[j-h] == cw && xset[j-h] > xw; ) { xset[j] = xset[j-h]; xcard[j] = xcard[j-h]; if ((j -= h) < h) break; } xset[j] = xw; xcard[j] = cw; } h /= 3; } while (h > 0); for (i = 0; i < nxsets; ++i) xinv[xset[i]] = i; xstart[0] = 0; for (i = 1; i < nxsets; ++i) if (xcard[i] > xcard[i-1]) xstart[xcard[i]] = i; xstart[xcard[nxsets-1]+1] = nxsets; for (i = 0; i < maxn2; ++i) { d = &data[i]; d->xorb = (int*) ALLOCS(nxsets,sizeof(int)); if (d->xorb==NULL) { fprintf(stderr,">E genbg: malloc failed in makeleveldata()\n"); exit(2); } d->ne = d->dmax = d->xlb = d->xub = -1; } } /**************************************************************************/ static UPROC userautomproc(int count, permutation *p, int *orbits, int numorbits, int stabvertex, int n) /* Automorphism procedure called by nauty Form orbits on powerset of VG Operates on data[n-n1] */ { int i,j1,j2; int moved,pxi,pi; int w,lo,hi; int *xorb; xorb = data[n-n1].xorb; lo = data[n-n1].lo; hi = data[n-n1].hi; if (count == 1) /* first automorphism */ for (i = lo; i < hi; ++i) xorb[i] = i; moved = 0; for (i = 0; i < n; ++i) if (p[i] != i) moved |= xbit[i]; for (i = lo; i < hi; ++i) { if ((w = xset[i] & moved) == 0) continue; pxi = xset[i] & ~moved; while (w) { j1 = XNEXTBIT(w); w &= ~xbit[j1]; pxi |= xbit[p[j1]]; } pi = xinv[pxi]; j1 = xorb[i]; while (xorb[j1] != j1) j1 = xorb[j1]; j2 = xorb[pi]; while (xorb[j2] != j2) j2 = xorb[j2]; if (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1; else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2; } } /***************************************************************************** * * * refinex(g,lab,ptn,level,numcells,count,active,goodret,code,m,n) is a * * custom version of refine() which can exit quickly if required. * * * * Only use at level==0. * * goodret : whether to do an early return for code 1 * * 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, permutation *count, set *active, boolean goodret, int *code, int m, int n) { int i,c1,c2,labc1; setword x; int split1,split2,cell1,cell2; int cnt,bmin,bmax; set *gptr; setword workset; int workperm[MAXN]; int bucket[MAXN+2]; if (n == 1) { *code = 1; return; } *code = 0; split1 = -1; while (*numcells < n && ((split1 = nextelement(active,1,split1)) >= 0 || (split1 = nextelement(active,1,-1)) >= 0)) { DELELEMENT1(active,split1); for (split2 = split1; ptn[split2] > 0; ++split2) {} if (split1 == split2) /* trivial splitting cell */ { gptr = GRAPHROW(g,lab[split1],1); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; c1 = cell1; c2 = cell2; while (c1 <= c2) { labc1 = lab[c1]; if (ISELEMENT1(gptr,labc1)) ++c1; else { lab[c1] = lab[c2]; lab[c2] = labc1; --c2; } } if (c2 >= cell1 && c1 <= cell2) { ptn[c2] = 0; ++*numcells; ADDELEMENT1(active,c1); } } } else /* nontrivial splitting cell */ { workset = 0; for (i = split1; i <= split2; ++i) workset |= bit[lab[i]]; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; i = cell1; if (x = workset & g[lab[i]]) /* not == */ cnt = POPCOUNT(x); else cnt = 0; count[i] = bmin = bmax = cnt; bucket[cnt] = 1; while (++i <= cell2) { if (x = workset & g[lab[i]]) /* not == */ cnt = POPCOUNT(x); else cnt = 0; while (bmin > cnt) bucket[--bmin] = 0; while (bmax < cnt) bucket[++bmax] = 0; ++bucket[cnt]; count[i] = cnt; } if (bmin == bmax) continue; c1 = cell1; for (i = bmin; i <= bmax; ++i) if (bucket[i]) { c2 = c1 + bucket[i]; bucket[i] = c1; if (c1 != cell1) { ADDELEMENT1(active,c1); ++*numcells; } if (c2 <= cell2) ptn[c2-1] = 0; c1 = c2; } for (i = cell1; i <= cell2; ++i) workperm[bucket[count[i]]++] = lab[i]; for (i = cell1; i <= cell2; ++i) lab[i] = workperm[i]; } } if (ptn[n-2] == 0) { if (lab[n-1] == n-1) { *code = 1; if (goodret) return; } else { *code = -1; return; } } else { i = n - 1; while (1) { if (lab[i] == n-1) break; --i; if (ptn[i] == 0) { *code = -1; return; } } } } } /**************************************************************************/ static void makecanon(graph *g, graph *gcan, int n1, int n2) /* gcan := canonise(g) */ { int lab[MAXN],ptn[MAXN],orbits[MAXN]; setword active[1]; int i; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; options.writemarkers = FALSE; options.writeautoms = FALSE; options.getcanon = TRUE; options.defaultptn = FALSE; for (i = 0; i < n1+n2; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n1-1] = ptn[n1+n2-1] = 0; EMPTYSET(active,1); ADDELEMENT(active,0); ADDELEMENT(active,n1); nauty(g,lab,ptn,active,orbits,&options,&stats, workspace,50,1,n1+n2,gcan); } /**************************************************************************/ static boolean accept1(graph *g, int n2, int x, graph *gx, int *deg, boolean *rigid) /* decide if n2 in theta(g+x) -- version for n2+1 < maxn2 */ { int i,n; int lab[MAXN],ptn[MAXN],orbits[MAXN]; permutation count[MAXN]; graph h[MAXN]; int xw; int nx,numcells,code; int i0,i1,degn; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a1calls; #endif n = n1 + n2; nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; gx[n] = 0; deg[n] = degn = XPOPCOUNT(x); xw = x; while (xw) { i = XNEXTBIT(xw); xw &= ~xbit[i]; gx[i] |= bit[n]; gx[n] |= bit[i]; ++deg[i]; } #ifdef PRUNE1 if (PRUNE1(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif for (i = 0; i < n1; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n1-1] = 0; i0 = n1; i1 = n; for (i = n1; i < nx; ++i) { if (deg[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == n1) { numcells = 2; active[0] = bit[0] | bit[n1]; } else { numcells = 3; active[0] = bit[0] | bit[n1] | bit[i1+1]; ptn[i1] = 0; } refinex(gx,lab,ptn,0,&numcells,count,active,FALSE,&code,1,nx); if (code < 0) return FALSE; if (numcells == nx) { *rigid = TRUE; #ifdef INSTRUMENT ++a1succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif return TRUE; } options.writemarkers = FALSE; options.writeautoms = FALSE; options.getcanon = TRUE; options.defaultptn = FALSE; options.userautomproc = userautomproc; active[0] = 0; #ifdef INSTRUMENT ++a1nauty; #endif 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 #ifdef PRUNE2 if (PRUNE2(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif return TRUE; } else return FALSE; } /**************************************************************************/ static 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; int lab[MAXN],ptn[MAXN],orbits[MAXN]; int degx[MAXN],invar[MAXN]; setword vmax,gv; int qn,qv; permutation count[MAXN]; int xw; int nx,numcells,code; int degn,i0,i1,j,j0,j1; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a2calls; if (nuniq) ++a2uniq; #endif n = n1 + n2; nx = n + 1; for (i = 0; i < n; ++i) { gx[i] = g[i]; degx[i] = deg[i]; } gx[n] = 0; degx[n] = degn = XPOPCOUNT(x); xw = x; while (xw) { i = XNEXTBIT(xw); xw &= ~xbit[i]; gx[i] |= bit[n]; gx[n] |= bit[i]; ++degx[i]; } #ifdef PRUNE1 if (PRUNE1(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif if (nuniq) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } for (i = 0; i < n1; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n1-1] = 0; i0 = n1; i1 = n; for (i = n1; i < nx; ++i) { if (degx[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == n1) { numcells = 2; active[0] = bit[0] | bit[n1]; if (!distinvar(gx,invar,n1,n2+1)) return FALSE; qn = invar[n]; j0 = n1; j1 = n; while (j0 <= j1) { j = lab[j0]; qv = invar[j]; if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > n1) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } else { numcells = 3; ptn[i1] = 0; active[0] = bit[0] | bit[n1] | bit[i1+1]; vmax = 0; j = MAXN; for (i = 0; i < n1; ++i) if (degx[i] < j && degx[i] > 0) { j = degx[i]; vmax = bit[i]; } else if (degx[i] == j) vmax |= bit[i]; gv = gx[n] & vmax; qn = POPCOUNT(gv); j0 = i1+1; j1 = n; while (j0 <= j1) { j = lab[j0]; gv = gx[j] & vmax; qv = POPCOUNT(gv); if (qv > qn) return FALSE; else if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > i1+1) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } refinex(gx,lab,ptn,0,&numcells,count,active,TRUE,&code,1,nx); if (code < 0) return FALSE; else if (code > 0 || numcells >= nx-4) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } options.writemarkers = FALSE; options.writeautoms = FALSE; options.getcanon = TRUE; options.defaultptn = FALSE; active[0] = 0; #ifdef INSTRUMENT ++a2nauty; #endif 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,deg,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } else return FALSE; } /**************************************************************************/ static void xbnds(int n2, int ne, int dmax) /* find bounds on degree for vertex n2 Store answer in data[*].* */ { int xlb,xub,m; xlb = n2 == 0 ? (connec ? 1 : 0) : dmax; if (xlb < mindeg2) xlb = mindeg2; m = mine - ne - (maxn2 - n2 -1)*maxdeg2; if (m > xlb) xlb = m; xub = maxdeg2; m = (maxe - ne) / (maxn2 - n2); if (m < xub) xub = m; data[n2].ne = ne; data[n2].dmax = dmax; data[n2].xlb = xlb; data[n2].xub = xub; } /**************************************************************************/ static void genextend(graph *g, int n2, int *deg, int ne, boolean rigid, int xlb, int xub) /* extend from n2 to n2+1 */ { int x,y,d; int *xorb,xc; int nx,i,j,imin,imax,dmax; int xlbx,xubx,n; graph gx[MAXN]; int degx[MAXN]; boolean rigidx; int dneed,need,nfeet,hideg,deg1,ft[MAXN],nfrag,frag[MAXN]; #ifdef INSTRUMENT boolean haschild; haschild = FALSE; ++nodes[n2]; if (rigid) ++rigidnodes[n2]; #endif n = n1 + n2; nx = n2 + 1; dmax = deg[n-1]; d = 0; dneed = mindeg1 - maxn2 + n2; need = 0; hideg = 0; deg1 = 0; for (i = 0; i < n1; ++i) { if (deg[i] == maxdeg1) d |= xbit[i]; if (deg[i] <= dneed) need |= xbit[i]; if (deg[i] >= 2) hideg |= xbit[i]; if (deg[i] == 1) deg1 |= xbit[i]; } if (xlb < XPOPCOUNT(need)) xlb = XPOPCOUNT(need); if (xlb > xub) return; imin = xstart[xlb]; imax = xstart[xub+1]; xorb = data[n2].xorb; if (nx == maxn2) { if (footfree) { nfeet = 0; for (j = 0; j < n2; ++j) { x = xval[j] & hideg; IFLE1BITS(x) ft[nfeet++] = xval[j] & deg1; } } if (cutfree) fragments(xval,n2,frag,&nfrag); for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if ((x & d) != 0) continue; if ((need & ~x) != 0) continue; if (simple) { for (j = n2; --j >= 0;) if (x == xval[j]) break; if (j >= 0) continue; } if (maxcommon >= 0) { for (j = n2; --j >= 0;) { y = x & xval[j]; if (XPOPCOUNT(y) > maxcommon) break; } if (j >= 0) continue; } if (footfree) { y = x & (hideg | deg1); IFLE1BITS(y) continue; for (j = 0; j < nfeet; ++j) if ((x & ft[j]) == 0) break; if (j < nfeet) continue; } if (cutfree) { y = x & (hideg | deg1); IFLE1BITS(y) continue; for (j = 0; j < nfrag; ++j) if ((x & frag[j]) == 0) break; if (j < nfrag) continue; } xval[n2] = x; if (nx == nprune) { if (curres == 0) curres = mod; #if SPLITTEST --curres; ++splitcases; continue; #else if (--curres != 0) continue; #endif } if (accept2(g,n2,x,gx,deg,xc > dmax)) if (!connec || isconnected(gx,n+1)) { ADDBIG(ecount[ne+xc],1); #ifdef INSTRUMENT haschild = TRUE; #endif (*outproc)(outfile,canonise ? gcan : gx,n1,n2+1); } } } else { for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if ((x & d) != 0) continue; if ((need & ~x) != 0) continue; if (nx == nprune) { if (curres == 0) curres = mod; #if SPLITTEST --curres; ++splitcases; continue; #else if (--curres != 0) continue; #endif } if (simple) { for (j = n2; --j >= 0;) if (x == xval[j]) break; if (j >= 0) continue; } if (maxcommon >= 0) { for (j = n2; --j >= 0;) { y = x & xval[j]; if (XPOPCOUNT(y) > maxcommon) break; } if (j >= 0) continue; } xval[n2] = x; for (j = 0; j < n; ++j) degx[j] = deg[j]; if (data[nx].ne != ne+xc || data[nx].dmax != xc) xbnds(nx,ne+xc,xc); xlbx = data[nx].xlb; xubx = data[nx].xub; if (xlbx > xubx) continue; data[nx].lo = xstart[xlbx]; data[nx].hi = xstart[xubx+1]; if (accept1(g,n2,x,gx,degx,&rigidx)) { #ifdef INSTRUMENT haschild = TRUE; #endif genextend(gx,nx,degx,ne+xc,rigidx,xlbx,xubx); } } } #ifdef INSTRUMENT if (haschild) ++fertilenodes[n2]; #endif } /**************************************************************************/ /**************************************************************************/ main(int argc, char *argv[]) { char *arg; long ltemp; boolean badargs,gotD,gote,gotf,gotmr,gotZ,gotd,gotX; long Dval1,Dval2; long dval1,dval2; int i,j,imin,imax,argnum,sw; int splitlevinc; graph g[MAXN1]; int deg[MAXN1]; bigint nout; double t1,t2; char *outfilename; char msg[201]; HELP; nauty_check(WORDSIZE,1,MAXN,NAUTYVERSIONID); if (MAXN > WORDSIZE || MAXN1 > 8*sizeof(int)-2) { fprintf(stderr,"genbg: incompatible MAXN, MAXN1 or WORDSIZE\n"); fprintf(stderr,"--See notes in program source\n"); exit(1); } badargs = FALSE; connec = FALSE; verbose = FALSE; nautyformat = FALSE; nooutput = FALSE; canonise = FALSE; greout = FALSE; simple = FALSE; graph6 = FALSE; sparse6 = FALSE; quiet = FALSE; footfree = FALSE; cutfree = FALSE; gote = FALSE; gotf = FALSE; gotmr = FALSE; gotD = FALSE; gotd = FALSE; gotZ = FALSE; gotX = splitlevinc; outfilename = NULL; maxdeg1 = maxdeg2 = MAXN; mindeg1 = mindeg2 = 0; argnum = 0; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('n',nautyformat) else SWBOOLEAN('u',nooutput) else SWBOOLEAN('q',quiet) else SWBOOLEAN('v',verbose) else SWBOOLEAN('z',simple) else SWBOOLEAN('F',footfree) else SWBOOLEAN('L',cutfree) else SWBOOLEAN('l',canonise) else SWBOOLEAN('c',connec) else SWBOOLEAN('a',greout) else SWBOOLEAN('g',graph6) else SWBOOLEAN('s',sparse6) else SWINT('Z',gotZ,maxcommon,"genbg -Z") else SWINT('X',gotX,splitlevinc,"geng -X") else SWRANGE('D',":-",gotD,Dval1,Dval2,"genbg -D") else SWRANGE('d',":-",gotd,dval1,dval2,"genbg -d") #ifdef PLUGIN_SWITCHES PLUGIN_SWITCHES #endif else badargs = TRUE; } } else if (arg[0] == '-' && arg[1] == '\0') gotf = TRUE; else { if (argnum == 0) { if (sscanf(arg,"%d",&n1) != 1) badargs = TRUE; ++argnum; } else if (argnum == 1) { if (sscanf(arg,"%d",&maxn2) != 1) badargs = TRUE; ++argnum; } else if (gotf) badargs = TRUE; else { if (!gotmr) { if (sscanf(arg,"%d/%d",&res,&mod) == 2) { gotmr = TRUE; continue; } } if (!gote) { if (sscanf(arg,"%d:%d",&mine,&maxe) == 2 || sscanf(arg,"%d-%d",&mine,&maxe) == 2) { gote = TRUE; if (maxe == 0 && mine > 0) maxe = MAXN*MAXN/4; continue; } else if (sscanf(arg,"%d",&mine) == 1) { gote = TRUE; maxe = mine; continue; } } if (!gotf) { outfilename = arg; gotf = TRUE; continue; } } } } if (argnum < 2) badargs = TRUE; else if (n1 < 1 || maxn2 < 0 || n1 > MAXN1 || n1+maxn2 > MAXN) { fprintf(stderr, ">E genbg: must have n1=1..%d, n1+n2=1..%d\n",MAXN1,MAXN); badargs = TRUE; } if (!gote) { mine = 0; maxe = n1 * maxn2; } if (!gotmr) { mod = 1; res = 0; } else if (argnum == 5 || argnum > 6) badargs = TRUE; if (gotd) { mindeg1 = dval1; mindeg2 = dval2; } if (gotD) { maxdeg1 = Dval1; maxdeg2 = Dval2; } if (maxdeg1 > maxn2) maxdeg1 = maxn2; if (maxdeg2 > n1) maxdeg2 = n1; if (connec && mine < n1+maxn2-1) mine = n1 + maxn2 - 1; if (connec && mindeg1 == 0) mindeg1 = 1; if (connec && mindeg2 == 0) mindeg2 = 1; if (maxe > n1*maxdeg1) maxe = n1*maxdeg1; if (maxe > maxn2*maxdeg2) maxe = maxn2*maxdeg2; if (mine < n1*mindeg1) mine = n1*mindeg1; if (mine < maxn2*mindeg2) mine = maxn2*mindeg2; if (!badargs && (mine > maxe || maxe < 0 || maxdeg1 < 0 || maxdeg2 < 0)) { fprintf(stderr,">E genbg: impossible mine,maxe,maxdeg values\n"); badargs = TRUE; } if (!gotZ) maxcommon = -1; if (!badargs && (mine > maxe || maxe < 0 || maxdeg1 < 0 || maxdeg2 < 0)) { fprintf(stderr, ">E genbg: impossible mine,maxe,mindeg,maxdeg values\n"); badargs = TRUE; } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if ((nautyformat!=0) + (graph6!=0) + (greout!=0) + (sparse6!=0) + (nooutput!=0) > 1) gt_abort(">E genbg: -ungsa are incompatible\n"); #ifdef OUTPROC outproc = OUTPROC; #else #ifdef OUTPROC1 outproc = write12; #endif if (nautyformat) outproc = writenauty; else if (nooutput) outproc = nullwrite; else if (sparse6) outproc = writes6x; else if (greout) outproc = writegre; else outproc = writeg6x; #endif #ifdef PLUGIN_INIT PLUGIN_INIT #endif for (i = 0; i <= maxe; ++i) ZEROBIG(ecount[i]); if (nooutput) outfile = stdout; else if (!gotf || outfilename == NULL) { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename, nautyformat ? "wb" : "w")) == NULL) { fprintf(stderr, ">E genbg: can't open %s for writing\n",outfilename); gt_abort(NULL); } /* if (!quiet) { fprintf(stderr,">A %s n=%d+%d e=%d:%d d=%d:%d D=%d:%d ", argv[0],n1,maxn2,mine,maxe, mindeg1,mindeg2,maxdeg1,maxdeg2); if (simple) fprintf(stderr,"z"); if (footfree) fprintf(stderr,"F"); if (connec) fprintf(stderr,"c"); if (maxcommon >= 0) fprintf(stderr,"Z%d",maxcommon); if (mod > 1) fprintf(stderr," class=%d/%d",res,mod); fprintf(stderr,"\n"); } */ if (!quiet) { msg[0] = '\0'; if (strlen(argv[0]) > 75) fprintf(stderr,">A %s",argv[0]); else CATMSG1(">A %s",argv[0]); CATMSG4(" n=%d+%d e=%d:%d",n1,maxn2,mine,maxe); CATMSG4(" d=%d:%d D=%d:%d ",mindeg1,mindeg2,maxdeg1,maxdeg2); if (simple) CATMSG0("z"); if (footfree) CATMSG0("F"); if (connec) CATMSG0("c"); if (maxcommon >= 0) CATMSG1("Z%d",maxcommon); if (cutfree) CATMSG0("L"); if (mod > 1) CATMSG2(" class=%d/%d",res,mod); CATMSG0("\n"); fputs(msg,stderr); fflush(stderr); } class1size = n1; for (i = 0; i < n1; ++i) { g[i] = 0; deg[i] = 0; } t1 = CPUTIME; if (maxn2 == 0) { if (res == 0) { ADDBIG(ecount[0],1); (*outproc)(outfile,g,n1,0); } } else { makeleveldata(); curres = res; if (mod <= 1) nprune = 0; else if (maxn2 >= 6) nprune = maxn2 - 2; else if (maxn2 >= 3) nprune = maxn2 - 1; else nprune = maxn2; if (gotX) { nprune += splitlevinc; if (nprune > maxn2) nprune = maxn2; if (nprune < 0) nprune = 0; } xbnds(0,0,0); imin = xstart[data[0].xlb]; imax = xstart[data[0].xub+1]; for (i = imin; i < imax; ++i) data[0].xorb[i] = -1; for (i = data[0].xlb; i <= data[0].xub; ++i) data[0].xorb[xstart[i]] = xstart[i]; genextend(g,0,deg,0,FALSE,data[0].xlb,data[0].xub); } t2 = CPUTIME; ZEROBIG(nout); for (i = 0; i <= maxe; ++i) SUMBIGS(nout,ecount[i]); if (verbose) for (i = 0; i <= maxe; ++i) if (!ISZEROBIG(ecount[i])) { fprintf(stderr,">C "); PRINTBIG(stderr,ecount[i]); fprintf(stderr," graphs with %d edges\n",i); } #ifdef INSTRUMENT fprintf(stderr,"\n>N node counts\n"); for (i = 0; i < maxn2; ++i) fprintf(stderr," level %2d: %7ld (%ld rigid, %ld fertile)\n", i,nodes[i],rigidnodes[i],fertilenodes[i]); fprintf(stderr,">A1 %ld calls to accept1, %ld nauty, %ld succeeded\n", a1calls,a1nauty,a1succs); fprintf(stderr, ">A2 %ld calls to accept2, %ld nuniq, %ld nauty, %ld succeeded\n", a2calls,a2uniq,a2nauty,a2succs); fprintf(stderr,"\n"); #endif #if SPLITTEST fprintf(stderr,">Z %lu splitting cases at level %d; cpu=%3.2f sec\n", splitcases,nprune,t2-t1); #else if (!quiet) { fprintf(stderr,">Z "); PRINTBIG(stderr,nout); fprintf(stderr," graphs generated in %3.2f sec\n",t2-t1); } #endif exit(0); } nauty24r2/planarity.c0000600000604200001440000110113711274163463013462 0ustar bdmusers/* planarity.c - code for planarity testing of undirected graphs. * Method of Boyer and Myrvold, programmed by Paulette Lieby. * The copyright of this program is owned by the Magma project. * Distributed with nauty by permission. ***************************************************************/ /* * sparseg_adjl.c */ /* What: ***** Implementing: Some high-level functions on the sparse graph as an adjacency list. In particular, testing if it is planar. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif boolean sparseg_adjl_plan_and_iso (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int e, int *c, t_ver_sparse_rep **VR, t_adjl_sparse_rep **AR, t_embed_sparse_rep **ER, int *nbr_e_obs) /* the input graph is given as an adjacency list: V: array of vertices n: size of graph A: adjacency list e: number of edges if the graph is planar the embedding is stored in VR and ER; the embedding contains e edges (nbr_e_obs not used) if the graph is non planar the obstruction is returned in VR and AR together with the number of edges in nbr_e_obs in all cases is also returned the number of components (in c) */ { t_dlcl **dfs_tree, **back_edges, **mult_edges; int edge_pos, v, w; boolean ans; t_ver_edge *embed_graph; ans = sparseg_adjl_is_planar(V, n, A, c, &dfs_tree, &back_edges, &mult_edges, &embed_graph, &edge_pos, &v, &w); if (!ans) { embedg_obstruction(V, A, dfs_tree, back_edges, embed_graph, n, &edge_pos, v, w, VR, AR, nbr_e_obs); } else { embedg_embedding(V, A, embed_graph, n, e, *c, edge_pos, mult_edges, VR, ER); } sparseg_dlcl_delete(dfs_tree, n); sparseg_dlcl_delete(back_edges, n); sparseg_dlcl_delete(mult_edges, n); embedg_VES_delete(embed_graph, n); return ans; } int * sparseg_adjl_footprint (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int v) /* return v's footprint: an array fp of size n where fp[i] = index of (directed) edge [v, i] in A */ { /* note that we won't initialise the array: its subsequent usage doesn't require it */ int *fp, e; fp = (int *) mem_malloc(sizeof(int) * n); if (V[v].first_edge == NIL) /* do nothing */ return fp; e = V[v].first_edge; while (e != NIL) { fp[A[e].end_vertex] = e; e = A[e].next; } return fp; } void sparseg_adjl_print (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, boolean user_level) { int v; for (v = 0; v < n; v++) { int next; if (user_level) fprintf(stdout, "%d:\t", v + 1); else fprintf(stdout, "%d:\t", v); next = V[v].first_edge; while (next != NIL) { if (user_level) fprintf(stdout, "%d ", A[next].end_vertex + 1); else fprintf(stdout, "%d ", A[next].end_vertex); next = A[next].next; } fprintf(stdout, "\n"); } } void sparseg_adjl_embed_print (t_ver_sparse_rep *V_e, int n, t_adjl_sparse_rep *A, t_embed_sparse_rep *E, boolean user_level) /* print the embedding given by E, edges are referred to by their index in A and V_e[v].first_edge is the index in E of the first edge (in the embedding's order) incident from v note that E is NOT indexed by the same vertices' array that indexes A (at the creation of the sparse graph) */ { int v; for (v = 0; v < n; v++) { int start, next; if (user_level) fprintf(stdout, "%d:\t", v + 1); else fprintf(stdout, "%d:\t", v); if (V_e[v].first_edge == NIL) { fprintf(stdout, "\n"); continue; } start = next = V_e[v].first_edge; if (user_level) fprintf(stdout, "%d ", A[ E[next].in_adjl ].end_vertex + 1); else fprintf(stdout, "%d ", A[ E[next].in_adjl ].end_vertex); next = E[next].next; while (next != start) /* recall that in E edges are linked into a circular list */ { if (user_level) fprintf(stdout, "%d ", A[ E[next].in_adjl ].end_vertex + 1); else fprintf(stdout, "%d ", A[ E[next].in_adjl ].end_vertex); next = E[next].next; } fprintf(stdout, "\n"); } } graph * sparseg_adjl_to_nauty_graph (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A) /* write the sparse graph as a nauty graph */ { int m, v, e, i; graph *g; m = (n + WORDSIZE - 1) / WORDSIZE; g = (graph *) mem_malloc(n * m * sizeof(graph)); for (i = (long) m * n; --i >= 0;) g[i] = 0; /* we first copy V and A's information into g */ for (v = 0; v < n; v++) { e = V[v].first_edge; while (e != NIL) /* A[e].end_vertex is the next neighbour in the list, A[e].next points to the next edge in the list */ { if (A[e].end_vertex != v) /* no loops */ { ADDELEMENT(GRAPHROW(g, v, m), A[e].end_vertex); } e = A[e].next; } } return g; } #if 0 t_edge_sparse_rep * sparseg_adjl_edges (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int e, boolean digraph) /* e is the number of edges */ { t_edge_sparse_rep *edges; int m, u, v, pos_e; graph *g; edges = (t_edge_sparse_rep *) mem_malloc(sizeof(t_edge_sparse_rep) * e); m = (n + WORDSIZE - 1) / WORDSIZE; g = sparseg_adjl_to_nauty_graph(V, n, A); pos_e = 0; for (u = 0; u < n; u++) { v = digraph == TRUE ? 0 : u + 1; for (; v < n; v++) { if (ISELEMENT(GRAPHROW(g, u, m), v)) { t_edge_sparse_rep edge; edge.ends[0] = u; edge.ends[1] = v; edges[pos_e++] = edge; } } } ASSERT(pos_e == e); mem_free(g); return edges; } #endif t_edge_sparse_rep * sparseg_adjl_edges (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int e, boolean digraph) /* e is the number of edges */ { #if 0 t_edge_sparse_rep *edges; int u, v, pos_e, *loops, *foot_print; graph *g; loops = (int *) mem_malloc(sizeof(int) * n); for (v = 0; v < n; v++) { loops[v] = 0; } edges = (t_edge_sparse_rep *) mem_malloc(sizeof(t_edge_sparse_rep) * e); pos_e = 0; foot_print = (int *) mem_malloc(sizeof(int) * n); for (u = 0; u < n; u++) foot_print[u] = NIL; for (v = 0; v < n; v++) { int ne; t_edge_sparse_rep edge; ne = V[v].first_edge; while (ne != NIL) { u = A[ne].end_vertex; if (digraph || (!digraph && u > v)) { foot_print[u] = v; } else if (!digraph && u == v) { if (loops[v] == 0) { foot_print[u] = v; } loops[v] ^= 1; } ne = A[ne].next; } for (u = 0; u < n; u++) if (foot_print[u] == v) { edge.ends[0] = v; edge.ends[1] = u; edges[pos_e++] = edge; } } ASSERT(pos_e == e); mem_free(loops); mem_free(foot_print); return edges; #endif /* there must be a simpler way */ #if 0 typedef struct edge_list { int size; t_edge_sparse_rep *edges; } t_edge_list; t_edge_list *edge_table; t_edge_sparse_rep *edges; int u, v, nbr_e, pos_e, *loops; graph *g; loops = (int *) mem_malloc(sizeof(int) * n); for (v = 0; v < n; v++) { loops[v] = 0; } /* now create an edge table as follows: - there are n lists in total - their respective size is given by size - their contents by *edges: edge_table[i] will contain all the edges whose end-point is i: these edges, by construction, will be sorted according to their starting point what for? to finish off each start-vertex processing with a bucket sort so that the edges are sorted wrt start- & end-point bucket sort is linear, hence why... */ edge_table = (t_edge_list *) mem_malloc(sizeof(t_edge_list) * n); for (v = 0; v < n; v++) { edge_table[v].size = 0; edge_table[v].edges = NP; } edges = (t_edge_sparse_rep *) mem_malloc(sizeof(t_edge_sparse_rep) * e); nbr_e = 0; pos_e = 0; for (v = 0; v < n; v++) { int ne, w, u; ne = V[v].first_edge; while (ne != NIL) { u = A[ne].end_vertex; if (digraph || (!digraph && u > v)) { t_edge_sparse_rep edge; edge.ends[0] = v; edge.ends[1] = u; /* now stick this edge into the table: one may ponder as to the cost of constantly reallocating memory... some cursory tests in another context tell me that this is pretty much ok (and certainly better than allocating n^2 storage space) */ if (edge_table[u].size == 0) { edge_table[u].edges = (t_edge_sparse_rep *) mem_malloc(sizeof(t_edge_sparse_rep)); } else { edge_table[u].edges = (t_edge_sparse_rep *) mem_realloc(edge_table[u].edges, sizeof(t_edge_sparse_rep) * (edge_table[u].size + 1)); } (edge_table[u].edges)[edge_table[u].size] = edge; edge_table[u].size += 1; nbr_e++; } else if (!digraph && u == v) { if (loops[v] == 0) { t_edge_sparse_rep edge; edge.ends[0] = v; edge.ends[1] = u; if (edge_table[u].size == 0) { edge_table[u].edges = (t_edge_sparse_rep *) mem_malloc(sizeof(t_edge_sparse_rep)); } else { edge_table[u].edges = (t_edge_sparse_rep *) mem_realloc(edge_table[u].edges, sizeof(t_edge_sparse_rep) * (edge_table[u].size + 1)); } (edge_table[u].edges)[edge_table[u].size] = edge; edge_table[u].size += 1; nbr_e++; } loops[v] ^= 1; } ne = A[ne].next; } /* bucket sort must take place here: of course the whole lot is not exactly linear! since we perform the sort n times; but we can hope for a "good" ?? average behaviour: in any case this must be better that checking adjacencies n^2 times in a sparse rep. (see edge_set_iset_assure) */ for (w = 0; w < n; w++) { if (edge_table[w].size > 0) { for (u = 0; u < edge_table[w].size; u++) { ASSERT((edge_table[w].edges)[u].ends[0] == v); edges[pos_e++] = (edge_table[w].edges)[u]; } mem_free(edge_table[w].edges); edge_table[w].size = 0; edge_table[w].edges = NP; } } } ASSERT(nbr_e == e); ASSERT(pos_e == e); mem_free(loops); mem_free(edge_table); return edges; #endif t_edge_sparse_rep *edges; int u, v, pos_e, *loops; graph *g; edges = (t_edge_sparse_rep *) mem_malloc(sizeof(t_edge_sparse_rep) * e); loops = (int *) mem_malloc(sizeof(int) * n); for (v = 0; v < n; v++) { loops[v] = 0; } pos_e = 0; for (v = 0; v < n; v++) { int ne; ne = V[v].first_edge; while (ne != NIL) { int u; u = A[ne].end_vertex; if (digraph || (!digraph && u > v)) { t_edge_sparse_rep edge; edge.ends[0] = v; edge.ends[1] = u; edges[pos_e++] = edge; } else if (!digraph && u == v) { if (loops[v] == 0) { t_edge_sparse_rep edge; edge.ends[0] = v; edge.ends[1] = u; edges[pos_e++] = edge; } loops[v] ^= 1; } ne = A[ne].next; } } ASSERT(pos_e == e); mem_free(loops); return edges; } /* * sparseg_adjl_modify.c */ /* What: ***** Implementing: Some high-level functions on the sparse graph as an adjacency list. In particular, adding/removing vertices/edges. NOTE: Most of the functions implicitely assume that the graph is undirected; this must be slightly rewritten for the general case -- just haven't got the time right now... ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif boolean sparseg_adjl_add_edge (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep **A, int *size_A, int *pos, int u, int v, boolean CHECK) /* add the UNDIRECTED edge to the sparse graph (V, n, A) - pos records where to add the next edge in A - if pos + 1 == size_A, we must extend A we check if the edge is already in the graph iff CHECK true also we assume that the graph (V, n, A) is undirected */ { boolean edge_exists; edge_exists = FALSE; if (CHECK) { edge_exists = sparseg_adjl_dir_edge_exists(V, n, *A, u, v); if (edge_exists) return FALSE; } if (*pos == *size_A) { IF_DEB( fprintf(stdout, "realloc \n"); ) *size_A += 2; /* add two directed edges */ *A = (t_adjl_sparse_rep *) mem_realloc(*A, sizeof(t_adjl_sparse_rep) * *size_A); } else if (*pos + 1 == *size_A) { IF_DEB( fprintf(stdout, "realloc \n"); ) *size_A += 1; /* add two directed edges */ *A = (t_adjl_sparse_rep *) mem_realloc(*A, sizeof(t_adjl_sparse_rep) * *size_A); } ASSERT(*pos + 1 < *size_A); sparseg_adjl_add_dir_edge(V, n, A, size_A, pos, u, v, FALSE); sparseg_adjl_add_dir_edge(V, n, A, size_A, pos, v, u, FALSE); return TRUE; } boolean sparseg_adjl_add_edge_no_extend (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int size_A, int *pos, int u, int v, boolean CHECK) /* like sparseg_adjl_add_edge but here we are guaranteed that pos + 1 < size_A (unless that for some reason we attempt to add an edge which is already there) this feature is required when A is part of a Magma block: we do not want to reallocate A here (would be done at a higher level) we check if the edge is already in the graph iff CHECK true also, we assume that we use this procedur only when dealing with an undirected graph */ { boolean edge_added; edge_added = sparseg_adjl_add_dir_edge_no_extend(V, n, A, size_A, pos, u, v, CHECK); if (edge_added) sparseg_adjl_add_dir_edge_no_extend(V, n, A, size_A, pos, v, u, FALSE); return edge_added; } boolean sparseg_adjl_add_dir_edge (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep **A, int *size_A, int *pos, int u, int v, boolean CHECK) /* add the DIRECTED edge to the sparse graph (V, n, A) - pos records where to add the next edge in A - if pos >= size_A, we must extend A we check if the edge is already in the graph iff CHECK true */ { boolean edge_exists; edge_exists = FALSE; if (CHECK) { edge_exists = sparseg_adjl_dir_edge_exists(V, n, *A, u, v); if (edge_exists) return FALSE; } if (*pos == *size_A) { *size_A += 1; /* add one directed edge */ *A = (t_adjl_sparse_rep *) mem_realloc(*A, sizeof(t_adjl_sparse_rep) * *size_A); } ASSERT(*pos < *size_A); sparseg_adjl_add_dir_edge_no_extend(V, n, *A, *size_A, pos, u, v, FALSE); return TRUE; } boolean sparseg_adjl_add_dir_edge_no_extend (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int size_A, int *pos, int u, int v, boolean CHECK) /* add an edge where A is guaranteed to be be big enough (unless that for some reason we attempt to add an edge which is already there) this feature is required when A is part of a Magma block: we do not want to reallocate A here (would be done at a higher level) we check if the edge is already in the graph iff CHECK true */ { /* given the way V and A represent the graph, it is simplest to add the new edge at the beginning of i's adj. list */ int i_v; t_adjl_sparse_rep a; if (CHECK && sparseg_adjl_dir_edge_exists(V, n, A, u, v)) return FALSE; if (*pos >= size_A) DIE(); /* otherwise always add the edge */ i_v = *pos; a.end_vertex = v; a.next = V[u].first_edge; A[(*pos)++] = a; V[u].first_edge = i_v; return TRUE; } boolean sparseg_adjl_remove_edge_no_red (t_ver_sparse_rep *V, t_adjl_sparse_rep *A, int u, int v) /* remove the UNDIRECTED edge from sparse graph (V, A) if (u, v) is not an edge then nothing changes (and return FALSE) A will be left with "holes" */ { sparseg_adjl_remove_dir_edge_no_red(V, A, u, v); return sparseg_adjl_remove_dir_edge_no_red(V, A, v, u); } boolean sparseg_adjl_remove_dir_edge_no_red (t_ver_sparse_rep *V, t_adjl_sparse_rep *A, int u, int v) /* remove the DIRECTED edge from the sparse graph (V, n, A) if (u, v) is not an edge then nothing changes (and return FALSE) A will be left with "holes" */ { int cur_e, prev_e; cur_e = V[u].first_edge; if (cur_e == NIL) /* (u, v) is not an edge */ return FALSE; if (A[cur_e].end_vertex == v) { V[u].first_edge = A[cur_e].next; return TRUE; /* done */ } while (A[cur_e].end_vertex != v) /* if (u, v) is an edge then this loop will terminate */ { prev_e = cur_e; cur_e = A[cur_e].next; if (cur_e == NIL) /* (u, v) is not an edge */ return FALSE; } ASSERT(A[cur_e].end_vertex == v); A[prev_e].next = A[cur_e].next; return TRUE; } int sparseg_adjl_remove_all_dir_edge_no_red (t_ver_sparse_rep *V, t_adjl_sparse_rep *A, int u, int v) /* remove all DIRECTED edges [u, v] from the non-simple sparse graph (V, n, A) if (u, v) is not an edge then nothing changes; we return the number of edges removed A will be left with "holes" */ { int cur_e, prev_e, e_removed; if (V[u].first_edge == NIL) /* (u, v) is not an edge */ return 0; e_removed = 0; while (A[V[u].first_edge].end_vertex == v) { V[u].first_edge = A[V[u].first_edge].next; e_removed++; if (V[u].first_edge == NIL) return e_removed; } ASSERT(A[V[u].first_edge].end_vertex != v); prev_e = V[u].first_edge; cur_e = A[prev_e].next; while (cur_e != NIL) { if (A[cur_e].end_vertex == v) { A[prev_e].next = A[cur_e].next; e_removed++; cur_e = A[cur_e].next; } else { prev_e = cur_e; cur_e = A[cur_e].next; } } return e_removed; } void sparseg_adjl_add_vertices (t_ver_sparse_rep **V, int n, int nmore) /* add nmore vertices V is assumed to have length n */ { int v; *V = (t_ver_sparse_rep *) mem_realloc(*V, sizeof(t_ver_sparse_rep) * (n + nmore)); sparseg_adjl_add_vertices_no_extend(*V, n, nmore); } void sparseg_adjl_add_vertices_no_extend (t_ver_sparse_rep *V, int n, int nmore) /* add nmore vertices, here V is assumed to have length n + nmore (ie V has already been made bigger) */ { int v; for (v = n; v < n + nmore; v++) { V[v].first_edge = NIL; } } void sparseg_adjl_remove_vertex (t_ver_sparse_rep **V, int n, t_adjl_sparse_rep *A, int pos_A, int w, int *e) /* V is assumed to have length n: we will reallocate V so that V will have length n-1 A is occupied from [0..pos-1], A will be left with holes we also assume that the graph can have loops and multiple edges; further, we the edge counting implicitely assumes that graph is undirected!!! this must be eventually fixed */ { int v, nv, edge, loops; t_ver_sparse_rep *new_V; /* we first count the loops if any */ loops = 0; edge = (*V)[w].first_edge; while (edge != NIL) { loops = A[edge].end_vertex == w ? loops + 1 : loops; edge = A[edge].next; } ASSERT(loops % 2 == 0); loops /= 2; /* we recreate the vertices array */ new_V = (t_ver_sparse_rep *) mem_malloc(sizeof(t_ver_sparse_rep) * (n - 1)); for (v, nv = 0; v < n; v++, nv++) { if (v == w) { nv--; } else { new_V[nv].first_edge = (*V)[v].first_edge; } } mem_free(*V); *V = new_V; *e -= loops; sparseg_adjl_remove_vertex_no_red(*V, n, A, w, e); /* oops! not relabelling vertices can wreck havock! */ sparseg_adjl_relabel_vertex(A, pos_A, w); } void sparseg_adjl_remove_vertex_no_red (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int w, int *e) /* here V has already size n - 1 and has been initialised, all what remains to do is to remove the edges incident from w in A A will be left with holes */ { int v, nbr_e_removed; nbr_e_removed = 0; for (v = 0; v < n - 1; v++) { nbr_e_removed += sparseg_adjl_remove_all_dir_edge_no_red(V, A, v, w); } *e= *e - nbr_e_removed; } void sparseg_adjl_relabel_vertex (t_adjl_sparse_rep *A, int pos, int u) /* relabel all vertices v > u as v-1 (required when removing a vertex) */ { int i; for (i = 0; i < pos; i++) { A[i].end_vertex = A[i].end_vertex > u ? A[i].end_vertex - 1 : A[i].end_vertex; } } /* * sparseg_adjl_pred.c */ /* What: ***** Implementing: Some high-level functions on the sparse graph as an adjacency list: predicates. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif boolean sparseg_adjl_dir_edge_exists (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int u, int v) /* does the directed edge [u, v] already exist in the graph */ { int cur_e, prev_e; cur_e = V[u].first_edge; if (cur_e == NIL) return FALSE; if (A[cur_e].end_vertex == v) { return TRUE; } while (A[cur_e].end_vertex != v) { prev_e = cur_e; cur_e = A[cur_e].next; if (cur_e == NIL) /* (u, v) is not an edge */ return FALSE; } ASSERT(A[cur_e].end_vertex == v); return TRUE; } boolean sparseg_adjl_u_adj_v (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int u, int v) /* is u adj. to v */ { return sparseg_adjl_dir_edge_exists(V, n, A, u, v); } boolean sparseg_adjl_sub (t_ver_sparse_rep *V1, int n1, t_adjl_sparse_rep *A1, t_ver_sparse_rep *V2, int n2, t_adjl_sparse_rep *A2) /* test if the (V1, n1, A1) sparse graph is a subgraph of the (V2, n2, A2) graph */ { int v, *fp, n, bign, i; n = n1 > n2 ? n2 : n1; bign = n1 > n2 ? n1 : 0; fp = (int *) mem_malloc(sizeof(int) * n); for (i = 0; i < n; i++) fp[i] = NIL; for (v = 0; v < n; v++) { int ne1, ne2; ne1 = V1[v].first_edge; ne2 = V2[v].first_edge; if (ne1 == NIL) { continue; } else if (ne2 == NIL) { mem_free(fp); return FALSE; } while (ne2 != NIL) { int u2; u2 = A2[ne2].end_vertex; fp[u2] = v; ne2 = A2[ne2].next; } while (ne1 != NIL) { int u1; u1 = A1[ne1].end_vertex; if (fp[u1] != v) { mem_free(fp); return FALSE; } ne1 = A1[ne1].next; } } mem_free(fp); for (v = n; v < bign; v++) /* those vertices must not be end points of edges: this chcek is only necessary in the digraph case */ { if (V1[v].first_edge != NIL) return FALSE; } return TRUE; } boolean sparseg_adjl_eq (t_ver_sparse_rep *V1, int n1, t_adjl_sparse_rep *A1, t_ver_sparse_rep *V2, int n2, t_adjl_sparse_rep *A2) /* compare the two sparse graphs (V1, n1, A1) & (V2, n2, A2) we don't know their number of edges */ { if (n1 != n2) return FALSE; return sparseg_adjl_sub(V1, n1, A1, V2, n2, A2) && sparseg_adjl_sub(V2, n2, A2, V1, n1, A1); } /* * sparseg_dlcl_misc.c */ /* What: ***** Implementing: Housekeeping for an internal sparse graph representation internal to the planarity tester and obstruction isolator. This sparse graph consists of an array of doubly linked circular lists (the neighbour lists for each vertex). ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ /* aproto: beginstatic -- don't touch this!! */ static boolean sparseg_dlcl_is_present (t_dlcl *, int, t_dlcl **); /* aproto: endstatic -- don't touch this!! */ #ifndef PLANAR_IN_MAGMA #endif void sparseg_dlcl_delete (t_dlcl **g, int n) { int i; for (i = 0; i < n; i++) { embedg_dlcl_delete(g[i]); } mem_free(g); } void sparseg_dlcl_print (t_dlcl **g, int n) { int i; for (i = 0; i < n; i++) { fprintf(stdout,"%d:\t", i); embedg_dlcl_print(g[i]); } } static boolean sparseg_dlcl_is_present (t_dlcl *l, int label, t_dlcl **p) { *p = embedg_dlcl_find(l, label); return *p == NP ? FALSE : TRUE; } boolean sparseg_dlcl_is_adjacent (t_dlcl **g, int n, int v, int u, t_dlcl **p) /* is u adjacent to v */ { ASSERT(v >= 0 && v < n && u >= 0 && u < n); return sparseg_dlcl_is_present(g[v], u, p); } void sparseg_dlcl_append_to_neigh_list (t_dlcl **g, int n, int v, int u, int in_adjl) /* append u to the neighbour list of v */ { t_dlcl *u_rec; u_rec = embedg_dlcl_rec_new(u); u_rec->in_adjl = in_adjl; g[v] = embedg_dlcl_rec_append(g[v], u_rec); } void sparseg_dlcl_to_sparseg (t_dlcl **g, int n, int e, t_ver_sparse_rep **V, t_adjl_sparse_rep **A) /* e is the number of undirected edges of g convert a dlcl into the standard sparseg rep. as an adjacency list */ { int i_e, v; *V = (t_ver_sparse_rep *) mem_malloc(sizeof(t_ver_sparse_rep) * n); *A = (t_adjl_sparse_rep *) mem_malloc(sizeof(t_adjl_sparse_rep) * 2 * e); for (v = 0; v < n; v++) (*V)[v].first_edge = NIL; i_e = 0; for (v = 0; v < n; v++) { t_dlcl *l, *p; l = p = g[v]; if (!embedg_dlcl_is_empty(p)) { t_adjl_sparse_rep a; ASSERT((*V)[v].first_edge == NIL); (*V)[v].first_edge = i_e; a.end_vertex = p->info; a.next = i_e + 1; (*A)[i_e++] = a; p = embedg_dlcl_list_next(p); while (p != l) { a.end_vertex = p->info; a.next = i_e + 1; (*A)[i_e++] = a; p = embedg_dlcl_list_next(p); } /* end of list for v */ (*A)[i_e - 1].next = NIL; } } ASSERT(i_e == 2 * e); } boolean sparseg_dlcl_sub (t_dlcl **g1, int n1, t_dlcl **g2, int n2) /* is g2 a subgraph of g1 I request that both graphs have same order This is not used anywhere... do we need it??? */ { int n, v, *fp; if (n1 != n2) return FALSE; n = n1; fp = (int *) mem_malloc(sizeof(int) * n); for (v = 0; v < n; v++) fp[v] = NIL; for (v = 0; v < n; v++) { t_dlcl *l1, *p1, *l2, *p2; l1 = p1 = g1[v]; l2 = p2 = g2[v]; if (embedg_dlcl_is_empty(p1) && !embedg_dlcl_is_empty(p2)) { mem_free(fp); return FALSE; } if (embedg_dlcl_is_empty(p2)) { continue; } fp[p1->info] = v; p1 = embedg_dlcl_list_next(p1); while (p1 != l1) { fp[p1->info] = v; p1 = embedg_dlcl_list_next(p1); } if (fp[p2->info] != v) { mem_free(fp); return FALSE; } p2 = embedg_dlcl_list_next(p2); while (p2 != l2) { if (fp[p2->info] != v) { mem_free(fp); return FALSE; } } } mem_free(fp); return TRUE; } /* * VES_misc.c */ /* What: ***** Implementing: All low-level routines for the VES structure: - the VES structure is solely used within the planarity tester and obstruction isolator - it stores vertices, virtual vertices and edges --more on this later-- - it allows for circular doubly linked lists, hence enabling us -among other things- to store the graph embedding if the tester is successful - basic features: + the VES has exactly size 2n + 2(3n-5) : we add at most one more edge than the max for a planar graph (need to x by 2: we store directed edges) + a vertex and the edges incident FROM it are linked in a doubly linked circular list + where a vertex is inserted between two of its outcoming edges determines an external face walk for a bicomponent + the twin edge is more commonly known as the inverse edge + we have tree and back edges (from the DFS), and short-cut edges which are added by the tester -but short-cut edges are added in such a way as to maintain planarity (in a local sense) + vertices and edges can be marked (visited for example) + they have an orientation which must be eventuall recovered and which is set in the merge_bicomp routine + vertices are essentially known via their DFI or DFS index (though their label is stored too) blah, blah.... later then. Have a look at embedg_planar_alg_init which initialises the VES structure ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_SCE(x) {} #define IF_DEB_PROPER_FACE(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ boolean embedg_VES_is_vertex (int n, int i) /* is this a vertex (relative to the "big" array of size 2n + 2(3n-5)) */ { return i < n ? TRUE : FALSE; } boolean embedg_VES_is_virtual_vertex (int n, int i) /* is this a virtual vertex (relative to the "big" array of size 2n + 2(3n-5)) a virtual vertex is a vertex v^c which denotes the DFS parent of the child c see embedg_planar_alg_init for more */ { return i >= n && i < 2*n ? TRUE : FALSE; } boolean embedg_VES_is_edge (int n, int i) /* is this an edge (relative to the "big" array of size 2n + 2(3n-5)) */ { return i >= 2*n ? TRUE : FALSE; } boolean embedg_VES_is_tree_edge (t_ver_edge *embed_graph, int n, int i) /* is this s tree edge */ { return embedg_VES_is_edge(n, i) && embed_graph[i].type == TE; } boolean embedg_VES_is_back_edge (t_ver_edge *embed_graph, int n, int i) /* is this a back edge */ { return embedg_VES_is_edge(n, i) && embed_graph[i].type == BE; } boolean embedg_VES_is_short_cut_edge (t_ver_edge *embed_graph, int n, int i) /* as the name indicates... */ { return embedg_VES_is_edge(n, i) && embed_graph[i].type == SCE; } void embedg_VES_print_vertex (int n, int v) { ASSERT(embedg_VES_is_vertex(n, v)); fprintf(stdout, "%d ", v); } void embedg_VES_print_virtual_vertex (t_ver_edge *embed_graph, int n, int v) { int c; ASSERT(embedg_VES_is_virtual_vertex(n, v)); c = v - n; fprintf(stdout, "%d^%d ", embed_graph[c].DFS_parent, c); } void embedg_VES_print_any_vertex (t_ver_edge *embed_graph, int n, int v) { if (embedg_VES_is_vertex(n, v)) { embedg_VES_print_vertex(n, v); } else { embedg_VES_print_virtual_vertex(embed_graph, n, v); } } void embedg_VES_print_any_rec (t_ver_edge *embed_graph, int n, int r) { if (embedg_VES_is_edge(n, r)) { embedg_VES_print_edge(embed_graph, n, r); } else { embedg_VES_print_any_vertex(embed_graph, n, r); } } void embedg_VES_print_edge (t_ver_edge *embed_graph, int n, int e) { int v, prev, cur; ASSERT(embedg_VES_is_edge(n, e)); /* must find the vertex in the doubly linked circular list of vertices/edges */ prev = e; cur = v = embed_graph[e].link[0]; if (embedg_VES_is_vertex(n, v) || embedg_VES_is_virtual_vertex(n, v)) { embedg_VES_print_any_vertex(embed_graph, n, v); fprintf(stdout, ", "); embedg_VES_print_any_vertex(embed_graph, n, embed_graph[e].neighbour); fprintf(stdout, "):0\n"); } else while (!embedg_VES_is_vertex(n, v) && !embedg_VES_is_virtual_vertex(n, v)) { v = embedg_VES_get_next_in_dlcl(embed_graph, n, cur, prev); if (embedg_VES_is_vertex(n, v) || embedg_VES_is_virtual_vertex(n, v)) { embedg_VES_print_any_vertex(embed_graph, n, v); fprintf(stdout, ", "); embedg_VES_print_any_vertex(embed_graph, n, embed_graph[e].neighbour); fprintf(stdout, "):0\n"); } else { prev = cur; cur = v; } } } void embedg_VES_print_flipped_edges (t_ver_edge *embed_graph, int n, int edge_pos) /* print those edges in the structure whose sign is CLOCKW, ie which have been flipped at some stage */ { int e; for (e = 2*n; e <= edge_pos; e++) { if (!embedg_VES_is_short_cut_edge(embed_graph, n, e)) /* we don't care about the short-cut edges */ { if (embed_graph[e].sign != CCLOCKW) { embedg_VES_print_edge(embed_graph, n, e); } } } } int embedg_VES_get_edge_from_ver (t_ver_edge *embed_graph, int n, int v) /* not used anywhere; why is this here??? */ { int in, e; ASSERT(embedg_VES_is_vertex(n, v) || embedg_VES_is_virtual_vertex(n, v)); in = embedg_VES_is_edge(n, embed_graph[v].link[0]) ? 0 : 1; e = embed_graph[v].link[in]; ASSERT(embedg_VES_is_edge(n, e)); return e; } int embedg_VES_get_ver_from_edge (t_ver_edge *embed_graph, int n, int e) { int in, v; ASSERT(embedg_VES_is_edge(n, e)); in = embedg_VES_is_vertex(n, embed_graph[v].link[0]) || embedg_VES_is_virtual_vertex(n, embed_graph[v].link[0]) ? 0 : 1; v = embed_graph[v].link[in]; ASSERT(embedg_VES_is_vertex(n, v) || embedg_VES_is_virtual_vertex(n, v)); return v; } int embedg_VES_get_twin_edge (t_ver_edge *embed_graph, int n, int e) /* the twin edge is understood as being the inverse edge */ { int twin; ASSERT(embedg_VES_is_edge(n, e)); twin = e % 2 == 0 ? e + 1 : e - 1; ASSERT(embedg_VES_is_edge(n, twin)); return twin; } int embedg_VES_get_ver_from_virtual (t_ver_edge *embed_graph, int n, int vv) /* get v from the virtual vertex v^c */ { int v; ASSERT(embedg_VES_is_virtual_vertex(n, vv)); v = embed_graph[vv - n].DFS_parent; return v; } int embedg_VES_get_ver (t_ver_edge *embed_graph, int n, int v) { if (embedg_VES_is_virtual_vertex(n, v)) return embedg_VES_get_ver_from_virtual(embed_graph, n, v); return v; } int embedg_VES_get_next_in_dlcl (t_ver_edge *embed_graph, int n, int r, int prev) /* r is a (virtual) vertex or edge record in embed_graph: get the next in the list (formed by the .link[] fields) in the doubly linked circular list so that prev != next -- NOTE: a priori these lists always contain 2 elts at least so that there shouldn't be any problem... --> huh? is that true? */ { return embed_graph[r].link[0] == prev ? embed_graph[r].link[1] : embed_graph[r].link[0]; } void embedg_VES_walk_bicomp (t_ver_edge *embed_graph, int n, int v, int vin) /* walk the external face of the bicomp starting at VIRTUAL vertex v entered via vin this of course assumes that the "thing" rooted at v is a bicomponent -- depending where we are at in the tester this is not necessarily the case -- I comment upon this in merge_bicomps.c: embedg_VES_merge_pertinent_bicomps */ { int start, startin, s, sin; ASSERT(embedg_VES_is_virtual_vertex(n, v)); embedg_VES_print_virtual_vertex(embed_graph, n, v); s = NIL; start = v; startin = vin; while (s != v) { embedg_VES_get_succ_on_ext_face(embed_graph, n, start, startin, FALSE, 0, &s, &sin); if (embedg_VES_is_virtual_vertex(n, s)) { embedg_VES_print_virtual_vertex(embed_graph, n, s); } else { embedg_VES_print_vertex(n, s); } start = s; startin = sin; } fprintf(stdout, "\n"); } void embedg_VES_print_adj_list (t_ver_edge *embed_graph, int n, int r, boolean consistent) /* print r's adjacency list - r can be a vertex or edge the boolean if true assumes that the list is consistent (will determine the way we traverse the list) a priori we should get the same result either way */ { if (consistent) { int next; embedg_VES_print_any_rec(embed_graph, n, r); next = embed_graph[r].link[0]; while (next != r) { embedg_VES_print_any_rec(embed_graph, n, next); next = embed_graph[next].link[0]; } } else { int prev, cur, next; embedg_VES_print_any_rec(embed_graph, n, r); prev = r; cur = embed_graph[r].link[0]; while (cur != r) { embedg_VES_print_any_rec(embed_graph, n, cur); next = embedg_VES_get_next_in_dlcl(embed_graph, n, cur, prev); prev = cur; cur = next; } } } boolean embedg_VES_is_adj_list_consistent (t_ver_edge *embed_graph, int n, int r) /* checks that r's adjacency list is consistent: ie, that either traversing it using link[0] always or traversing it using embedg_VES_get_next_in_dlcl gives the SAME result */ { int *list_link, *list_n_dldl, il, id, i; list_link = (int *) mem_malloc(sizeof(int) * 2 * n); list_n_dldl = (int *) mem_malloc(sizeof(int) * 2 * n); /* must allocate 2*n space: I could have TE and SCE with same neighbour (or BE and SCE as well) */ il = id = -1; /* traversing the list via link[0] */ { int next; list_link[++il] = r; next = embed_graph[r].link[0]; while (next != r) { list_link[++il] = next; next = embed_graph[next].link[0]; } } /* traversing the list using embedg_VES_get_next_in_dlcl */ { int prev, cur, next; list_n_dldl[++id] = r; prev = r; cur = embed_graph[r].link[0]; while (cur != r) { list_n_dldl[++id] = cur; next = embedg_VES_get_next_in_dlcl(embed_graph, n, cur, prev); prev = cur; cur = next; } } if (il != id) { mem_free(list_link); mem_free(list_n_dldl); return FALSE; } for (i = 0; i <= il; i++) { if (list_link[i] != list_n_dldl[i]) { mem_free(list_link); mem_free(list_n_dldl); return FALSE; } } mem_free(list_link); mem_free(list_n_dldl); return TRUE; } boolean embedg_VES_are_adj_lists_consistent (t_ver_edge *embed_graph, int n) /* checks that the adjacency list of each vertex is consistent in the manner of embedg_VES_is_adj_list_consistent */ { int i; /* it is enough to visit the vertices and virtual vertices only (I don't think it is enough to do the vertices only --??) */ for (i = 0; i < 2*n; i++) if (!embedg_VES_is_adj_list_consistent(embed_graph, n, i)) return FALSE; return TRUE; } void embedg_VES_remove_edge (t_ver_edge *embed_graph, int n, int e) /* remove edge e from the embedding */ { int r1, r2, r1out, r2in, twin; ASSERT(embedg_VES_is_edge(n, e)); IF_DEB_SCE( fprintf(stdout, "removing an SCE, enter\n"); embedg_VES_print_edge(embed_graph, n, e); ) r1 = embed_graph[e].link[0]; r2 = embed_graph[e].link[1]; /* disable e and link r1 and r2 together: we had r1 -> e -> r2 */ embed_graph[e].link[0] = embed_graph[e].link[1] = e; r1out = embed_graph[r1].link[0] == e ? 0 : 1; r2in = embed_graph[r2].link[0] == e ? 0 : 1; if (r1 == r2) /* this I think should never happen, but one never knows... */ { embed_graph[r1].link[0] = embed_graph[r1].link[1] = r1; } else { embed_graph[r1].link[r1out] = r2; embed_graph[r2].link[r2in] = r1; } ASSERT(embedg_VES_is_adj_list_consistent(embed_graph, n, r1)); /* now we must do a similar thing for the twin (which must get reomved as well) */ twin = embedg_VES_get_twin_edge(embed_graph, n, e); IF_DEB_SCE( fprintf(stdout, "removing an SCE, the twin\n"); embedg_VES_print_edge(embed_graph, n, twin); ) r1 = embed_graph[twin].link[0]; r2 = embed_graph[twin].link[1]; embed_graph[twin].link[0] = embed_graph[twin].link[1] = twin; r1out = embed_graph[r1].link[0] == twin ? 0 : 1; r2in = embed_graph[r2].link[0] == twin ? 0 : 1; if (r1 == r2) { embed_graph[r1].link[0] = embed_graph[r1].link[1] = r1; } else { embed_graph[r1].link[r1out] = r2; embed_graph[r2].link[r2in] = r1; } ASSERT(embedg_VES_is_adj_list_consistent(embed_graph, n, r1)); } void embedg_VES_set_orientation (t_ver_edge *embed_graph, int n, int *ver_orient) /* using the vertices' orientation as given in ver_orient we set the orientation for each edge in the adjacency list for each vertex to do this we use the field sign which is NOT needed anymore by the tester since by the time we call this function we would have finished with that bit (the tester) sign is only set when merging bicomps - even though we'll perform another walkdown when recovering an obstruction (if any) no bicomp merging will occur, so we are safe */ { int v; for (v = 0; v < n; v++) { int o, e; o = ver_orient[v]; embed_graph[v].sign = o; e = embed_graph[v].link[0]; while (e != v) /* just as a note: note the way I get the next in the list here (as opposed to using embedg_VES_get_next_in_dlcl): this is because I implicitely assume that the adjacency lists are consistent Also note that edges can be SCE, it doesn't really matter anyway (they may not have been removed yet -- see the way we recover the obstruction: embedg_mark_obstruction) */ { embed_graph[e].sign = o; e = embed_graph[e].link[0]; } } } /* * dlcl_misc.c */ /* What: ***** Implementing: Housekeeping for a simple doubly linked circular list: this is a data structure ONLY used WITHIN the planarity tester and obstruction isolator and is not to be confused with the VES structure mentionned elsewhere. The VES structure is an array, while the dlcl one is a list of pointers. The dlcl is especially useful as it allows for the storage of an ordered list. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ /* aproto: beginstatic -- don't touch this!! */ static void embedg_dlcl_rec_free (t_dlcl *); static void embedg_dlcl_rec_insert_right (t_dlcl *, t_dlcl *); static void embedg_dlcl_rec_insert_left (t_dlcl *, t_dlcl *); static void embedg_dlcl_rec_retrieve (t_dlcl *); static void embedg_dlcl_rec_delete (t_dlcl *); static boolean embedg_dlcl_is_singleton (t_dlcl *); /* aproto: endstatic -- don't touch this!! */ #ifndef PLANAR_IN_MAGMA #endif t_dlcl * embedg_dlcl_rec_new (int info) /* create a new record with info in the global array to insert in the list */ { t_dlcl *r; r = (t_dlcl *) mem_malloc(sizeof(t_dlcl)); r->info = info; r->in_adjl = r->twin_in_adjl = NIL; r->mult = 1; r->right = r; r->left = r; return r; } static void embedg_dlcl_rec_free (t_dlcl *r) /* free */ { mem_free(r); } void embedg_dlcl_rec_print (t_dlcl *r) { fprintf(stdout,"%d ", r->info); } void embedg_dlcl_print (t_dlcl *l) { t_dlcl *p = l; if (!embedg_dlcl_is_empty(p)) { embedg_dlcl_rec_print(p); p = embedg_dlcl_list_next(p); while (p != l) { embedg_dlcl_rec_print(p); p = embedg_dlcl_list_next(p); } } fprintf(stdout,"\n"); } static void embedg_dlcl_rec_insert_right (t_dlcl *l, t_dlcl *r) { t_dlcl *tmp_r, *tmp_l; tmp_r = l->right; tmp_l = tmp_r->left; l->right = r; r->right = tmp_r; r->left = tmp_l; tmp_r->left = r; } static void embedg_dlcl_rec_insert_left (t_dlcl *l, t_dlcl *r) { t_dlcl *tmp_r, *tmp_l; tmp_l = l->left; tmp_r = tmp_l->right; l->left = r; r->left = tmp_l; r->right = tmp_r; tmp_l->right = r; } t_dlcl * embedg_dlcl_rec_append (t_dlcl *l, t_dlcl *r) { if (embedg_dlcl_is_empty(l)) return r; embedg_dlcl_rec_insert_left(l, r); return l; } t_dlcl * embedg_dlcl_rec_prepend (t_dlcl *l, t_dlcl *r) { if (embedg_dlcl_is_empty(l)) return r; embedg_dlcl_rec_insert_left(l, r); return r; } t_dlcl * embedg_dlcl_cat (t_dlcl *l, t_dlcl *m) /* concatenate m to the RIGHT of the end of l WITHOUT copying m */ { t_dlcl *h1, *h2, *e1, *e2; if (embedg_dlcl_is_empty(l)) return m; if (embedg_dlcl_is_empty(m)) return l; h1 = l; e1 = l->left; h2 = m; e2 = m->left; e1->right = h2; h2->left = e1; e2->right = h1; h1->left = e2; return l; } t_dlcl * embedg_dlcl_find (t_dlcl *l, int info) { t_dlcl *p = l; if (!embedg_dlcl_is_empty(p)) { if (p->info == info) { return p; } p = embedg_dlcl_list_next(p); while (p != l) { if (p->info == info) { return p; } p = embedg_dlcl_list_next(p); } } return NP; } t_dlcl * embedg_dlcl_find_with_NIL_twin_in_adjl (t_dlcl *l, int info) { t_dlcl *p = l; if (!embedg_dlcl_is_empty(p)) { if (p->info == info && p->twin_in_adjl == NIL) { return p; } p = embedg_dlcl_list_next(p); while (p != l) { if (p->info == info && p->twin_in_adjl == NIL) { return p; } p = embedg_dlcl_list_next(p); } } return NP; } static void embedg_dlcl_rec_retrieve (t_dlcl *r) { t_dlcl *right, *left; right = r->right; left = r->left; left->right = right; right->left = left; r->right = r; r->left = r; } static void embedg_dlcl_rec_delete (t_dlcl *r) { embedg_dlcl_rec_retrieve(r); embedg_dlcl_rec_free(r); } t_dlcl * embedg_dlcl_delete_first (t_dlcl *l) /* prune the list from the head: - set new head to right of old head - delete old head */ { t_dlcl *new_head; ASSERT(!embedg_dlcl_is_empty(l)); if (embedg_dlcl_is_singleton(l)) { new_head = NP; } else { new_head = l->right; } embedg_dlcl_rec_delete(l); return new_head; } t_dlcl * embedg_dlcl_delete_rec (t_dlcl *l, t_dlcl *r) /* delete r from l; if r == l, set new head to right of old head */ { t_dlcl *new_head; if (r == l) { return embedg_dlcl_delete_first(l); } embedg_dlcl_rec_delete(r); return l; } boolean embedg_dlcl_is_empty (t_dlcl *l) { return (l == NP) ? TRUE : FALSE; } static boolean embedg_dlcl_is_singleton (t_dlcl *l) { return (l->right == l) ? TRUE : FALSE; /* same as l->left == l */ } t_dlcl * embedg_dlcl_list_next (t_dlcl *l) /* this assumes no choice in the direction of the walking (always to the right) -- good enough when deleting for example or when the direction of the walking does not matter */ { return l->right; } t_dlcl * embedg_dlcl_list_prev (t_dlcl *l) /* this assumes no choice in the direction of the walking (always to the right) */ { return l->left; } t_dlcl * embedg_dlcl_list_last (t_dlcl *l) { return embedg_dlcl_list_prev(l); } void embedg_dlcl_delete (t_dlcl *l) { if (!embedg_dlcl_is_empty(l)) { while (!embedg_dlcl_is_singleton(l)) { t_dlcl *next; next = embedg_dlcl_list_next(l); embedg_dlcl_rec_delete(next); } embedg_dlcl_rec_delete(l); } } t_dlcl * embedg_dlcl_copy (t_dlcl *l) { t_dlcl *p, *c; if (embedg_dlcl_is_empty(l)) return NP; c = embedg_dlcl_rec_new(l->info); p = embedg_dlcl_list_next(l); while (p != l) { t_dlcl *temp; temp = embedg_dlcl_rec_new(p->info); temp->in_adjl = p->in_adjl; temp->twin_in_adjl = p->twin_in_adjl; temp->mult = p->mult; c = embedg_dlcl_rec_append(c, temp); p = embedg_dlcl_list_next(p); } return c; } int embedg_dlcl_length (t_dlcl *l) { t_dlcl *p; int n; if (embedg_dlcl_is_empty(l)) return 0; p = embedg_dlcl_list_next(l); n = 1; while (p != l) { n++; p = embedg_dlcl_list_next(p); } return n; } /* * planar_by_edge_addition.c */ /* What: ***** Implementing: The top level for the planarity tester. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} #define IF_DEB_TREE(x) {} #define IF_DEB_EDGES(x) {} #define IF_CPU(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif boolean sparseg_adjl_is_planar ( t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, /* input sparse graph */ int *nbr_c, /* size of the graph, #components */ t_dlcl ***dfs_tree, /* a sparse graph rep. for the dfs tree -- vertices are as DFIs -- and children are ordered wrt lowpoint value */ t_dlcl ***back_edges, /* for each vertex v, a dlcl of the back edges [v, x] incident to v where x is a DESCENDANT of v (vertices are given as DFIs) */ t_dlcl ***mult_edges, /* for each vertex v, a dlcl of the back edges [v, x] incident to v where x is a DESCENDANT of v (vertices are given as DFIs) */ t_ver_edge **embed_graph, /* output graph embedding -- more on that later */ int *edge_pos, /* pos. in embed_graph for addition of the next edge */ int *vr, int *wr /* if graph is non planar, return the unembedded edge (where wr descendant of vr) */ ) /* as the name indicates: is the graph planar? */ { int v; IF_CPU( float sttime; float time_to_now; ) *embed_graph = embedg_planar_alg_init(V, n, A, nbr_c, edge_pos, dfs_tree, back_edges, mult_edges); IF_CPU( sttime = time_current_user(); ) for (v = n - 1; v >= 0; v--) /* visit all vertices in descending DFI order */ { t_dlcl *be_l, *te_l, *p; IF_DEB( fprintf(stdout, "top level, vertex %d\n", v); ) /* find all the back edges [w, v] where w is a descendant of v and perform a walkup from w to v (ie determine which bicomps are pertinent) */ be_l = (*back_edges)[v]; p = be_l; if (!embedg_dlcl_is_empty(p)) { int w; w = p->info; IF_DEB( fprintf(stdout, "top level, before walkup for w %d\n", w); ) embedg_walkup(*embed_graph, n, v, p); p = embedg_dlcl_list_next(p); while (p != be_l) { w = p->info; IF_DEB( fprintf(stdout, "top level, before walkup for w %d\n", w); ) embedg_walkup(*embed_graph, n, v, p); p = embedg_dlcl_list_next(p); } } /* perform a walkdown for each tree edge [v, c], c a descendant of v (ie attempt to embed all back edges on the pertinent bicomps) */ te_l = (*dfs_tree)[v]; p = te_l; if (!embedg_dlcl_is_empty(p)) { int c, vv; t_merge_queue q; c = p->info; vv = c + n; IF_DEB( fprintf(stdout, "top level, before walkdown for c %d\n", c); ) q = embedg_walkdown(*embed_graph, n, edge_pos, vv); IF_DEB( fprintf(stdout, "top level, after walkdown for c %d, state of edges'sign\n", c); embedg_VES_print_flipped_edges(*embed_graph, n, *edge_pos); ) /* temp only */ embedg_merge_queue_delete(q); p = embedg_dlcl_list_next(p); while (p != te_l) { c = p->info; vv = c + n; IF_DEB( fprintf(stdout, "top level, before walkdown for c %d\n", c); ) q = embedg_walkdown(*embed_graph, n, edge_pos, vv); IF_DEB( fprintf(stdout, "top level, after walkdown for c %d, state of edges'sign\n", c); embedg_VES_print_flipped_edges(*embed_graph, n, *edge_pos); ) /* temp only */ embedg_merge_queue_delete(q); p = embedg_dlcl_list_next(p); } } /* check that each back edge [w, v], w a descendant of v, has been embedded */ be_l = (*back_edges)[v]; p = be_l; if (!embedg_dlcl_is_empty(p)) { int w; w = p->info; IF_DEB( fprintf(stdout, "top level, before checking embedding for w %d\n", w); ) if ((*embed_graph)[w].adjacent_to == v) /* this edge hasn't been embedded: the graph is non-planar */ { /* before returning we really want to ensure that the vertices' adjacency lists are consistent */ ASSERT(embedg_VES_are_adj_lists_consistent( *embed_graph, n)); IF_CPU( fprintf(stdout, "CPU for tester only %f\n", (time_current_user() - sttime)); ) *vr = v; *wr = w; return FALSE; } p = embedg_dlcl_list_next(p); while (p != be_l) { w = p->info; IF_DEB( fprintf(stdout, "top level, before checking embedding for w %d\n", w); ) if ((*embed_graph)[w].adjacent_to == v) { /* before returning we really want to ensure that the vertices' adjacency lists are consistent */ ASSERT(embedg_VES_are_adj_lists_consistent( *embed_graph, n)); IF_CPU( fprintf(stdout, "CPU for tester only %f\n", (time_current_user() - sttime)); ) *vr = v; *wr = w; return FALSE; } p = embedg_dlcl_list_next(p); } } } IF_DEB_EDGES( fprintf(stdout, "top level, total number of edges in embedding %d\n", *edge_pos - 2 * n + 1); ) /* before returning we really want to ensure that the vertices' adjacency lists are consistent */ ASSERT(embedg_VES_are_adj_lists_consistent(*embed_graph, n)); IF_CPU( fprintf(stdout, "CPU for tester only %f\n", (time_current_user() - sttime)); ) return TRUE; } /* * walkup.c */ /* What: ***** Implementing: The walkup routine within the VES structure: Walking up from w where [w, v^c] is a (directed) back edge to be embeeding later. Along the way collect all the pertinent bicomps that will need to be merged before embedding the back edges to v^c. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif void embedg_walkup (t_ver_edge *embed_graph, int n, int v, t_dlcl *p) /* walkup from w = p->info to v: [w, v] is a back edge where w is a DFS descendant of v */ { int w, x, xin, y, yin; w = p->info; IF_DEB( fprintf(stdout, "walkup from %d to %d, enter\n", w, v); ) embed_graph[w].adjacent_to = v; /* dirty trick to record some information about the BE [w, v] which will be useful at the time of creation and insertion of this BE: this happens in the walkdown procedure note that what I am doing here is safe: [w].in_adjl, [w].twin_in_adjl, [w].mult had no use so far since w is a vertex (and not an edge...) */ embed_graph[w].in_adjl = p->in_adjl; embed_graph[w].twin_in_adjl = p->twin_in_adjl; embed_graph[w].mult = p->mult; /* set up the traversal contexts for w: one in each direction */ x = w; xin = 1; y = w; yin = 0; while (x != v) { int vz, z, c; IF_DEB( fprintf(stdout, "walkup, x %d and y %d\n", x, y); ) if (embed_graph[x].visited == v || embed_graph[y].visited == v) { IF_DEB( if (embed_graph[x].visited == v) fprintf(stdout, "walkup, x visited\n"); else fprintf(stdout, "walkup, y visited\n"); ) break; } /* set x and y as visited! */ embed_graph[x].visited = embed_graph[y].visited = v; vz = embedg_VES_is_virtual_vertex(n, x) ? x : NIL; vz = embedg_VES_is_virtual_vertex(n, y) ? y : vz; if (vz != NIL) /* that is, x (or y) is a virtual vertex -- in other words, we are set to find the root of the bicomp containing w, or of the bicomp r^c such that w is in the tree rooted by c consequently, by definition, vz is PERTINENT */ { c = vz - n; z = embed_graph[c].DFS_parent; IF_DEB( fprintf(stdout, "walkup, vz is virtual, %d^%d\n", z, c); ) if (z != v) /* determine if vz externally or internally active */ { if (embed_graph[c].lowpoint < v) /* vz is externally active: APPEND to the list of pertinent bicomps */ { IF_DEB( fprintf(stdout, "walkup, vz is ext. active\n"); ) embed_graph[z].pertinent_bicomp_list = embedg_dlcl_rec_append( embed_graph[z].pertinent_bicomp_list, embedg_dlcl_rec_new(vz)); } else /* vz is internally active: PREPEND to the list of pertinent bicomps */ { IF_DEB( fprintf(stdout, "walkup, vz is pertinent\n"); ) embed_graph[z].pertinent_bicomp_list = embedg_dlcl_rec_prepend( embed_graph[z].pertinent_bicomp_list, embedg_dlcl_rec_new(vz)); } } /* continue the walkup, look if there are any other pertinent bicomps -- here "jump" to the next bicomp "up" */ x = z; xin = 1; y = z; yin = 0; } else /* continue the traversal of the bicomp until one finds its (virtual) root */ { embedg_VES_get_succ_on_ext_face(embed_graph, n, x, xin, FALSE, 0, &x, &xin); embedg_VES_get_succ_on_ext_face(embed_graph, n, y, yin, FALSE, 0, &y, &yin); } } } /* * walkdown.c */ /* What: ***** Implementing: The walkdown routine within the VES structure: walking down a bicomp rooted by a virtual vertex v^c and attempting to embed the back edges. This cannot be done if the walk has to stop due to the presence of externally active vertices on both the clockwise and the anticlockwise side of the bicomp. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_EMBED(x) {} #define IF_DEB_BE(x) {} #define IF_DEB_SCE(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif t_merge_queue embedg_walkdown (t_ver_edge *embed_graph, int n, int *edge_pos, int vv) /* walkdown from the virtual vertex: embed any back edges incident to vv if any and merge the encountered bicomps while walking down (very informative isn't it? :)) ... and return the merge queue: will be useful when isolating the Kuratowski subgraphs */ { t_merge_queue q; int v, c, vvout; ASSERT(embedg_VES_is_virtual_vertex(n, vv)); /* find v and c such that v^c = vv */ c = vv - n; v = embed_graph[c].DFS_parent; IF_DEB( fprintf(stdout, "walkdown from %d^%d, enter\n", v, c); ) IF_DEB_EMBED( fprintf(stdout, "walkdown, embedding at start\n"); embedg_VES_print_bigcomps(embed_graph, n); ) /* create an empty merge queue */ q = embedg_merge_queue_new(n); for (vvout = 0; vvout <= 1; vvout++) /* chose a direction for the walk, but walk in both directions unless a stopping vertex is encountered and other conditions are satisfied (see below) */ { int w, win; embedg_VES_get_succ_on_ext_face(embed_graph, n, vv, vvout ^ 1, FALSE, 0, &w, &win); IF_DEB( fprintf(stdout, "walkdown, successor (outside while loop) from %d^%d:%d is %d:%d\n", embed_graph[vv-n].DFS_parent, vv-n, vvout ^ 1, w, win); ) while (w != vv) /* is there no danger we walk the whole way back to vv and that all the vertices along the walk are inactive? answer: no, because of the short-cut edges. Short-cut edges are precisely inserted to remove the inactive vertices from the external face (ie they are "pushed" to the internal face of the bicomp) */ { if (embed_graph[w].adjacent_to == v) /* ie there is a (directed) back edge [w, v] (would have been set in the previous walkup routine): embed this edge, but before that, merge all the bicomps previouslsy collected */ { IF_DEB( fprintf(stdout, "walkdown, embed BE (%d^%d:%d, %d:%d)\n", embed_graph[vv-n].DFS_parent, vv - n, vvout, w, win); fprintf(stdout, "walkdown, queue before pulling elts\n"); embedg_merge_queue_print(q); ) while (!embedg_merge_queue_empty(q)) { int u, uin, vu, vuout; embedg_merge_queue_get(&q, &u, &uin, &vu, &vuout); IF_DEB( fprintf(stdout, "walkdown, pull from queue (%d:%d, %d^%d:%d)\n", u, uin, embed_graph[vu-n].DFS_parent, vu-n, vuout); ) embedg_VES_merge_pertinent_bicomps( embed_graph, n, vu, vuout, u, uin); } IF_DEB_BE( fprintf(stdout, "walkdown, before embed BE [%d^%d:%d, %d:%d]\n", embed_graph[vv-n].DFS_parent, vv - n, vvout, w, win); embedg_VES_print_adj_list( embed_graph, n, vv, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list( embed_graph, n, vv, FALSE); ) embedg_VES_embed_edge(embed_graph, n, edge_pos, BE, vv, vvout, w, win); IF_DEB_BE( fprintf(stdout, "walkdown, after embed BE [%d^%d:%d, %d:%d]\n", embed_graph[vv-n].DFS_parent, vv - n, vvout, w, win); embedg_VES_print_adj_list( embed_graph, n, vv, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list( embed_graph, n, vv, FALSE); ) IF_DEB_EMBED( fprintf(stdout, "walkdown, embedding after bicomp merge & back edge embedding\n"); embedg_VES_print_bigcomps(embed_graph, n); ) /* clear the adjacent_to flag */ embed_graph[w].adjacent_to = n; /* "invalid" value */ } if (!embedg_dlcl_is_empty(embed_graph[w].pertinent_bicomp_list)) /* each pertinent child bicomp of w (pertinent: contains active (ie more back edges to embed) elts) must be traversed and pushed onto the queue for later bicomp merging */ { int vw, vwout, x, xin, y, yin, s, sin; IF_DEB( fprintf(stdout, "walkdown, pertinent list for %d\n", w); embedg_dlcl_print(embed_graph[w].pertinent_bicomp_list); ) /* get the first child in the pertinent list (see how the list is built in embedg_walkup) the child will eventually be removed from that list when merging the bicomps, and surely this bicomp (rooted at vw) will be merged (later) because it is active and hence pushed on the merge queue */ /* we can start by pushing the vertex (w, win) on the merge queue */ embedg_merge_queue_append_vertex(&q, embed_graph, n, w, win); IF_DEB( fprintf(stdout, "walkdown, push 1rst 2-tuple on queue\n"); embedg_merge_queue_print(q); ) /* get the first child in the pertinent list */ vw = (embed_graph[w].pertinent_bicomp_list)->info; IF_DEB( fprintf(stdout, "walkdown, get pertinent %d^%d\n", embed_graph[vw - n].DFS_parent, vw - n); ) /* start two walks starting at vw */ embedg_VES_get_succ_active_on_ext_face(embed_graph, n, v , vw, 1, FALSE, 0, &x, &xin); embedg_VES_get_succ_active_on_ext_face(embed_graph, n, v, vw, 0, FALSE, 0, &y, &yin); /* because of the trick of inserting short-cut edges at previous stages, neighbours of vw are guaranteed to be active (however I'll use the more general embedg_VES_get_succ_active_on_ext_face instead of the restrictive embedg_VES_get_succ_on_ext_face because the walkdown may be used later to isolate Kuratowski minors, in a situation where SCEs could have been removed and thus where the successor on the external face will no longer be guaranteed to be active) (* actually I have decided to remove the SCE at the very last moment hence the above pb does not occur in the present implementation) it only remains to chose the next vertex where from to continue the walk; the choice is made in that order: - an internally active vertex (incident to v via a backedge but whose lowpoint is NO less than v) - a (externally active) pertinent vertex (incident to v via a backedge but whose lowpoint is less than v: ie which is also externally active) - as a last resort, a non-pertinent externally vertex, which is then a stopping vertex */ IF_DEB( fprintf(stdout, "walkdown, x and y: %d, %d\n", x, y); ) if (embedg_VES_is_ver_int_active(embed_graph, n, v, x)) /* x is internally active */ { IF_DEB( fprintf(stdout, "walkdown, x is int. active\n"); ) s = x; sin = xin; } else if (embedg_VES_is_ver_int_active( embed_graph, n, v, y)) /* y is internally active */ { IF_DEB( fprintf(stdout, "walkdown, y is int. active\n"); ) s = y; sin = yin; } else if (embedg_VES_is_ver_pertinent( embed_graph, n, v, x)) /* x is pertinent */ { IF_DEB( fprintf(stdout, "walkdown, x is pertinent\n"); ) s = x; sin = xin; } else /* tough luck: y may be externally active */ { IF_DEB( fprintf(stdout, "walkdown, tough luck\n"); ) s = y; sin = yin; } IF_DEB( fprintf(stdout, "walkdown, succ. on pertinent bicomp is %d:%d\n", s, sin); ) /* set vwout to respect consistency of traversal */ vwout = s == x ? 0 : 1; /* now that we know vwout we can push (vw, vwout) on the merge queue, thus completing the 4-tuple (w, win, vw, vwout) describing a bicomp merge to occur at a later stage */ embedg_merge_queue_append_virtual_vertex(&q, embed_graph, n, vw, vwout); IF_DEB( fprintf(stdout, "walkdown, push on queue (%d:%d, %d^%d:%d)\n", w, win, embed_graph[vw-n].DFS_parent, vw - n, vwout); embedg_merge_queue_print(q); ) /* we continue the walk */ w = s; win = sin; } /* at this point, w is either inactive or externally active (w can't be pertinent: its pertinent bicomp list is empty, and the back edge [w, v], if any, has already been embedded) */ else if (embedg_VES_is_ver_inactive(embed_graph, n, v, w)) /* w is inactive: continue with the walk on the external face and, insert a short cut edge so that w is removed from the external face */ { int s, sin; IF_DEB( fprintf(stdout, "walkdown, %d has no pertinent bicomps and is inactive\n", w); ) embedg_VES_get_succ_on_ext_face(embed_graph, n, w, win, FALSE, 0, &s, &sin); IF_DEB( fprintf(stdout, "walkdown, successor from %d:%d is %d:%d\n", w, win, s, sin); ) /* s is the successor of w: we embed a short circuit edge [vv, s] if - the bicomp is externally active (to ensure that at a later stage this new face gets bisected: so that we don't end up with a face of degree 2 (parallel edges)) - if [s, vv] is not a back edge CONSEQUENTLY, adding SCE edges + does not destroy the planarity of the graph + ensures that each face has degree > 2 so that |E| <= 3 * |V| - 6 remains valid at all times + that the space allocated to the edges in embed_graph (via MAXDE(n)) is sufficient NOTE: the above still allows to embed a short-cut edge as an edge parallel to a tree edge OR a back edge (which then has been embedded previously so that [w].adjacent has been cleared) but again, since the degree of the face will be > 2, that's ok recall that c = vv - n */ if (embed_graph[c].lowpoint < v /* bicomp rooted at vv is externally active */ && embed_graph[s].adjacent_to != v) /* [s, vv] is not a back edge */ { IF_DEB_SCE( fprintf(stdout, "walkdown, before embed SCE [%d^%d:%d, %d:%d]\n", embed_graph[vv-n].DFS_parent, vv - n, vvout, s, sin); embedg_VES_print_adj_list( embed_graph, n, vv, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list( embed_graph, n, vv, FALSE); ) embedg_VES_embed_edge(embed_graph, n, edge_pos, SCE, vv, vvout, s, sin); /* note also that the addition of short cut edges does not change the fact that the graph is planar (when it is, so we never run into the problem of creating/adding too many edges to embed-graph) */ IF_DEB_SCE( fprintf(stdout, "walkdown, after embed SCE [%d^%d:%d, %d:%d]\n", embed_graph[vv-n].DFS_parent, vv - n, vvout, s, sin); embedg_VES_print_adj_list( embed_graph, n, vv, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list( embed_graph, n, vv, FALSE); ) IF_DEB( fprintf(stdout, "walkdown, embed SCE [%d^%d:%d, %d:%d]\n", embed_graph[vv-n].DFS_parent, vv - n, vvout, s, sin); ) } /* continue the walk */ w = s; win = sin; } else /* w is non-pertinent and externally active: it is a stopping vertex: we stop here and see if we can walk in the other direction */ { IF_DEB( fprintf(stdout, "walkdown, %d is externally active\n", w); ) break; } } if (!embedg_merge_queue_empty(q)) /* mumm.... don't understand this one... let's see: the queue constains pertinent bicomps collected during one of the traversal of the external face, so that once a stopping vertex has been encountered and the queue is not empty, this means that we will be unable to embed any remaining back edges: it is important to remember that when w is a stopping vertex there is no choice left, since we walk the pertinent bicomp in both directions at once, and always choose the "best" possible vertex (see the choice strategy: (a) internally active, (b) pertinent, (c) the rest) */ { IF_DEB( fprintf(stdout, "walkdown, merge queue is not empty\n"); ) break; } } /* and return the merge queue */ return q; } /* * merge_queue_misc.c */ /* What: ***** Implementing: The merge queue stores the pertinent bicomps waiting to be merged before a subsequent back edge embedding. See walkdown.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif t_merge_queue embedg_merge_queue_new (int n) /* create a merge queue of 4 * (n-1) elts: we can only have at most n-1 virtual vertices, and for each of those we need to store 4 bits of info */ { t_merge_queue q; q.start = q.end = 0; q.b = (int *) mem_malloc(sizeof(int) * 4 * (n - 1)); return q; } void embedg_merge_queue_delete (t_merge_queue q) { mem_free(q.b); } boolean embedg_merge_queue_empty (t_merge_queue q) { return q.start == q.end ? TRUE : FALSE; } void embedg_merge_queue_print (t_merge_queue q) { int i; for (i = q.start; i < q.end; i++) { fprintf(stdout, "%d:%d ", q.b[i++], q.b[i]); } fprintf(stdout, "\n"); } void embedg_merge_queue_append (t_merge_queue *q, t_ver_edge *embed_graph, int n, int v, int vin, int vv, int vvout) /* append the 4-tuple (v, vin, vv, vvout) where v is a vertex and vv is its virtual counterpart we don't do much here, most of the work is done when pulling a bicomp/4-tuple from the queue */ { /* is this really necessary? - YES!!! */ ASSERT((*q).end < 4 * (n - 2)); ASSERT(embedg_VES_is_vertex(n, v)); ASSERT(embedg_VES_is_virtual_vertex(n, vv)); ASSERT(embed_graph[vv - n].DFS_parent == v); (*q).b[(*q).end++] = v; (*q).b[(*q).end++] = vin; (*q).b[(*q).end++] = vv; (*q).b[(*q).end++] = vvout; } void embedg_merge_queue_append_vertex (t_merge_queue *q, t_ver_edge *embed_graph, int n, int v, int vin) /* same as above but were we only append the 2-tuple (v, vin), appending the 2-tuple (vv, vvout) at a later stage (see embedg_merge_queue_append_virtual_vertex) */ { ASSERT((*q).end < 4 * (n - 2)); ASSERT(embedg_VES_is_vertex(n, v)); (*q).b[(*q).end++] = v; (*q).b[(*q).end++] = vin; IF_DEB( fprintf(stdout, "merge_queue_append_vertex, after, end is %d\n", (*q).end); ) } void embedg_merge_queue_append_virtual_vertex (t_merge_queue *q, t_ver_edge *embed_graph, int n, int vv, int vvout) /* counterpart to embedg_merge_queue_append_vertex: here we append the 2-tuple (vv, vvout), vv = v^c, where the 2-tuple (v, vin) is already in the queue (see embedg_merge_queue_append_vertex) */ { ASSERT(!embedg_merge_queue_empty(*q)); ASSERT(embedg_VES_is_virtual_vertex(n, vv)); ASSERT(embed_graph[vv - n].DFS_parent == (*q).b[(*q).end - 2]); (*q).b[(*q).end++] = vv; (*q).b[(*q).end++] = vvout; IF_DEB( fprintf(stdout, "merge_queue_append_virtual_vertex, after, end is %d\n", (*q).end); ) } void embedg_merge_queue_get (t_merge_queue *q, int *v, int *vin, int *vv, int *vvout) /* pulling out a 4-tuple from the beginning of the FIFO queue */ { ASSERT(!embedg_merge_queue_empty((*q))); *v = (*q).b[(*q).start++]; *vin = (*q).b[(*q).start++]; *vv = (*q).b[(*q).start++]; *vvout = (*q).b[(*q).start++]; } void embedg_merge_queue_prune (t_merge_queue *q, int *v, int *vin, int *vv, int *vvout) /* pulling out a 4-tuple from the end of the FIFO queue */ { ASSERT(!embedg_merge_queue_empty((*q))); *vvout = (*q).b[--((*q).end)]; *vv = (*q).b[--((*q).end)]; *vin = (*q).b[--((*q).end)]; *v = (*q).b[--((*q).end)]; } /* * vertex_activity.c */ /* What: ***** Implementing: Determining a vertex's activity. This takes place within the VES structure. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif boolean embedg_VES_is_ver_pertinent (t_ver_edge *embed_graph, int n, int v, int w) /* is w pertinent (wrt v) - the field adjacent_to = v: means there is a back edge [w, v] - or w has a non empty pertinent_bicomp_list */ { boolean ans; ans = embed_graph[w].adjacent_to == v ? TRUE : FALSE; if (ans) return TRUE; else return embedg_dlcl_is_empty(embed_graph[w].pertinent_bicomp_list) ? FALSE : TRUE; } boolean embedg_VES_is_ver_ext_active (t_ver_edge *embed_graph, int n, int v, int w) /* is w externally active (wrt v) this is the case when either w's least_ancestor < v or the first member of w's separated_DFS_child_list has lowpoint < v (the vertices in separated_DFS_child_list are ordered by lowpoint) why? because w's separated_DFS_child_list may be empty (due to prior bicomp merging say) and so its children are in effect inactive */ { boolean ans; ans = embed_graph[w].least_ancestor < v ? TRUE : FALSE; if (ans) return TRUE; else { if (embedg_dlcl_is_empty(embed_graph[w].separated_DFS_child_list)) { return FALSE; } else { int c; c = (embed_graph[w].separated_DFS_child_list)->info; return embed_graph[c].lowpoint < v ? TRUE : FALSE; } } } boolean embedg_VES_is_ver_int_active (t_ver_edge *embed_graph, int n, int v, int w) /* is w internally active (wrt v): this happens when w is pertinent but NOT externally active */ { return embedg_VES_is_ver_pertinent(embed_graph, n, v, w) && !embedg_VES_is_ver_ext_active(embed_graph, n, v, w); } boolean embedg_VES_is_ver_inactive (t_ver_edge *embed_graph, int n, int v, int w) /* is w inactive (wrt v), that is w nor pertinent nor externally activ */ { return !embedg_VES_is_ver_pertinent(embed_graph, n, v, w) && !embedg_VES_is_ver_ext_active(embed_graph, n, v, w); } /* * merge_bicomps.c */ /* What: ***** Implementing: In the VES structure, merging two bicomponents. That is, merging the virtual vertex v^c with the actual vertex v while merging their respective adjacency lists. This must be done in a very specific manner so as to able to determine the subsequent internal/external faces. Also, great care must be taken so that the resulting adj. list for v is consistent (wrt to the direction of traversal). ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_ADJL(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ void embedg_VES_merge_simple_bicomps (t_ver_edge *embed_graph, int n, int vv, int vvout, int v, int vin) /* merge the bicomp rooted at vv (vv a virtual vertex) with its counterpart v so that the resulting adjacency list for v is consistent and is the union of the adjacency lists for vv and v we treat the case that the bicomp may be flipped (vvout == vin) here */ { int c, edge, twin, root_edge, cur, prev; int vout, vvin, e1, e2, e3, e4, e1out, e3out, e4in; /* find c such that [v^c, c] is the root edge of the bicomp rooted at vv = v^c */ c = vv - n; ASSERT(embed_graph[c].DFS_parent == v); IF_DEB( fprintf(stdout, "merge_simple_bicomp, start: merge\n"); embedg_VES_print_virtual_vertex(embed_graph, n, vv); fprintf(stdout, ":%d & ", vvout); embedg_VES_print_vertex(n, v); fprintf(stdout, ":%d\n", vin); ) IF_DEB_ADJL( fprintf(stdout, "merge_simple_bicomp, adj. list for %d (before)\n", vv); embedg_VES_print_adj_list(embed_graph, n, vv, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list(embed_graph, n, vv, FALSE); fprintf(stdout, "\n"); fprintf(stdout, "merge_simple_bicomp, adj. list for %d (before)\n", v); embedg_VES_print_adj_list(embed_graph, n, v, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list(embed_graph, n, v, FALSE); ) /* find all edges incident to vv and (re)set all references to incidence to vv to incidence to v by the same token, find the root_edge [v^c, c] MOREVOVER, when vin == vvout, the bicomp (rooted by v^v = vv) will be flipped: we must invert the links of all the edges incident to vv so that their further union with v's adjacency list results in a consistent adjacency list for v! we do everything in one go */ /* very careful here: a root edge must ALSO be a TE (because the same edge could have been added as a SCE) */ root_edge = NIL; edge = embed_graph[vv].link[vvout]; ASSERT(embedg_VES_is_edge(n, edge)); if (embed_graph[edge].neighbour == c && embedg_VES_is_tree_edge(embed_graph, n, edge)) { root_edge = edge; } if (vin == vvout) /* invert the links */ { int in, out; in = embed_graph[edge].link[0]; out = embed_graph[edge].link[1]; embed_graph[edge].link[0] = out; embed_graph[edge].link[1] = in; } /* get the twin and set the neighbour there to v (was vv originally) */ twin = embedg_VES_get_twin_edge(embed_graph, n, edge); ASSERT(embed_graph[twin].neighbour == vv); embed_graph[twin].neighbour = v; prev = vv; cur = edge; while (edge != vv) { edge = embedg_VES_get_next_in_dlcl(embed_graph, n, cur, prev); if (embedg_VES_is_edge(n, edge)) /* get the twin again (and invert the links if need be) */ { if (embed_graph[edge].neighbour == c && embedg_VES_is_tree_edge(embed_graph, n, edge)) { root_edge = edge; } if (vin == vvout) { int in, out; in = embed_graph[edge].link[0]; out = embed_graph[edge].link[1]; embed_graph[edge].link[0] = out; embed_graph[edge].link[1] = in; } twin = embedg_VES_get_twin_edge(embed_graph, n, edge); ASSERT(embed_graph[twin].neighbour == vv); embed_graph[twin].neighbour = v; prev = cur; cur = edge; } else { ASSERT(edge == vv); /* only one vertex in the whole circular list */ } } ASSERT(root_edge != NIL); /* and now union the adjacency lists of v and vv: let e1 be the edge record used to enter v e2 exit v e3 enter vv e4 exit vv : e1 -> v -> e2 e3 -> vv -> e4 the union of the list is done in such a way that - e1 and e4 are consecutive in v's adjacency list: they are now in the internal face - e3 is now the edge record used to enter v: it is on the external face (along with e2) : e1 -> e4 e3 -> v -> e2 (note that this does not assume that e1 & e2 are distinct or that e3 & e4 are distinct) */ /* I must not forget the case where v is a lone vertex: this is the case where v has no DFS ancestor, ie when v is the root of a tree in the DFS forest */ e1 = embed_graph[v].link[vin]; vout = 1 ^ vin; e2 = embed_graph[v].link[vout]; if (e1 != v) { ASSERT(e2 != v); ASSERT(embedg_VES_is_edge(n, e1)); ASSERT(embedg_VES_is_edge(n, e2)); } e4 = embed_graph[vv].link[vvout]; ASSERT(embedg_VES_is_edge(n, e4)); vvin = 1 ^ vvout; e3 = embed_graph[vv].link[vvin]; ASSERT(embedg_VES_is_edge(n, e3)); /* must take care of the adjacency list's consistency of traversal (will be important only when recovering the embedding) */ if (e1 == e2) { ASSERT(embed_graph[e1].link[0] == embed_graph[e1].link[1]); if (vin == vvout) /* the bicomp will be flipped: must take 1 ^ vvout - difficult to explain -- later... */ { e1out = 1 ^ vvout; } else { e1out = vvout; } } else { e1out = embed_graph[e1].link[0] == v ? 0 : 1; } if (e3 == e4) { ASSERT(embed_graph[e3].link[0] == embed_graph[e3].link[1]); e3out = 1 ^ vin; e4in = vin; } else { e4in = embed_graph[e4].link[0] == vv ? 0 : 1; e3out = embed_graph[e3].link[0] == vv ? 0 : 1; } IF_DEB( fprintf(stdout, "merge_simple_bicomp, before union of lists, e1\n"); embedg_VES_print_edge(embed_graph, n, e1); fprintf(stdout, "merge_simple_bicomp, e3\n"); embedg_VES_print_edge(embed_graph, n, e3); fprintf(stdout, "merge_simple_bicomp, e4\n"); embedg_VES_print_edge(embed_graph, n, e4); ) /* make e1 and e4 consecutive in the adjacency list */ embed_graph[e1].link[e1out] = e4; embed_graph[e4].link[e4in] = e1; embed_graph[e3].link[e3out] = v; embed_graph[v].link[vin] = e3; IF_DEB( fprintf(stdout, "merge_simple_bicomp, after union of lists, e1\n"); embedg_VES_print_edge(embed_graph, n, e1); fprintf(stdout, "merge_simple_bicomp, e3\n"); embedg_VES_print_edge(embed_graph, n, e3); fprintf(stdout, "merge_simple_bicomp, e4\n"); embedg_VES_print_edge(embed_graph, n, e4); ) /* also, want to "disable" vv links, meaning then that vv is no longer a root of a bicomp */ embed_graph[vv].link[0] = embed_graph[vv].link[1] = vv; IF_DEB_ADJL( fprintf(stdout, "merge_simple_bicomp, adj. list for %d (after)\n", vv); embedg_VES_print_adj_list(embed_graph, n, vv, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list(embed_graph, n, vv, FALSE); fprintf(stdout, "\n"); fprintf(stdout, "merge_simple_bicomp, adj. list for %d (after)\n", v); embedg_VES_print_adj_list(embed_graph, n, v, TRUE); fprintf(stdout, "\n"); embedg_VES_print_adj_list(embed_graph, n, v, FALSE); ) ASSERT(embedg_VES_is_adj_list_consistent(embed_graph, n, v)); /* finally, give an orientation to the (formerly) root edge [vv, c] to keep traversal consistent (when recovering embedding) */ if (vin == vvout) /* flip: set the sign of the root edge to clockwise note: a bicomp is merged only once, so there is no need to "flip" the root_edge's sign: it is set once at initialisation and then changed here if need be. */ { embed_graph[root_edge].sign = CLOCKW; IF_VERB( fprintf(stdout, "merge_simple_bicomp, flip for %d, sign is now %d for %d of type %d\n", c, embed_graph[root_edge].sign, root_edge, embed_graph[root_edge].type); embedg_VES_print_edge(embed_graph, n, root_edge); ) } } void embedg_VES_merge_pertinent_bicomps (t_ver_edge *embed_graph, int n, int vv, int vvout, int v, int vin) /* the bicomps to be merged are pertinent: on top (and before) performing a simple merge, there are several things to do related to the merging to pertinent bicomps */ { /* a note of caution: it is (very) likely that after a bicomp merge the resulting bicomp is not biconnected (and hence traversal of the external face of the bicomp via embedg_VES_get_succ_on_ext_face is non-sensical) remembering that a PERTINENT bicomp merge is ALWAYS followed by a back edge embedding we see that the end result is then a bicomp where again traversal of the external face via embedg_VES_get_succ_on_ext_face will make sense */ t_dlcl *pertinent_list, *head, *rep_in_parent_list, *parent_list; int c; /* find c such that [v^c, c] is the root edge of the bicomp rooted at vv = v^c */ c = vv - n; ASSERT(embed_graph[c].DFS_parent == v); /* two things to do first: - remove vv from head of pertinent_bicomp_list of v - remove c from separated_DFS_child_list of v one may ask the point of this since the separated_DFS_child_list seems to mirror pertinent_bicomp_list: but this is not exactly so: + pertinent_bicomp_list is ordered according to the activity of the (virtual) vertices + separated_DFS_child_list is ordered according to the vertices' lowpoint values in effect, it could (almost?*) be said that these two lists are in reverse order (the *almost bit would warrant some thinking here) */ /* remove vv from head of pertinent_bicomp_list of v */ pertinent_list = head = embed_graph[v].pertinent_bicomp_list; ASSERT(!embedg_dlcl_is_empty(pertinent_list)); ASSERT(head->info == vv); IF_DEB( fprintf(stdout, "merge_pertinent_bicomp, start: merge\n"); embedg_VES_print_virtual_vertex(embed_graph, n, vv); fprintf(stdout, ":%d & ", vvout); embedg_VES_print_vertex(n, v); fprintf(stdout, ":%d\n", vin); ) IF_DEB( fprintf(stdout, "merge_pertinent_bicomp, pertinent bicomp_list of %d (before)\n", v); embedg_dlcl_print(embed_graph[v].pertinent_bicomp_list); ) embed_graph[v].pertinent_bicomp_list = embedg_dlcl_delete_first(pertinent_list); IF_DEB( fprintf(stdout, "merge_pertinent_bicomp, pertinent bicomp_list of %d (after)\n", v); embedg_dlcl_print(embed_graph[v].pertinent_bicomp_list); ) /* vv = v^c: remove c from separated_DFS_child_list of v */ rep_in_parent_list = embed_graph[c].rep_in_parent_list; ASSERT(!embedg_dlcl_is_empty(rep_in_parent_list)); parent_list = embed_graph[v].separated_DFS_child_list; ASSERT(!embedg_dlcl_is_empty(parent_list)); embed_graph[v].separated_DFS_child_list = embedg_dlcl_delete_rec(parent_list, rep_in_parent_list); /* that's it, it remains to merge, ie. union the adjacency list, and flipping the bicomp if necessary */ embedg_VES_merge_simple_bicomps(embed_graph, n, vv, vvout, v, vin); } /* * embed_edge.c */ /* What: ***** Implementing: Embedding an edge so that it lies on the external face of a bicomp. We work here with the VES structure. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_EMBED(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ void embedg_VES_embed_edge (t_ver_edge *embed_graph, int n, int *edge_pos, int edge_type, int vv, int vvout, int w, int win) /* embed the edge (vv, w) (vv a virtual vertex, w a vertex) between vv and the edge vvout and the edge win and w so that after the embedding, one exits vv via (vv, w) and enters w via the twin (w, vv) */ { int temp, tempin, tempout; ASSERT(edge_type == BE || edge_type == SCE); ASSERT(embedg_VES_is_virtual_vertex(n, vv)); ASSERT(embedg_VES_is_vertex(n, w)); IF_DEB( fprintf(stdout, "embed_edge, (%d:%d)\n", vv, w); ) /* first, set the edge [vv, w] with the appropriate info when [vv, w] is a back edge there is some more work to do (see the walkup procedure for the extra information we need to copy here */ (*edge_pos)++; ASSERT(*edge_pos < 2*n + 2 * MAXE(n)); embed_graph[*edge_pos].neighbour = w; embed_graph[*edge_pos].type = edge_type; embed_graph[*edge_pos].sign = CCLOCKW; if (edge_type == BE) { ASSERT(embed_graph[w].adjacent_to == embed_graph[vv - n].DFS_parent); /* PLUS: originally when the back edge [w, vv] was created (in the dfs preprocessing stage), it carried in .in_adjl the index of this directed edge in the adjacency list but now, note that we are actually inserting the directed edge [vv, w] in vv's adjacency list, meaning that in_adjl and twin_in_adjl must be exchanged! */ embed_graph[*edge_pos].in_adjl = embed_graph[w].twin_in_adjl; embed_graph[*edge_pos].twin_in_adjl = embed_graph[w].in_adjl; ASSERT(embed_graph[w].mult % 2 == 0); /* the original graph is always undirected: we store its number of undirected edges */ embed_graph[*edge_pos].mult = embed_graph[w].mult / 2; } /* insert this edge between vertex record for vv and edge record vv.link[vvout] */ temp = embed_graph[vv].link[vvout]; if (embed_graph[temp].link[0] == embed_graph[temp].link[1]) /* this needs special treatment to ensure consistency of orientation */ { ASSERT(embed_graph[temp].link[0] == vv); tempin = 1 ^ vvout; } else { tempin = embed_graph[temp].link[0] == vv ? 0 : 1; } IF_DEB( fprintf(stdout, "embed_edge, edge out of vv\n"); embedg_VES_print_edge(embed_graph, n, temp); ) embed_graph[vv].link[vvout] = *edge_pos; embed_graph[temp].link[tempin] = *edge_pos; /* the links for *edge_pos must also be "consistent" */ embed_graph[*edge_pos].link[vvout] = temp; embed_graph[*edge_pos].link[vvout ^ 1] = vv; /* now create/set the twin edge, the directed edge [w, vv] */ (*edge_pos)++; ASSERT(*edge_pos < 2*n + 2 * MAXE(n)); embed_graph[*edge_pos].neighbour = vv; embed_graph[*edge_pos].type = edge_type; embed_graph[*edge_pos].sign = CCLOCKW; if (edge_type == BE) { embed_graph[*edge_pos].in_adjl = embed_graph[w].in_adjl; embed_graph[*edge_pos].twin_in_adjl = embed_graph[w].twin_in_adjl; embed_graph[*edge_pos].mult = embed_graph[w].mult / 2; } /* and insert the twin edge between edge record w.link[win] and vertex record for w */ temp = embed_graph[w].link[win]; if (embed_graph[temp].link[0] == embed_graph[temp].link[1]) /* again, special treatment to ensure consistency of orientation */ { ASSERT(embed_graph[temp].link[0] == w); tempout = 1 ^ win; } else { tempout = embed_graph[temp].link[0] == w ? 0 : 1; } IF_DEB( fprintf(stdout, "embed_edge, edge in of w\n"); embedg_VES_print_edge(embed_graph, n, temp); ) embed_graph[w].link[win] = *edge_pos; embed_graph[temp].link[tempout] = *edge_pos; /* and consistent orientation */ embed_graph[*edge_pos].link[win] = temp; embed_graph[*edge_pos].link[win ^ 1] = w; } void embedg_VES_add_edge (t_ver_edge *embed_graph, int n, int *edge_pos, int v, int w, boolean MARK, int mark) /* add the edge (v, w): this is DIFFERENT from embedg_VES_embed_edge in the sense that the present function will only be used when building the Kuratowski homeomorphs: that is, we are in a situation where the graph is NON planar consequently it doesn't matter much where in the adjacency lists of v & w the edge is added: let's say that we always add it at the beginning for our sanity's sake, we'll ensure that the resulting adjacency lists remain consistent! and we add the edge as a BE! PLUS we mark it with mark in MARK true */ { int temp; ASSERT(embedg_VES_is_vertex(n, v) || embedg_VES_is_virtual_vertex(n, v)); ASSERT(embedg_VES_is_vertex(n, w) || embedg_VES_is_virtual_vertex(n, w)); IF_DEB( fprintf(stdout, "add_edge, (%d:%d)\n", v, w); ) /* not sure this is the best place to do this: mark the endpoints */ if (MARK) { embed_graph[v].visited = mark; embed_graph[w].visited = mark; } /* first, set the edge [v, w] with the appropriate info */ (*edge_pos)++; ASSERT(*edge_pos < 2*n + 2 * MAXE(n)); embed_graph[*edge_pos].neighbour = w; embed_graph[*edge_pos].type = BE; /* the edge's orientation will be the same as the vertex */ embed_graph[*edge_pos].sign = embed_graph[v].sign; /* and mark the edge */ if (MARK) { embed_graph[*edge_pos].visited = mark; } /* insert this edge between vertex record for v and edge record v.link[1] */ temp = embed_graph[v].link[1]; IF_DEB( fprintf(stdout, "add_edge, edge out of v\n"); embedg_VES_print_edge(embed_graph, n, temp); ) embed_graph[v].link[1] = *edge_pos; embed_graph[temp].link[0] = *edge_pos; /* the links for *edge_pos must also be "consistent" */ embed_graph[*edge_pos].link[1] = temp; embed_graph[*edge_pos].link[0] = v; /* now create/set the twin edge, the directed edge [w, v] */ (*edge_pos)++; ASSERT(*edge_pos < 2*n + 2 * MAXE(n)); embed_graph[*edge_pos].neighbour = v; embed_graph[*edge_pos].type = BE; embed_graph[*edge_pos].sign = embed_graph[w].sign; if (MARK) { embed_graph[*edge_pos].visited = mark; } /* insert this edge between vertex record for w and edge record w.link[1] */ temp = embed_graph[w].link[1]; IF_DEB( fprintf(stdout, "add_edge, edge out of w\n"); embedg_VES_print_edge(embed_graph, n, temp); ) embed_graph[w].link[1] = *edge_pos; embed_graph[temp].link[0] = *edge_pos; /* and consistent orientation */ embed_graph[*edge_pos].link[1] = temp; embed_graph[*edge_pos].link[0] = w; } /* * recover.c */ /* What: ***** Implementing: From the VES data structure recover either the embedding ot the obstruction into the t_sparseg_ver_struct, t_sparseg_adjl_struct, t_sparseg_embed_struct data types. (This is no even quite true: for some obscure reason I recover the obstruction as a dlcl[] structure to be converted later. The obvious reason being that it is easier to check as such. Maybe I leave it as it is...) ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_EMBED_MULT(x) {} #define IF_DEB_EMBED_LOOPS(x) {} #define IF_DEB_EMBED(x) {} #define IF_DEB_CHECK_EMBED(x) {} #define IF_DEB_FACES(x) {} #define IF_VERB(x) {} #define IF_DEB_SCE(x) {} #define IF_DEB_OBS(x) {} #define IF_DEB_CHECK_OBS(x) {} #define IF_CPU(x) {} /* aproto: header embed_graph_protos.h */ /* aproto: beginstatic -- don't touch this!! */ static void embedg_recover_embedding_embed_mult (t_dlcl **, t_embed_sparse_rep *, int, int, int, int, int *, boolean *, int *); static void embedg_recover_embedding_embed_loops (t_dlcl **, t_embed_sparse_rep *, int, int, int *, boolean *); static t_dlcl **embedg_get_reduced_obs (t_dlcl **, int); static boolean embedg_is_red_obs_K33 (t_dlcl **, int); static boolean embedg_is_red_obs_K5 (t_dlcl **, int); /* aproto: endstatic -- don't touch this!! */ #ifndef PLANAR_IN_MAGMA #endif void embedg_recover_embedding ( t_ver_sparse_rep *V, t_adjl_sparse_rep *A, /* input (original sparse graph) */ t_ver_edge *embed_graph, int n, int nbr_e, t_dlcl **mult_edges, t_ver_sparse_rep **vertices, t_embed_sparse_rep **embedding ) /* recover the embedding to prepare for the final Magma type for sparse & embedded graph we assume that all vertices/edges have been given their orientation at this stage we also embed the multiple edges and loops which were set aside in mult_edges by sparseg_adjl_dfs_preprocessing: as it turns out the last bit is pretty hairy! */ { /* the idea is to return an array of vertices and an array representing the embedding (careful: need to weedout the SCE) vertices: (*vertices)[i].first_edge contains index to first edge in embedding embedding: a doubly linked circular list of edges, for each record/edge e = (*embedding)[i]: e.in_adjl: index in A of e e.next: next edge in CLOCKW (as an index in the embedding) e.prev: previous edge in CLOCKW (as an index in embedding) e.inv: inverse edge (as an index in embedding) e.mark: a mark for this edge let's say that this new array is a slimmed down version of embed_graph one issue to address: - for edge e, find its index in A: this should be found in either the embed_graph[v] record of the mult_edges[v] record */ int index_embed, v, mult, w, v_w_in_embed, new_first_edge; boolean set_next; IF_DEB( fprintf(stdout, "in recover emb.\n"); sparseg_dlcl_print(mult_edges, n); ); *vertices = (t_ver_sparse_rep *) mem_malloc(sizeof(t_ver_sparse_rep) * n); *embedding = (t_embed_sparse_rep *) mem_malloc(sizeof(t_embed_sparse_rep) * 2 * nbr_e); index_embed = 0; set_next = TRUE; for (v = 0; v < n; v++) { int v_l, orient, in, out, e, cur_e, next_e; /* we take v's label */ v_l = embed_graph[v].label; /* first let's deal with the isolated vertex case: those that refer to self */ if (embed_graph[v].link[0] == v) { int temp_index_embed; ASSERT(embed_graph[v].link[1] == v); /* there may be [v, v] loops for this vertex, must check this */ temp_index_embed = index_embed - 1; /* temp_index_embed is pre-increased below */ embedg_recover_embedding_embed_loops(mult_edges, *embedding, nbr_e, v, &temp_index_embed, &set_next); if (temp_index_embed > index_embed - 1) /* must fix beginning and end of adjacency list: */ { (*vertices)[v_l].first_edge = index_embed; (*embedding)[temp_index_embed].next = (*vertices)[v_l].first_edge; (*embedding)[(*vertices)[v_l].first_edge].prev = temp_index_embed; index_embed = temp_index_embed; index_embed += 1; } else { (*vertices)[v_l].first_edge = NIL; } continue; } /* get v's orientation, and from this decide the way in which v's adjacency list will be traversed (recall that the list is supposed to be consistent, so no bad surprises) */ orient = embed_graph[v].sign; in = orient == CCLOCKW ? 0 : 1; out = 1 ^ in; e = embed_graph[v].link[out]; while (embedg_VES_is_short_cut_edge(embed_graph, n, e)) { e = embed_graph[e].link[out]; } ASSERT(embedg_VES_is_edge(n, e) && !embedg_VES_is_short_cut_edge(embed_graph, n, e)); /* strictly speaking there should be no SCEs left at this stage... if there are SCEs in v's list, it must be the case that the list also contains tree or back edges... */ (*vertices)[v_l].first_edge = index_embed; IF_DEB_EMBED( fprintf(stdout, "recov. embed. DFI %d vertex %d at %d (edges) and %d (embedding)\n", v, v_l, index_e, (*vertices)[v_l].first_edge); ) cur_e = e; while (TRUE) { next_e = embed_graph[cur_e].link[out]; while (embedg_VES_is_short_cut_edge(embed_graph, n, next_e)) { next_e = embed_graph[next_e].link[out]; } ASSERT(!embedg_VES_is_short_cut_edge(embed_graph, n, next_e)); if (next_e == v) /* end of adjacency list */ { break; } ASSERT(embedg_VES_is_edge(n, next_e)); (*embedding)[index_embed].in_adjl = embed_graph[cur_e].in_adjl; (*embedding)[index_embed].next = index_embed + 1; /* next in adj. list */ (*embedding)[index_embed].mark = NIL; /* mark */ /* cur_e's twin is trickier: we'll use twin's label field to store cur_e's index in the embedding if cur_e's label != NIL this means that cur_e's twin is already stored in edges/embedding and consequently that cur_e.label = index of its twin (in the embedding) note that it is safe to do so since an edge's label has no meaning */ if (embed_graph[cur_e].label != NIL) { (*embedding)[index_embed].inv = embed_graph[cur_e].label; /* but fix the twin by the same token */ (*embedding)[embed_graph[cur_e].label].inv = index_embed; ASSERT((*embedding)[embed_graph[cur_e].label].in_adjl == embed_graph[cur_e].twin_in_adjl); } else /* we store cur_e's index in the embedding in twin's label */ { int twin; twin = embedg_VES_get_twin_edge(embed_graph, n, cur_e); embed_graph[twin].label = index_embed; } /* so the only thing we couldn't update yet is (*embedding)[index_embed].prev, cur_e previous edge in the list but we can do this for next_e */ (*embedding)[index_embed + 1].prev = index_embed; /* we check if there are any multiple edges or loops to embed */ w = embed_graph[cur_e].neighbour; mult = embed_graph[cur_e].mult - 1; /* one was for the TE or BE edge */ if (index_embed == (*vertices)[v_l].first_edge) /* when looking for multiple edges/loops we must temporarily "close" this ordered list of vertices when in presence of the first edge in the list: not doing this would mean that (*embedding)[(*vertices)[v_l].first_edge].prev contains some irrelevant value which may cause (major) trouble when embedding inverses of multiple edges... */ { (*embedding)[(*vertices)[v_l].first_edge].prev = index_embed; } embedg_recover_embedding_embed_mult(mult_edges, *embedding, nbr_e, v, w, mult, &index_embed, &set_next, &new_first_edge); embedg_recover_embedding_embed_loops(mult_edges, *embedding, nbr_e, v, &index_embed, &set_next); set_next = TRUE; /* yes, it may be the case that (*vertices)[v_l].first_edge change while in embedg_recover_embedding_embed_mult -- see that function for more */ (*vertices)[v_l].first_edge = new_first_edge == NIL ? (*vertices)[v_l].first_edge : new_first_edge; /* that's all, we proceed to read a new edge in the list */ index_embed += 1; cur_e = next_e; } /* now next_e = v so that cur_e is the last edge in v's adjacency list we must deal with this case separately */ /* fix cur_e in embedding (and its twin) */ (*embedding)[index_embed].in_adjl = embed_graph[cur_e].in_adjl; /* we temporarily set next of cur_e in to index_embed + 1 */ (*embedding)[index_embed].next = index_embed + 1; (*embedding)[index_embed].mark = NIL; /* mark */ /* fix cur_e's twin */ if (embed_graph[cur_e].label != NIL) { (*embedding)[index_embed].inv = embed_graph[cur_e].label; (*embedding)[embed_graph[cur_e].label].inv = index_embed; ASSERT((*embedding)[embed_graph[cur_e].label].in_adjl == embed_graph[cur_e].twin_in_adjl); } else { int twin; twin = embedg_VES_get_twin_edge(embed_graph, n, cur_e); embed_graph[twin].label = index_embed; } /* we temporarily set the next record's prev field: but we can do that only if we haven't processed all the edges yet */ if (index_embed < 2 * nbr_e - 1) { (*embedding)[index_embed + 1].prev = index_embed; /* again, check if there are any multiple edges/loops to embed */ w = embed_graph[cur_e].neighbour; mult = embed_graph[cur_e].mult - 1; /* one was for the TE or BE edge */ v_w_in_embed = index_embed; if (index_embed == (*vertices)[v_l].first_edge) /* same comment as above */ { (*embedding)[(*vertices)[v_l].first_edge].prev = index_embed; } embedg_recover_embedding_embed_mult(mult_edges, *embedding, nbr_e, v, w, mult, &index_embed, &set_next, &new_first_edge); embedg_recover_embedding_embed_loops(mult_edges, *embedding, nbr_e, v, &index_embed, &set_next); /* same comment as above */ (*vertices)[v_l].first_edge = new_first_edge == NIL ? (*vertices)[v_l].first_edge : new_first_edge; } /* to finish off, we must set: cur_e's next field: next of cur_e in the list is ... vertices[v_l].first_edge cur_e's next's previous field... */ if (set_next) /* set_next (poorly named) is used to indicate which edges must be updated to "close off" the list: if set_next is TRUE, we are in the standard case where the last edge in the ordered adj. list is at index_embed if set_next is FALSE, the last edge in the ordered adj. list is at v_w_in_embed: because it could have happened (in embedg_recover_embedding_embed_mult only) that the edges have been "wedged" between v_w_in_embed.prev and v_w_in_embed, leaving v_w_in_embed the last in the list */ { (*embedding)[index_embed].next = (*vertices)[v_l].first_edge; (*embedding)[(*vertices)[v_l].first_edge].prev = index_embed; } else { (*embedding)[v_w_in_embed].next = (*vertices)[v_l].first_edge; (*embedding)[(*vertices)[v_l].first_edge].prev = v_w_in_embed; } set_next = TRUE; /* a simple check */ ASSERT(embedg_dlcl_is_empty(mult_edges[v])); /* we can process another vertex */ index_embed += 1; } /* when this is done there are a few things that must hold */ ASSERT(index_embed == 2 * nbr_e); } static void embedg_recover_embedding_embed_mult (t_dlcl **mult_edges, t_embed_sparse_rep *embedding, int nbr_e, int v, int w, int mult, int *index_embed, boolean *set_next, int *first_edge) /* see if the directed edge [v, w] is multiple: if so embed it in embedding moreover if there are any [v, v] loops do that too */ { /* we take care of multiple edges: for tree edges and back edges their multiplicity is indicated by the embed_graph[cur_e].mult field (which records the number of undirected edges) for loops hovewer this information is stored in the mult field of the FIRST encountered neighbour v in v's neighbour list */ t_dlcl *p; int v_w_in_embed, v_w_prev; boolean do_twins, start, do_first_edge; IF_DEB_EMBED_MULT( fprintf(stdout, "in recover emb. mult, v %d w %d mult %d\n", v, w, mult); ) /* the current index_embed value is the edge [v, w]: I must record this value as it will be needed later */ v_w_in_embed = *index_embed; start = TRUE; *set_next = TRUE; do_twins = FALSE; *first_edge = NIL; do_first_edge = FALSE; v_w_prev = NIL; while (mult > 0) { ASSERT(!embedg_dlcl_is_empty(mult_edges[v])); p = embedg_dlcl_find(mult_edges[v], w); /* note that using embedg_dlcl_find to always find the first in the list with p->info == w is ok here since any previous such records would have been deleted/removed from the list */ ASSERT(p != NP); /* otherwise we couldn't have mult > 0 ! */ *index_embed += 1; /* once again I must use a similar sort of trick as in the main function to deal with the inverse edge: the inverse edge is to be found in mult_edges[w]: if p->twin_in_adjl (which was initialised to NIL and has NOT been set in the DFS preprocessing), if p->twin_in_adjl != NIL, then a. its inverse in mult_edges[w] has already been embedded in *embedding b. its index there is stored in p->twin_in_adjl precisely */ if (p->twin_in_adjl != NIL) { if (! start) /* if the first the multiple edges' inverse is already stored, then this is true for ALL of them */ { ASSERT(do_twins == TRUE); } do_twins = TRUE; } else /* similarly, if the first the multiple edges' inverse is not already stored, then this is true for ALL of them */ { ASSERT(do_twins == FALSE); } embedding[*index_embed].in_adjl = p->in_adjl; embedding[*index_embed].mark = NIL; /* as we will see do_twins has to be treated differently */ if (!do_twins) /* this is pretty standard as works as the main recover function */ { t_dlcl *i_m_l, *i_p; embedding[*index_embed].next = *index_embed + 1; /* we store the current index in the embedding in the twin/inverse's twin_in_adjl field */ i_p = i_m_l = mult_edges[w]; ASSERT(!embedg_dlcl_is_empty(i_m_l)); i_p = embedg_dlcl_find_with_NIL_twin_in_adjl(i_m_l, v); ASSERT(i_p != NP); ASSERT(i_p->twin_in_adjl == NIL); i_p->twin_in_adjl = *index_embed; /* to finish off this bit we set embedding[*index_embed + 1].prev but I can only set this prev field if I haven't reached the end of the embedding[] array: this is why we needed nbr_e (total number of edges to embed) as input */ if (*index_embed < 2 * nbr_e - 1) { embedding[*index_embed + 1].prev = *index_embed; } } else /* how to insert the inverses of multiple edges already in the embedding: if one studies how the twin_in_adjl field has been set while dealing with the inverses of the present multiple edges one sees that the latter must be inserted in counter clockwise order (assuming that the inverses were inserted in clockwise order) this is necessariy to ensure a correct matching between the edge and its inverse */ { embedding[*index_embed].inv = p->twin_in_adjl; /* fix the twin by the same token */ embedding[p->twin_in_adjl].inv = *index_embed; /* general (reverse) insertion for these edges */ embedding[*index_embed].prev = *index_embed + 1; embedding[*index_embed].next = *index_embed - 1; /* ok, that was the easy bit, things are a bit more complicated below... */ if (start) /* the edges are "wedged" between embedding[v_w_in_embed].prev and v_w_in_embed, hence the following */ { v_w_prev = embedding[v_w_in_embed].prev; if (v_w_prev == v_w_in_embed) /* in this case the first edge in the adj. list of the vertex whose first_edges is v_w_in_embed will be changed (because we insert in reverse order) */ { do_first_edge = TRUE; } embedding[*index_embed].next = v_w_in_embed; embedding[v_w_in_embed].prev = *index_embed; ASSERT(embedding[embedding[*index_embed].inv].prev == embedding[v_w_in_embed].inv); ASSERT(embedding[embedding[v_w_in_embed].inv].next == embedding[*index_embed].inv); } if (mult == 1) /* last inv. edge in this list to add */ { ASSERT(v_w_prev != NIL); /* must fix embedding[v_w_prev].next appropriately (and embedding[*index_embed].prev) this may be overwritten later on, but not necessarily so the next_set flag will enable us to decide which edge ends this adjacency list: see above */ embedding[*index_embed].prev = v_w_prev; embedding[v_w_prev].next = *index_embed; *set_next = FALSE; ASSERT(embedding[embedding[*index_embed].inv].prev == embedding[*index_embed - 1].inv); ASSERT(embedding[embedding[*index_embed - 1].inv].next == embedding[*index_embed].inv); if (do_first_edge) /* the first edge is the last one added */ { *first_edge = *index_embed; } embedding[v_w_in_embed].next = *index_embed + 1; if (*index_embed < 2 * nbr_e - 1) { embedding[*index_embed + 1].prev = v_w_in_embed; } } ASSERT(embedding[embedding[*index_embed].inv].prev == embedding[embedding[*index_embed].next].inv); } /* to finish off this bit we delete the p record from m_l and set embedding[*index_embed + 1].prev */ mult_edges[v] = embedg_dlcl_delete_rec(mult_edges[v], p); mult--; start = FALSE; } /* conclusion: sevral days to get this working! *sigh* */ } static void embedg_recover_embedding_embed_loops (t_dlcl **mult_edges, t_embed_sparse_rep *embedding, int nbr_e, int v, int *index_embed, boolean *set_next) /* embed the [v, v] loops */ { /* the loops' multiplicity is stored in the mult field of the FIRST encountered neighbour v in v's neighbour list */ t_dlcl *p; int nbr_loops; /* have a look if there are any [v. v] loops */ p = embedg_dlcl_find(mult_edges[v], v); if (p == NP) { return; } /* when there are loops to add to the adjaceny list, edge insertion resume in the "normal" clockwaise saya, way: so we reset set_next to true */ *set_next = TRUE; nbr_loops = p->mult; ASSERT(nbr_loops % 2 == 0); /* we counted directed edges */ nbr_loops /= 2; IF_DEB_EMBED_LOOPS( fprintf(stdout, "in recover emb. loops, nbr_loops [v, v] %d\n", nbr_loops); ) while (nbr_loops > 0) /* a loop requires to embed two directed edges */ { p = embedg_dlcl_find(mult_edges[v], v); ASSERT(p != NP); *index_embed += 1; embedding[*index_embed].in_adjl = p->in_adjl; embedding[*index_embed].next = *index_embed + 1; embedding[*index_embed].mark = NIL; embedding[*index_embed].inv = *index_embed + 1; embedding[*index_embed + 1].prev = *index_embed; mult_edges[v] = embedg_dlcl_delete_rec(mult_edges[v], p); IF_DEB_EMBED_LOOPS( fprintf(stdout, "in recover emb. loops, mid\n"); embedg_dlcl_print(mult_edges[v]); ); /* now do the "inverse" loop */ p = embedg_dlcl_find(mult_edges[v], v); ASSERT(p != NP); *index_embed += 1; embedding[*index_embed].in_adjl = p->in_adjl; embedding[*index_embed].next = *index_embed + 1; embedding[*index_embed].mark = NIL; embedding[*index_embed].inv = *index_embed - 1; if (*index_embed < 2 * nbr_e - 1) { embedding[*index_embed + 1].prev = *index_embed; } mult_edges[v] = embedg_dlcl_delete_rec(mult_edges[v], p); nbr_loops--; IF_DEB_EMBED_LOOPS( fprintf(stdout, "in recover emb. loops, end\n"); embedg_dlcl_print(mult_edges[v]); ); } } void embedg_recov_embed_walk_proper_face (int n, int e, t_adjl_sparse_rep *A, t_embed_sparse_rep *embedding, boolean MARK, int mark) /* do a proper face walk in the recovered embedding starting at index e in the embedding */ { int cur, next; IF_DEB_FACES( fprintf(stdout, "recov. emb. proper face walk\n"); fprintf(stdout, "[-, %d] ", A[embedding[e].in_adjl].end_vertex); ) cur = e; next = NIL; while (next != e) /* to get the next in a proper face traversal: get the previous of the cur's inverse */ { int inv; inv = embedding[cur].inv; next = embedding[inv].prev; ASSERT(embedding[next].mark != mark); if (MARK) { embedding[next].mark = mark; } cur = next; IF_DEB_FACES( fprintf(stdout, "[-, %d] ", A[embedding[cur].in_adjl].end_vertex); ) } IF_DEB_FACES( fprintf(stdout, "\n"); ) } boolean embedg_check_recov_embedding (int n, int nbr_e, int nbr_comp, t_ver_sparse_rep *vertices, t_adjl_sparse_rep *A, t_embed_sparse_rep *embedding) /* check if the recovered embedding is a valid embedding SHOULD ONLY be use after creation, that is, after having recovered the embedding from the VES structure (because of the mark MIN_EMBED_MARK we use) */ { int v, e, f; f = 0; /* do all the edges in embedding: careful: we have 2 * nbr_e to visit (the edge and its inverse!) */ for (e = 0; e < 2 * nbr_e; e++) { /* we check if the current edge is marked: if not, we traverse a proper face bordered by this edge */ if (embedding[e].mark != MIN_EMBED_MARK) /* we --hopefully-- perform this check only after creation where mark == NIL */ { embedg_recov_embed_walk_proper_face(n, e, A, embedding, TRUE, MIN_EMBED_MARK); f++; } } /* must also count a face for each isolated vertex */ for (v = 0; v < n; v++) { if (vertices[v].first_edge == NIL) f++; } IF_DEB_CHECK_EMBED( fprintf(stdout, "recovered embedding, n: %d\t e: %d\t C: %d\t f: %d\n", n, nbr_e, nbr_comp, f); ) return f == 2 * nbr_comp + nbr_e - n ? TRUE : FALSE; } t_dlcl ** embedg_recover_obstruction (t_ver_edge *embed_graph, int n, minor m, int *nbr_e) /* recover the obstruction as a t_dlcl * structure: and return the number of edges: lets say we agree on returning the number of undirected edges -- I don't know yet which way to do, directed or undirected??? so far in the algorithm we only dealt with DFIs, but now, we retrieve the obstruction not wrt DFIs but wrt the vertices' labels */ { /* so I am looking, in embed_graph, for the vertices and edges marked MARK_MINORS(n) */ int v; t_dlcl **obs; obs = (t_dlcl **) mem_malloc(sizeof(t_dlcl *) * n); for (v = 0; v < n; v++) obs[v] = NP; *nbr_e = 0; for (v = 0; v < 2*n; v++) /* must check real vertices as well as virtual vertices */ { int e; if (embed_graph[v].link[0] == v) /* isolated vertex case */ { ASSERT(embed_graph[v].link[1] == v); continue; } e = embed_graph[v].link[0]; while (e != v) { ASSERT(embedg_VES_is_edge(n, e)); if (embed_graph[e].visited == MARK_MINORS(n)) { int cur_v, neigh; /* virtual vertices may still hang around */ /* let's get the "actual" v: note that the statement below is safe since if v were not a valid virtual vertex (ie [v - n].DFS_parent = n) it would have an empty adjacency list and we wouldn't be there anyway */ cur_v = embedg_VES_get_ver(embed_graph, n, v); neigh = embedg_VES_get_ver(embed_graph, n, embed_graph[e].neighbour); /* again, cur_v and neigh are DFIs, we want vertex labels at this stage */ cur_v = embed_graph[cur_v].label; neigh = embed_graph[neigh].label; sparseg_dlcl_append_to_neigh_list(obs, n, cur_v, neigh, embed_graph[e].in_adjl); (*nbr_e)++; } e = embed_graph[e].link[0]; } } IF_DEB_OBS( fprintf(stdout, "recovering the obstruction\n"); sparseg_dlcl_print(obs, n); ); ASSERT(*nbr_e % 2 == 0); *nbr_e /= 2; return obs; } static t_dlcl ** embedg_get_reduced_obs (t_dlcl **obs, int n) /* reduce the obstruction by removing all degree 2 vertices (so that they become isolated vertices) */ { t_dlcl **reduced; int v; reduced = (t_dlcl **) mem_malloc(sizeof(t_dlcl *) * n); for (v = 0; v < n; v++) { reduced[v] = embedg_dlcl_copy(obs[v]); } for (v = 0; v < n; v++) { t_dlcl *n_l, *n_l_b, *p, *new_n_v, *n_l_x, *b_in_n_x; int a, b, n_x; n_l = reduced[v]; while (!embedg_dlcl_is_empty(n_l) && embedg_dlcl_list_last(n_l) == embedg_dlcl_list_next(n_l)) /* pick out which vertices have deg 2 */ { a = n_l->info; b = embedg_dlcl_list_next(n_l)->info; /* we remove the edge (v, b), or rather, we identify v and b: b will then be an isolated vertex fix v's neighbour list: all of b's neighbours are now v's neighbours */ reduced[v] = n_l = embedg_dlcl_delete_rec(n_l, embedg_dlcl_list_last(n_l)); p = n_l_b = reduced[b]; ASSERT(!embedg_dlcl_is_empty(n_l_b)); n_x = p->info; if (n_x != v) { new_n_v = embedg_dlcl_rec_new(n_x); reduced[v] = n_l = embedg_dlcl_cat(n_l, new_n_v); /* and in n_x neighbour list, we must replace b by v */ n_l_x = reduced[n_x]; b_in_n_x = embedg_dlcl_find(n_l_x, b); b_in_n_x->info = v; } /* and do this for all of b's neighbours */ p = embedg_dlcl_list_next(p); while (p != n_l_b) { n_x = p->info; if (n_x != v) { new_n_v = embedg_dlcl_rec_new(n_x); reduced[v] = n_l = embedg_dlcl_cat(n_l, new_n_v); n_l_x = reduced[n_x]; b_in_n_x = embedg_dlcl_find(n_l_x, b); b_in_n_x->info = v; } p = embedg_dlcl_list_next(p); } embedg_dlcl_delete(reduced[b]); reduced[b] = NP; } } IF_DEB_CHECK_OBS( fprintf(stdout, "reducing the obstruction\n"); sparseg_dlcl_print(reduced, n); ) /* now check no degree 2 vertices are left */ for (v = 0; v < n; v++) { t_dlcl *n_l; n_l = reduced[v]; if (!embedg_dlcl_is_empty(n_l)) { ASSERT(embedg_dlcl_list_last(n_l) != embedg_dlcl_list_next(n_l)); } } return reduced; } static boolean embedg_is_red_obs_K33 (t_dlcl **reduced, int n) /* check if the (reduced) obstruction is indeed K33 */ { int v, order, vs[6], i, b1[3]; /* check that order == 6 and that the obstruction is cubic */ order = 0; for (v = 0; v < n; v++) { if (!embedg_dlcl_is_empty(reduced[v])) { if (order == 6) { return FALSE; } order++; vs[order - 1] = v; if (embedg_dlcl_length(reduced[v]) != 3) { return FALSE; } } } if (order != 6) { return FALSE; } /* check if bipartite */ v = vs[0]; ASSERT(!embedg_dlcl_is_empty(reduced[v])); b1[0] = reduced[v]->info; b1[1] = embedg_dlcl_list_next(reduced[v])->info; b1[2] = embedg_dlcl_list_prev(reduced[v])->info; for (i = 1; i < 6; i++) { t_dlcl *n_v; v = vs[i]; n_v = reduced[v]; ASSERT(!embedg_dlcl_is_empty(n_v)); if (n_v->info == b1[0] || embedg_dlcl_list_next(n_v)->info == b1[0] || embedg_dlcl_list_prev(n_v)->info == b1[0]) { if ((n_v->info != b1[1] && embedg_dlcl_list_next(n_v)->info != b1[1] && embedg_dlcl_list_prev(n_v)->info != b1[1]) && (n_v->info != b1[2] && embedg_dlcl_list_next(n_v)->info != b1[2] && embedg_dlcl_list_prev(n_v)->info != b1[2])) { return FALSE; } } else { if ((n_v->info == b1[1] || embedg_dlcl_list_next(n_v)->info == b1[1] || embedg_dlcl_list_prev(n_v)->info == b1[1]) || (n_v->info == b1[2] || embedg_dlcl_list_next(n_v)->info == b1[2] || embedg_dlcl_list_prev(n_v)->info == b1[2])) { return FALSE; } } } return TRUE; } static boolean embedg_is_red_obs_K5 (t_dlcl **reduced, int n) /* check if the (reduced) obstruction is indeed K5 */ { int v, order; /* check that order == 5 and that the obstruction is quadric */ order = 0; for (v = 0; v < n; v++) { if (!embedg_dlcl_is_empty(reduced[v])) { if (order == 5) { return FALSE; } order++; if (embedg_dlcl_length(reduced[v]) != 4) { return FALSE; } } } return TRUE; } boolean embedg_check_recov_obs (t_dlcl **obs, int n, minor m) /* check if the recovered obstruction is one of K33 or K5 */ { t_dlcl **reduced; boolean ans; reduced = embedg_get_reduced_obs(obs, n); if (m != MINOR_E5) { ans = embedg_is_red_obs_K33(reduced, n); } else { ans = embedg_is_red_obs_K5(reduced, n); } sparseg_dlcl_delete(reduced, n); return ans; } /* * obstruction.c */ /* What: ***** Implementing: The graph is not planar: we recover the obstruction from the VES structure and check it as well. (Some of these checks will disappear later) ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} #define IF_DEB_OBS(x) {} #define IF_DEB_CHECK_OBS(x) {} #define IF_CPU(x) {} #define IF_DEB_MINOR(x) {} /* aproto: header embed_graph_protos.h */ void embedg_obstruction ( t_ver_sparse_rep *V, t_adjl_sparse_rep *A, /* the input graph as a sparse graph */ t_dlcl **dfs_tree, /* a sparse graph rep. for the dfs tree -- vertices are as DFIs -- and children are ordered wrt lowpoint value */ t_dlcl **back_edges, /* for each vertex v, a dlcl of the back edges [v, x] incident to v where x is a DESCENDANT of v (vertices are given as DFIs) */ t_ver_edge *embed_graph, /* output of tester */ int n, /* size of the graph */ int *edge_pos, /* pos. in embed_graph for addition of the next edge */ int v, int w_in, /* the unembedded directed back edge [w_in, v] */ t_ver_sparse_rep **OV, /* the obstruction as an adjacency list */ t_adjl_sparse_rep **OA, int *nbr_e_obs /* obstruction's #edges */ ) /* the graph is non planar: we must mark & recover the K33 or K5 homeomorph */ { int *ver_orient; minor m; t_dlcl **obs; /* this is magma code - must be removed */ float sttime, time_to_now; IF_CPU( sttime = time_current_user(); ) /* we will NOT remove the short-cut edges at this stage: we'll have to perform another walkdown in embedg_iso_is_minor_A so 1. saves time when looking for ext. active vertices 2. more importantly this enables us to ascertain that the number of edges in embed_graph (even after completing whichever obstruction applying in this case) will NEVER be > 3*n - 5!!! 3. SCEs are then removed in embedg_iso_is_minor_A (obligatory path for every possible case) */ /* we must compute each vertex's orientation (wrt flipped bicomps) and set the edges' orientation: the other day I was wondering why this was necessary in this instance (because after all we won't get an embedding): orientation is required bacause later in the piece we do a proper face traversal (I guess for Minor C testing) */ ver_orient = embedg_vertices_orientation(embed_graph, n); embedg_VES_set_orientation(embed_graph, n, ver_orient); mem_free(ver_orient); m = embedg_mark_obstruction(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w_in); /* get the obstruction */ obs = embedg_recover_obstruction(embed_graph, n, m, nbr_e_obs); /* and check it */ if (!embedg_check_recov_obs(obs, n, m)) { sparseg_dlcl_delete(obs, n); DIE(); } sparseg_dlcl_to_sparseg(obs, n, *nbr_e_obs, OV, OA); sparseg_dlcl_delete(obs, n); /* just for the sake of it, chcek if the obstruction is a subgraph of the input graph */ if (!sparseg_adjl_sub(*OV, n, *OA, V, n, A)) { DIE(); } IF_DEB_OBS( sparseg_adjl_print(*V, n, *A, FALSE); ) IF_CPU( fprintf(stdout, "CPU for obstruction recovering %f\n", (time_current_user() - sttime)); ) } minor embedg_mark_obstruction ( t_dlcl **dfs_tree, /* a sparse graph rep. for the dfs tree -- vertices are as DFIs -- and children are ordered wrt lowpoint value */ t_dlcl **back_edges, /* for each vertex v, a dlcl of the back edges [v, x] incident to v where x is a DESCENDANT of v (vertices are given as DFIs) */ t_ver_edge *embed_graph, /* output of tester */ int n, /* size of the graph */ int *edge_pos, /* pos. in embed_graph for addition of the next edge */ int v, int w_in /* the unembedded directed back edge [w_in, v] */ ) /* the graph is non planar: we must mark & recover the K33 or K5 homeomorph */ { int c, vr, x, y, w; int *path_v, *path_e, nbr_v, entry_in_path_e; boolean px_attached_high, py_attached_high, is_minor_D; minor m; IF_CPU( float sttime; float time_to_now; sttime = time_current_user(); ) /* find c such that v^c is the root of the biconnected component on which the walkdown failed */ c = embedg_iso_get_c_of_v(embed_graph, n, v, w_in); /* now: decide which minor we are dealing with and mark the appropriate one (vertices/edges marked as MARK_MINOR(n) in embed_graph) */ if (embedg_iso_is_minor_A(embed_graph, n, edge_pos, v, c, &vr)) { embedg_mark_minor_A(dfs_tree, back_edges, embed_graph, n, edge_pos, v, c, vr); IF_DEB_MINOR( fprintf(stdout, "Minor A\n"); ) return MINOR_A; } /* get the externally active vertices x & y and the pertinent w on the external face of the bicomp rooted by v^c and determine if minor B */ if (embedg_iso_is_minor_B(embed_graph, n, edge_pos, v, c, &x, &y, &w)) { embedg_mark_minor_B(dfs_tree, back_edges, embed_graph, n, edge_pos, v, c, x, y, w); IF_DEB_MINOR( fprintf(stdout, "Minor B\n"); ) IF_CPU( fprintf(stdout, "CPU for obstruction isolation %f\n", time_current_user() - sttime); ) return MINOR_B; } /* the remaining cases: must get the highest x-y path it will be containing in path_v (vertices), path_e (edges) */ embedg_iso_get_highest_x_y_path(embed_graph, n, MARK_EXT_FACE(n), MARK_EXT_FACE_L(n), MARK_EXT_FACE_R(n), v, c, x, y, w, &path_v, &path_e, &nbr_v, &entry_in_path_e, &px_attached_high, &py_attached_high, &is_minor_D); /* we are in the minor C case if either one of p_x or p_y is attached high */ if (px_attached_high || py_attached_high) { embedg_mark_minor_C(dfs_tree, back_edges, embed_graph, n, edge_pos, v, c, x, y, w, path_v, path_e, nbr_v, px_attached_high, py_attached_high); IF_DEB_MINOR( fprintf(stdout, "Minor C\n"); ) mem_free(path_v); mem_free(path_e); IF_CPU( fprintf(stdout, "CPU for obstruction isolation %f\n", time_current_user() - sttime); ) return MINOR_C; } if (is_minor_D) { embedg_mark_minor_D(dfs_tree, back_edges, embed_graph, n, edge_pos, v, c, x, y, w, path_v, path_e, nbr_v, entry_in_path_e); IF_DEB_MINOR( fprintf(stdout, "Minor D\n"); ) mem_free(path_v); mem_free(path_e); IF_CPU( fprintf(stdout, "CPU for obstruction isolation %f\n", time_current_user() - sttime); ) return MINOR_D; } /* finally, the minor E case */ m = embedg_mark_minor_E(dfs_tree, back_edges, embed_graph, n, edge_pos, v, c, x, y, w, path_v, path_e, nbr_v); switch (m) { case MINOR_E1: IF_DEB_MINOR( fprintf(stdout, "Minor E1\n"); ) break; case MINOR_E2: IF_DEB_MINOR( fprintf(stdout, "Minor E2\n"); ) break; case MINOR_E3: IF_DEB_MINOR( fprintf(stdout, "Minor E3\n"); ) break; case MINOR_E4: IF_DEB_MINOR( fprintf(stdout, "Minor E4\n"); ) break; case MINOR_E5: IF_DEB_MINOR( fprintf(stdout, "Minor E5\n"); ) break; } mem_free(path_v); mem_free(path_e); IF_CPU( fprintf(stdout, "CPU (scaled) for obstruction isolation %f\n", (time_current_user() - sttime) / e); ) return m; } /* * isolator.c */ /* What: ***** Implementing: The graph is non planar: we isolate the obstruction. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} #define IF_DEB_TREE(x) {} #define IF_DEB_EDGES(x) {} #define IF_CPU(x) {} /* #define IF_DEB_MINOR(x) {x} -- Not Used */ /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif int embedg_iso_get_c_of_v (t_ver_edge *embed_graph, int n, int v, int w) /* the edge [v, w] (w a descendant of v) remains unembedded after the walkdown returns find c such that v^c is the root of the biconnected component on which the walkdown failed */ { /* how to do this??? easy! follow the DFS tree path as given by the field DFS_parent */ int u; u = embed_graph[w].DFS_parent; while (embed_graph[u].DFS_parent != v) { u = embed_graph[u].DFS_parent; } /* this is guaranteed to succeed given the structure of the DFS tree and the fact that there exists a back edge [w, v] */ return u; } boolean embedg_iso_is_minor_A (t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int *vr) /* determines if the obstruction is a minor A */ { /* to do this we again call the walkdown routine with v^c as input, the walkdown routine will fail (since there will be an un-embedded back edge incident to v and to a vertex in the subtree rooted by v^c) the obstruction is a minor A if the merge queue returned by the walkdown is non-empty, if this is the case we return the bicomp last appended to the queue */ int vv; t_merge_queue q; vv = c + n; q = embedg_walkdown(embed_graph, n, edge_pos, vv); /* we MUST remove the SCEs here: this is the only place where it will be done when looking for and recovering an obstruction this is safe since this very function applies to ALL cases! */ embedg_remove_SCE(embed_graph, n, *edge_pos); if (!embedg_merge_queue_empty(q)) /* the bicomp of interest is the last in the queue */ { int r, rin, vrout; embedg_merge_queue_prune(&q, &r, &rin, vr, &vrout); embedg_merge_queue_delete(q); return TRUE; } else { embedg_merge_queue_delete(q); return FALSE; } } void embedg_iso_get_x_y_w (t_ver_edge *embed_graph, int n, int v, int r, int c, int mark, int mark_l, int mark_r, int *x, int *y, int *w) /* the obstruction is one of minor B, C, D, E. get the externally active vertices x & y along the external face paths starting at r^c get a pertinent vertex w along the lower external face path between x and y external activity and pertinence are wrt v all the vertices on the external face r^c...x...w and r^c...y...w will be marked (the visited field) */ { int vr, vrin, x_y[4]; int s, sin, cur, curin; vr = c + n; /* find x and y first: note that we mark the vertices on the external face r^c...x and r^c...y more on that below */ embed_graph[vr].visited = mark; for (vrin = 0; vrin <= 1; vrin++) { int m; m = vrin == 0 ? mark_l : mark_r; embedg_VES_get_succ_ext_active_on_ext_face(embed_graph, n, v, vr, vrin, TRUE, m, &s, &sin); x_y[vrin] = s; x_y[vrin + 2] = sin; /* note the bizarre way I store the active vertex and the direction out of which to continue a walk on the lower external face as described above */ } *x = x_y[0]; *y = x_y[1]; /* next get the pertinent w on the lower external face from x to y */ cur = x_y[0]; curin = x_y[2]; embedg_VES_get_succ_pertinent_on_ext_face(embed_graph, n, v, cur, curin, TRUE, mark_l, w, &sin); /* now all the vertices r^c...x...w and r^c...y have been marked, it remains to mark the vertices on the y...w external face path (will need to be able to distinguish the external face later on) Note the way the external face is marked (needed when recovering the highest x-y path): mark_l for the path v^c...x...w mark_r for the path v^c...y mark for the lower external face y...w */ cur = x_y[1]; curin = x_y[3]; s = n; while (s != *w) { embedg_VES_get_succ_pertinent_on_ext_face(embed_graph, n, v, cur, curin, TRUE, mark, &s, &sin); cur = s; curin = sin; } IF_DEB( fprintf(stdout, "get x, y & w: the external face\n"); fprintf(stdout, "%d\t", vr); cur = vr; curin = 0; while (s != vr) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &s, &sin); cur = s; curin = sin; fprintf(stdout, "%d\t", s); } fprintf(stdout, "\n"); ) } boolean embedg_iso_is_minor_B (t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int *x, int *y, int *w) /* determines if the obstruction is a minor B and return x, y (ext. active) and w (pertinent) */ { /* get x & y the ext. active vertices on the (external face) path out of v^c, and w the pertinent vertex on the lower external face x-y PLUS mark the whole external face with MARK_EXT_FACE(n) */ embedg_iso_get_x_y_w(embed_graph, n, v, v, c, MARK_EXT_FACE(n), MARK_EXT_FACE_L(n), MARK_EXT_FACE_R(n), x, y, w); if (embedg_dlcl_is_empty(embed_graph[*w].pertinent_bicomp_list)) /* w has no pertinent child bicomp: not a minor B */ return FALSE; else { t_dlcl *pert_l; int l; pert_l = embed_graph[*w].pertinent_bicomp_list; l = embedg_dlcl_list_last(pert_l)->info; /* if w has an ext. active pertinent child bicomp then minor B note that we need to know if w has an ext. active AND pertinent bicomp child: so it is NOT good enough to test w's separated_DFS_child_list as is done in embedg_VES_is_ver_ext_active!!!!!!!!! PLUS: l is actually a VIRTUAL vertex: to check its lowpoint I must take its DFS child l - n !!!!!!!! */ ASSERT(embedg_VES_is_virtual_vertex(n, l)); l = l - n; return embed_graph[l].lowpoint < v ? TRUE : FALSE; } } void embedg_iso_get_highest_x_y_path ( t_ver_edge *embed_graph, int n, int mark, int mark_l, int mark_r, int v, int c, int x, int y, int w, int **path_v, /* stack of vertices in x-y path */ int **path_e, /* stack of egdes in x-y path */ int *nbr_v, /* number of vertices in path_v */ int *entry_in_path_e, /* the in direction for the FIRST edge in path_e: needed later on *sigh* */ boolean *px_attached_high, boolean *py_attached_high, boolean *is_minor_D ) /* the obstruction is one of minor C, D, E. we want to recover the highest x-y path: the obstructing path attached to the external faces v^c - x - w and v^c - y - w while doing all this we also determine if the case is a minor C or a minor D */ { /* the path is obtained by walking the proper face starting at v where ALL the edges incident to v^c BUT the ones bordering the external face have been removed I won't I don't think remove these edges, but instead I'll be implementing an "avoidance" walk */ int vv, s, sin, p_x, p_y, cur_v, cur_vin; int e, ein, s_e, s_ein; boolean avoid_vv; /* must start the walk at edge embed_graph[v^c].link[1 ^ 0], (vvin = 0 is in direction of x, see embedg_iso_get_x_y_w) */ vv = c + n; e = embed_graph[vv].link[1]; ein = 0; /* because of adjacency list consistency */ *path_v = (int *) mem_malloc(sizeof(int) * n); *path_e = (int *) mem_malloc(sizeof(int) * n); (*nbr_v) = -1; /* recall that in embedg_iso_get_x_y_w we did mark (with mark, mark_l, mark_r) ALL the vertices lying on the external face walk starting & ending at v^c: we will use this fact to enable us to decide if a vertex is on the external face (as opposed to being on the internal face) */ s = embed_graph[e].neighbour; ASSERT(embed_graph[s].visited == mark_l); /* this must be the case since s lies on the external face starting at v^c in x's direction -- we push s onto the stack */ (*path_v)[++(*nbr_v)] = s; /* start the proper face walk which "avoids" v^c since the internal edges incident to v^c are supposed to have been removed please read on */ avoid_vv = FALSE; while (TRUE) { boolean av; av = embedg_VES_get_succ_on_proper_face_with_avoidance( embed_graph, n, e, ein, vv, FALSE, 0, &s, &s_e, &s_ein); avoid_vv = av == TRUE ? av : avoid_vv; if (embed_graph[s].visited == mark_l) /* means that s is still on the external face: empty the path's stack and push s */ { (*nbr_v) = -1; (*path_v)[++(*nbr_v)] = s; e = s_e; ein = s_ein; } else if (*nbr_v == 0) /* s is the first encountered vertex after path_v[0] which does not lie on the external face v^c...c...w given the way we pushed things on the vertex stack, path_v[0] will be the point of attachement of the x-y path on the v^c...x...w external face path_e[0] will contain nothing: a dummy path_e[1] will be the first edge in the x-y path (and entry_in_path will give the in-direction to this edge) oh yes!, we break the loop at this point if the vertex s lies on the v^c...y...w external face */ { ASSERT(embed_graph[(*path_v)[0]].visited == mark_l); /* the first vertex on the path must be on the v^c...x...w external face */ (*path_v)[++(*nbr_v)] = s; /* and now we also push the edge on the edge stack I'll need this later to initiate a proper face walk starting at the first vertex/edge in the x-y path, which is the same as starting from s_e */ (*path_e)[*nbr_v] = s_e; *entry_in_path_e = s_ein; e = s_e; ein = s_ein; /* since we are at the start of the path, we must not forget to reset avoid_vv */ avoid_vv = FALSE; if (embed_graph[s].visited == mark_r || embed_graph[s].visited == mark) /* we have reached the v^c...y...w external face: we can stop here */ { break; } /* if not finished yet, we also mark s (and path_v[0]) as visited: later on we'll need to recognise which of the vertices in path have already been encountered (in case of encountering a cut-vertex due to the "removal" of the "internal" edges incidnet ot v^c) note that we mark s as visited iff s if not already on the v^c..y..w external face */ ASSERT(embedg_VES_is_vertex(n, (*path_v)[0])); ASSERT(embedg_VES_is_vertex(n, s)); embed_graph[s].visited = MARK_X_Y_PATH(n); } else if (embed_graph[s].visited == MARK_X_Y_PATH(n)) /* this means that s is a cut vertex on the internal face walk: pop all the vertices from path until s's last occurrence in path */ { ASSERT((*nbr_v) >= 0); while ((*path_v)[(*nbr_v)] != s) { (*nbr_v)--; ASSERT((*nbr_v) >= 0); /* note that s should be somewhere in path! */ } /* note also that popping from path_v also implies popping from path_e */ e = s_e; ein = s_ein; } else /* we push s and s_e on their respective stacks */ { (*path_v)[++(*nbr_v)] = s; (*path_e)[*nbr_v] = s_e; e = s_e; ein = s_ein; if (embed_graph[s].visited == mark_r || embed_graph[s].visited == mark) /* again, s lies on the v^c...y...w external face: we end the walk: path_v now contains the highest x-y path note that there can be no conflict between mark_r or mark and MARK_X_Y_PATH(n) since we mark with MARK_X_Y_PATH iff the vertex is NOT marked with mark_r/mark! */ { break; } else /* we must mark this vertex as MARK_X_Y_PATH since we aren't finished yet */ { embed_graph[s].visited = MARK_X_Y_PATH(n); } } } /* there is only one thing remaining to do: see if p_x or p_y are attached high (ie closer to v^c than x or y resp.) we walk the external face starting at v^c in y's direction (again see embedg_iso_get_x_y_w) */ *px_attached_high = TRUE; p_x = (*path_v)[0]; /* p_y denotes the attachement point of the x-y path on the v^c...y...w external face */ s = n; cur_v = vv; cur_vin = 0; while (s != p_x) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur_v, cur_vin, FALSE, 0, &s, &sin); if (s == x) { *px_attached_high = FALSE; break; } cur_v = s; cur_vin = sin; } *py_attached_high = TRUE; p_y = (*path_v)[*nbr_v]; /* p_y denotes the attachement point of the x-y path on the v^c...y...w external face */ s = n; cur_v = vv; cur_vin = 1; while (s != p_y) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur_v, cur_vin, FALSE, 0, &s, &sin); if (s == y) { *py_attached_high = FALSE; break; } cur_v = s; cur_vin = sin; } /* now we are in the minor C case if either p_x or p_y are attached high the minor D case: this happens when there is a path v^c - z where z lies on the x-y path that is, when either v^c has been effectively "avoided" within the embedg_VES_get_succ_on_proper_face_with_avoidance function BUT ONLY if this "avoidance" happened AFTER having encountered the very first vertex on the x-y path! or when a cut vertex has been encountered on the x-y path: separable components on this walk can only occur if one walks the face while skipping the edges incident to v^c in any case this means that checking the return from the embedg_VES_get_succ_on_proper_face_with_avoidance function is enough: this is the purpose of avoid_vv. */ *is_minor_D = !(*px_attached_high || *py_attached_high) && avoid_vv; IF_DEB( int i; fprintf(stdout, "x-y path\t"); for (i = 0; i <= *nbr_v; i++) fprintf(stdout, "%d\t", (*path_v)[i]); fprintf(stdout, "\n"); ) } /* * embedg_misc.c */ /* What: ***** Implementing: Some high level routinse for the VES structure. See VES_misc.c. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} #define IF_DEB_TREE(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif void embedg_VES_delete (t_ver_edge *embed_graph, int n) { int i; for (i = 0; i < n; i++) { embedg_dlcl_delete(embed_graph[i].separated_DFS_child_list); /* embedg_dlcl_delete(embed_graph[i].rep_in_parent_list); NO!!! this points to something in separated_DFS_child_list */ embedg_dlcl_delete(embed_graph[i].pertinent_bicomp_list); } mem_free(embed_graph); } void embedg_VES_print (t_ver_edge *embed_graph, int n) { int i; fprintf(stdout, "vertices\n"); for (i = 0; i < n; i++) { t_ver_edge rec; rec = embed_graph[i]; fprintf(stdout, "\nDFI\t%d\tlabel\t%d\n", i, rec.label); fprintf(stdout, "DFS parent\t%d\tleast_a\t%d\tlowpoint\t%d\n", rec.DFS_parent, rec.least_ancestor, rec.lowpoint); fprintf(stdout, "separated_DFS_child_list\n"); embedg_dlcl_print(rec.separated_DFS_child_list); } fprintf(stdout, "\nvirtual vertices\n"); for (i = n; i < 2*n; i++) { int c; c = i - n; fprintf(stdout, "%d^%d\t", embed_graph[c].DFS_parent, c); } fprintf(stdout, "\n"); embedg_VES_print_bigcomps(embed_graph, n); } void embedg_VES_print_bigcomps (t_ver_edge *embed_graph, int n) /* walking the external faces of all the bicomp; for testing only */ { int i; fprintf(stdout, "bicomponents\n"); /* to get to the bicomps, it makes sense to start at the virtual vertices???? */ for (i = n + 1; i < 2*n; i++) /* a note of caution: there is no virtual vertex at embed_graph[n] since that would mean a virtual vertex x^0 which makes no sense (0 is the root of the dfs_tree) */ { embedg_VES_walk_bicomp(embed_graph, n, i, 0); } fprintf(stdout, "\n"); } /* * planar_alg_init.c */ /* What: ***** Implementing: Initialising the embed_graph aka VES data structure from the information collected from the DFS. The embed_graph/VES data structure is an array consisting of vertices, virtual vertices and edges; vertices, virtual vertices and edges share a common record structure; one of the particular features is that any vertex is linked together with its incident edges into a doubly circular linked list. See also VES_misc.c. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_DFS(x) {} #define IF_VERB(x) {} #define IF_DEB_TREE(x) {} #define IF_CPU(x) {} /* aproto: header embed_graph_protos.h */ /* aproto: beginstatic -- don't touch this!! */ static embedg_init_insert_TE (t_ver_edge *, int, int *, t_dlcl *); /* aproto: endstatic -- don't touch this!! */ #ifndef PLANAR_IN_MAGMA #endif t_ver_edge * embedg_planar_alg_init ( t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, /* input sparse graph */ int *nbr_c, /* size of the graph, #components*/ int *edge_pos, /* pos in the struct where the last edge has been inserted */ t_dlcl ***dfs_tree, /* a sparse graph rep. for the dfs tree -- vertices are as DFIs */ t_dlcl ***back_edges, /* for each vertex v, a dlcl of the back edges [v, x] incident to v where x is a DESCENDANT of v -- vertices are as DFIs */ t_dlcl ***mult_edges /* for each vertex v, a dlcl of the back edges [v, x] incident to v where x is a DESCENDANT of v -- vertices are as DFIs */ ) /* initialising embed_graph, the fundamental data structure underpinning the tester and obstruction isolator from there on, a vertex is exclusively referred to by its DFI!! -- so forget about labels */ { int *dfs_nbr; /* dfs numbering for each vertex */ int *dfs_order; /* vertices in dfs order */ int *lowpoint; /* lowpoint value for each DFI */ int *dfs_parent; /* for each DFI, its DFS ancestor as a DFI (DFS index) */ int *least_a; /* for each DFI, its least ancestor's DFI (via a back edge exclusively) */ t_ver_edge *embed_graph; int i; IF_CPU( float sttime; float time_to_now; sttime = time_current_user(); ) ASSERT(n >= 1); /* DFS and lowpoint calculations + ordering */ sparseg_adjl_dfs_preprocessing(V, n, A, nbr_c, &dfs_nbr, &dfs_order, &lowpoint, dfs_tree, back_edges, &dfs_parent, &least_a, mult_edges); IF_CPU( fprintf(stdout, "CPU for DFS only %f\n", (time_current_user() - sttime)); sttime = time_current_user(); ) IF_DEB_DFS( fprintf(stdout, "DFS indices\n"); for (i = 0; i < n; i++) fprintf(stdout, "%d ", dfs_nbr[i]); fprintf(stdout, "\n"); fprintf(stdout, "DFS order\n"); for (i = 0; i < n; i++) fprintf(stdout, "%d ", dfs_order[i]); fprintf(stdout, "\n"); fprintf(stdout, "lowpoint values\n"); for (i = 0; i < n; i++) fprintf(stdout, "%d ", lowpoint[i]); fprintf(stdout, "\n"); ); IF_VERB( fprintf(stdout, "DFS parent\n"); for (i = 0; i < n; i++) fprintf(stdout, "%d ", dfs_parent[i]); fprintf(stdout, "\n"); ); IF_VERB( fprintf(stdout, "least ancestors\n"); for (i = 0; i < n; i++) fprintf(stdout, "%d ", least_a[i]); fprintf(stdout, "\n"); ); IF_VERB( for (i = 0; i < n; i++) { fprintf(stdout, "the list of children ordered by lowpoint for %d\n", i); embedg_dlcl_print((*dfs_tree)[i]); } ); IF_DEB_DFS( fprintf(stdout, "the tree edges\n"); sparseg_dlcl_print(*dfs_tree, n); fprintf(stdout, "the back edges\n"); sparseg_dlcl_print(*back_edges, n); fprintf(stdout, "multiple edges\n"); sparseg_dlcl_print(*mult_edges, n); ); /* create the data structure for the embedded graph: it will have (max) size 2*n + 2 * MAXE(n) we will see that that number of edges is sufficient even when later adding short-cut edges (see embedg_walkdown) */ embed_graph = (t_ver_edge *) mem_malloc(sizeof(t_ver_edge) * (2*n + 2 * MAXE(n))); /* initialisation */ for (i = 0; i < 2*n + 2 * MAXE(n); i++) /* some fields are initialised to n as n is actually an "invalid" value */ { t_ver_edge rec; rec.label = NIL; rec.DFS_parent = n; rec.least_ancestor = n; rec.lowpoint = n; rec.separated_DFS_child_list = NP; rec.rep_in_parent_list = NP; rec.pertinent_bicomp_list = NP; rec.adjacent_to = n; rec.visited = n; rec.neighbour = n; rec.in_adjl = NIL; rec.twin_in_adjl = NIL; rec.mult = 0; rec.type = NIL; rec.sign = NILSIGN; /* make the links refer back to self */ rec.link[0] = rec.link[1] = i; embed_graph[i] = rec; } /* embed_graph[0..n-1]: the n vertices ATTENTION: the vertices are stored according to their DFS numbering */ for (i = 0; i < n; i++) { t_ver_edge rec; rec = embed_graph[i]; rec.label = dfs_order[i]; rec.DFS_parent = dfs_parent[i]; rec.least_ancestor = least_a[i]; rec.lowpoint = lowpoint[i]; rec.separated_DFS_child_list = embedg_dlcl_copy((*dfs_tree)[i]); IF_VERB( fprintf(stdout, "the list of children ordered by lowpoint for DFI %d\n", i); embedg_dlcl_print(rec.separated_DFS_child_list); ); embed_graph[i] = rec; } /* one more thing to do for these vertices: fix the rep_in_parent_list field */ for (i = 1; i < n; i++) { t_dlcl *parent_list, *rep; int parent; parent = embed_graph[i].DFS_parent; /* careful: this is a DFI */ /* recall that the vertices in embed_graph are accessed via their DFI */ if (parent != n) /* when parent == n this means that i the root of a DFS tree in the disconnected graph */ { parent_list = embed_graph[parent].separated_DFS_child_list; rep = embedg_dlcl_find(parent_list, i); ASSERT(rep != NP); embed_graph[i].rep_in_parent_list = rep; } } /* embed_graph[n..2*n-1]: the n virtual vertices do I need to do anything here????? no - I don't think so let's try to explain what virtual vertices are: let v^c be a virtual vertex: - it is at position c + n in the array, - c is the DFS child of v, - v can be retrieved by taking embed_graph[c].DFS_parent, - v^c is said virtual as long as the bicomp rooted by v^c is not merged with the vertex v - once v is merged (identified?) with v^c, then v^c is of no relevance anymore below we will see that we embed all the tree edges as singleton bicomps (bicomponent): (0^1, 1), (1^2, 2) etc...: this is what virtual vertices are there for: to distinguish them from their "real" counterpart with which they will be ultimately merged the primary reason for this is: while testing for planarity virtual vertices are the roots of bicomps */ /* now the edges: we actually embed the tree edges so that each tree edge forms a (singleton) biconnected component embedding an edge in effect means creating the doubly linked circular list of [virtual] vertices & the edges incident to it this list is built using the links 0 & 1 in embed_graph[i] */ /* for each tree edge (v,u) we embed (v^u, u) (v^u is the virtual vertex) CAREFUL: when talking about vertex v say, we mean the vertex with DFI v, and NOT the vertex with label v ************************************************************** */ *edge_pos = 2*n - 1; /* edge_pos will tell us where to insert the next edge in embed_graph[] */ for (i = 0; i < n; i++) { t_dlcl *te_l, *p; te_l = (*dfs_tree)[i]; p = te_l; if (!embedg_dlcl_is_empty(p)) { /* the test below is a bit stupid... well... */ ASSERT(embed_graph[p->info].DFS_parent == i); embedg_init_insert_TE(embed_graph, n, edge_pos, p); p = embedg_dlcl_list_next(p); while (p != te_l) { ASSERT(embed_graph[p->info].DFS_parent == i); embedg_init_insert_TE(embed_graph, n, edge_pos, p); p = embedg_dlcl_list_next(p); } } } mem_free(dfs_nbr); mem_free(dfs_order); mem_free(lowpoint); mem_free(dfs_parent); mem_free(least_a); IF_CPU( fprintf(stdout, "CPU for remainder of initialisation %f\n", (time_current_user() - sttime)); ) return embed_graph; } static embedg_init_insert_TE (t_ver_edge *embed_graph, int n, int *edge_pos, t_dlcl *p) /* init and insert a tree edge in embed graph: the tree edge will form a singleton bicomponent (v^c, c) where c is p->info and v is c.DFS_parent */ { int c, v; c = p->info; v = embed_graph[c].DFS_parent; ASSERT(v >= 0 && v < n); /* now (v, c) is a tree edge; embed the directed edge [v^c, c] -- and recall that v^c is a virtual vertex, at position c + n in embed_graph, and that vertex c is at position c */ /* first, set this edge with the appropriate info */ (*edge_pos)++; ASSERT(*edge_pos < 2*n + 2 * MAXE(n)); embed_graph[*edge_pos].neighbour = c; embed_graph[*edge_pos].in_adjl = p->in_adjl; embed_graph[*edge_pos].twin_in_adjl = p->twin_in_adjl; ASSERT(p->mult % 2 == 0); /* we want the number of undirected edges */ embed_graph[*edge_pos].mult = p->mult / 2; embed_graph[*edge_pos].type = TE; embed_graph[*edge_pos].sign = CCLOCKW; /* link this with vertex v^c in a doubly linked circular list */ embed_graph[c + n].link[0] = embed_graph[c + n].link[1] = *edge_pos; embed_graph[*edge_pos].link[0] = embed_graph[*edge_pos].link[1] = c + n; /* now create/set the twin edge, the directed edge [c, v^c] */ (*edge_pos)++; ASSERT(*edge_pos < 2*n + 2 * MAXE(n)); embed_graph[*edge_pos].neighbour = c + n; embed_graph[*edge_pos].in_adjl = p->twin_in_adjl; embed_graph[*edge_pos].twin_in_adjl = p->in_adjl; embed_graph[*edge_pos].mult = p->mult / 2; embed_graph[*edge_pos].type = TE; embed_graph[*edge_pos].sign = CCLOCKW; /* and link it with vertex c in a doubly linked circular list */ embed_graph[c].link[0] = embed_graph[c].link[1] = *edge_pos; embed_graph[*edge_pos].link[0] = embed_graph[*edge_pos].link[1] = c; } /* * dfs_preprocessing.c */ /* What: ***** Implementing: A DFS as an initialisation step for the planarity tester. This is an especially beefed up DFS that collects lots of marginal information: - a DFS tree as a list of DFS children for each vertex - the DFS children are sorted according to their lowpoint value - a back_edge structure as a list of descendants v for each vertex u such that [v, u] is a back edge - a multiple edges structure which stores multiple (directed) edges NOT in the DFS tree nor in the back_edge struc, and loops - the vertices in DFS order - the DFS index (DFI) for each vertex - the lowpoint value for each vertex - the number of components of the (possibly disconnected) graph - for each vertex, its DFS parent - for each vertex v, its least ancestor u such that [v, u] is a back edge ALL info above (except the vertices in DFS order) is given in terms of the vertices' DFIs and NOT their labels. ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ /* There are some dodgy things which need some thought; it would be nice to fix them so that the code get's cleaner: - we do store in_adj (and twin_in_adjl) for each directed edge: + this is ONLY needed at the time of recovering the embedding (see embedg_recover_embedding) and its sole use is to establish a link between an edge in the embedding structure t_embed_sparse_rep *E and the corresponding edge in the t_adjl_sparse_rep *A struc. + well, I cannot recall why I thought this correspondence was needed in the first place and it might well be the case that there is no use for it; in which case recovering the embedding is simplified (we would store the end-vertex in the embedding's edges instead of their index in the adjacency list) - there are some non-linear bits in the DFS below: when searching for an already existing tree/back/multiple edge. I couldn't fix this in less then one hour so I leave it as it is... for now. This shouldn't be a major issue, overall timings of the planarity tester do not show this non-linear "bump"... - also, this algorithm has been growing incrementally and I now realise that I am using some redundant data structures: for example visited[] and the vertex and could be dispensed with... ...more things to clean up... Paulette 07/02/02 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} #define IF_DEB_TREE(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif void sparseg_adjl_dfs_preprocessing ( t_ver_sparse_rep *V, int n, /* size of the graph */ t_adjl_sparse_rep *A, /* input sparse graph */ int *c, /* nbr of components */ int **dfs_nbr, /* dfs numbering for each vertex */ int **dfs_order, /* vertices in dfs order */ int **lowpoint, /* lowpoint value for each DFI */ t_dlcl ***dfs_tree, /* a sparse graph rep. for the dfs tree: for each DFI, a list of its children's DFI ordered wrt their lowpoint values */ t_dlcl ***back_edges, /* for each DFI v, a dlcl of the back edges [v, x] incident to v where x is a DESCENDANT of v */ int **dfs_parent, /* for each DFI its DFS ancestor */ int **least_a, /* for each DFI, its least ancestor's DFI via a back edge exclusively */ t_dlcl ***mult_edges /* for each DFI v, a dlcl of the multiple directed edges NOT included in either dfs_tree or back_edges */ ) /* in ALL the returned info above BUT dfs_order[] we store the vertices' DFIs (DFS indices) and NOT their labels! -- shuffling between labels and vertices can then be done via dfs_nbr[] and dfs_order[] */ { int pos_v_stack, pos_e_stack, dfs_n; int *visited, *vertex_stack, *edge_stack, *lowpoint_order; int *TE_in_adjl, *TE_twin_in_adjl, *TE_mult; int v, lp, cur, cur_e, next; t_dlcl **temp, *lowpoint_list, **new_dfs_tree; /* create the dfs tree as a sparse graph */ *dfs_tree = (t_dlcl **) mem_malloc(sizeof(t_dlcl *) * n); /* the DFS numbering for the vertices */ *dfs_nbr = (int *) mem_malloc(sizeof(int) * n); /* the vertices as ordered by their DFS index */ *dfs_order = (int *) mem_malloc(sizeof(int) * n); /* the lowpoint value for each DFI */ *lowpoint = (int *) mem_malloc(sizeof(int) * n); /* the (directed) back edges */ *back_edges = (t_dlcl **) mem_malloc(sizeof(t_dlcl *) * n); /* the DFS parent for each DFI */ *dfs_parent = (int *) mem_malloc(sizeof(int) * n); /* the least ancestor (via a back edge exlusively) for each DFI */ *least_a = (int *) mem_malloc(sizeof(int) * n); /* the (directed) multiple edges */ *mult_edges = (t_dlcl **) mem_malloc(sizeof(t_dlcl *) * n); /* the vertices visited while DFS */ visited = (int *) mem_malloc(sizeof(int) * n); /* stack of vertices: last current vertex */ vertex_stack = (int *) mem_malloc(sizeof(int) * n); /* stack of (tree) edges: last added tree edge */ edge_stack = (int *) mem_malloc(sizeof(int) * n); /* the following will be used in order to recreate the dfs_tree so that the DFS children of each DFI are ordered according to their lowpoint value */ lowpoint_order = (int *) mem_malloc(sizeof(int) * n); temp = (t_dlcl **) mem_malloc(sizeof(t_dlcl *) * n); new_dfs_tree = (t_dlcl **) mem_malloc(sizeof(t_dlcl *) * n); /* finally, three more holding arrays: a trick to remember which tree edges we are talking about: when constructing dfs_tree, back_edges, mult_edges - we NEED to record the index in A (the adjacency list) of some of the edges and their twins/inverses we are currently storing in either of these structures - we also need to record the number of multiple (directed) edges we encounter when the graph is not simple this is easy to do when storing back edges and multiple edges, and tree edges also: but this lattest set of neighbour lists (dfs_tree) is subsequently reordered so that DFS children are ordered wrt lowpoint values; - consequently the info about position in adjacency list and edge multiplicity are lost in the ordering process the two following arrays will remember the info we'll need later - more about this below */ TE_in_adjl = (int *) mem_malloc(sizeof(int) * n); TE_twin_in_adjl = (int *) mem_malloc(sizeof(int) * n); TE_mult = (int *) mem_malloc(sizeof(int) * n); /* initialization of the data structures */ for (v = 0; v < n; v++) { (*dfs_tree)[v] = (*back_edges)[v] = (*mult_edges)[v] = NP; visited[v] = TE_mult[v] = 0; (*dfs_parent)[v] = (*least_a)[v] = n; temp[v] = new_dfs_tree[v] = NP; TE_in_adjl[v] = TE_twin_in_adjl[v] = NIL; /* note that in the 3rd last statement n is considered as an "invalid" value; will be if importance in the overall algorithm */ } /* the DFS tree is rooted at vertex 0 */ dfs_n = -1; pos_v_stack = -1; pos_e_stack = -1; *c = 0; for (v = 0; v < n; v++) { if (visited[v]) /* we come only at this level when looking for a new subtree (when graph is disconnected) */ { continue; } else { (*c)++; } cur = v; visited[cur] = 1; (*dfs_nbr)[cur] = ++dfs_n; (*lowpoint)[(*dfs_nbr)[cur]] = dfs_n; (*dfs_order)[dfs_n] = cur; cur_e = V[cur].first_edge == NIL ? NIL : V[cur].first_edge; while (TRUE) { if (cur_e != NIL) { t_dlcl *existing_e; next = A[cur_e].end_vertex; if (!visited[next]) /* adding tree edges (careful: directed edges) AND tree edges are stored as [dfs_nbr[u], dfs_nbr[cv]] instead of [u, cv]: that is we store the edges according to the vertices' DFIs */ { IF_DEB_TREE( io_printf("add tree edge %d\t%d\n", cur+1, next+1); ); (*dfs_nbr)[next] = ++dfs_n; (*lowpoint)[(*dfs_nbr)[next]] = dfs_n; (*dfs_order)[dfs_n] = next; sparseg_dlcl_append_to_neigh_list(*dfs_tree, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], NIL); TE_in_adjl[(*dfs_nbr)[next]] = cur_e; TE_mult[(*dfs_nbr)[next]]++; /* we push cur and the edge (cur, cur_e) on their respective stacks */ vertex_stack[++pos_v_stack] = cur; edge_stack[++pos_e_stack] = cur_e; /* and mark next as visited */ visited[next] = 1; /* update dfs_parent (always deal with DFIs rembember!) */ (*dfs_parent)[(*dfs_nbr)[next]] = (*dfs_nbr)[cur]; /* the DFS goes one level deeper */ cur = next; cur_e = V[cur].first_edge == NIL ? NIL : V[cur].first_edge; } /* the next three tests deal with multiple edges and loops: apart from storing these (DIRECTED) edges in mult_edges, we also need to update the multipliciaty information about these edges */ else if (sparseg_dlcl_is_adjacent(*dfs_tree, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], &existing_e)) /* [cur, next] is a tree edge */ { sparseg_dlcl_append_to_neigh_list(*mult_edges, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], cur_e); TE_mult[(*dfs_nbr)[next]]++; cur_e = A[cur_e].next; /* next in cur's adjacency list */ } else if (sparseg_dlcl_is_adjacent(*back_edges, n, (*dfs_nbr)[next], (*dfs_nbr)[cur], &existing_e)) /* [cur, next] is a back edge */ { sparseg_dlcl_append_to_neigh_list(*mult_edges, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], cur_e); (existing_e->mult)++; cur_e = A[cur_e].next; /* next in cur's adjacency list */ } else if (next == cur) /* the case of a loop */ { if (sparseg_dlcl_is_adjacent(*mult_edges, n, (*dfs_nbr)[next], (*dfs_nbr)[cur], &existing_e)) /* in this case we must update the multiplicity of this edge: note that the elt. in cur's neighbours list that gets updated is the first in the list dodgy??? certainly, but can't think of a better way to do this eventually it will happen that even myself won't understand what I am doing.......... */ { (existing_e->mult)++; } sparseg_dlcl_append_to_neigh_list(*mult_edges, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], cur_e); cur_e = A[cur_e].next; /* next in cur's adjacency list */ } else if (sparseg_dlcl_is_adjacent(*dfs_tree, n, (*dfs_nbr)[next], (*dfs_nbr)[cur], &existing_e)) /* [next, cur] is a tree edge: that is, [cur, next] is [next, cur]'s twin/inverse: 1. if it is the first time one encounters [cur, next] (as it would always be the case for a simple graph) then all I need to do is to update the tree edge's multiplicity, and the twin info in TE_[] 2. if [cur, next] is actually a multiple edge, then I'll need to store it in mult_edges; and I update the tree edge's multiplicity too. No twin info will be required here. Why? see how recover.c embeds the multiple edges in the planar embedding. 3. how do I know it is the first time I encounter [cur, next]?: when TE_twin_in_adjl = NIL 4. finally, note that the present counting scheme implies that the mult field always holds the number of directed edges: ie, if [a, b] is a tree edge, [a, b].mult = 2 because we would have counted [a, b] and [b, a] this applies to tree edges, back edges, and loops */ { ASSERT(TE_in_adjl[(*dfs_nbr)[cur]] != NIL); if (TE_twin_in_adjl[(*dfs_nbr)[cur]] == NIL) { TE_twin_in_adjl[(*dfs_nbr)[cur]] = cur_e; } else { sparseg_dlcl_append_to_neigh_list(*mult_edges, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], cur_e); } TE_mult[(*dfs_nbr)[cur]]++; cur_e = A[cur_e].next; /* next in cur's adjacency list */ } else if (sparseg_dlcl_is_adjacent(*back_edges, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], &existing_e)) /* [next, cur] is a back edge: [cur, next] is its inverse: we proceed as for the tree edge case above */ { ASSERT(existing_e->in_adjl != NIL); if (existing_e->twin_in_adjl == NIL) { existing_e->twin_in_adjl = cur_e; } else { sparseg_dlcl_append_to_neigh_list(*mult_edges, n, (*dfs_nbr)[cur], (*dfs_nbr)[next], cur_e); } (existing_e->mult)++; cur_e = A[cur_e].next; /* next in cur's adjacency list */ } /* the next bit concludes the DFS: it deals with the case where a back edge needs to be added */ else /* that is, next is visited and neither the tree edge [next, cur] nor the back edge [next, cur] exist: this implies that [cur, next] is a back edge that must be added to the back_edges structure (with dfs_nbr(next) < dfs_nbr(cur)) */ { IF_DEB_TREE( io_printf("add back edge %d\t%d\n", cur+1, next+1); ); ASSERT(visited[next]); ASSERT((*dfs_nbr)[cur] > (*dfs_nbr)[next]); sparseg_dlcl_append_to_neigh_list(*back_edges, n, (*dfs_nbr)[next], (*dfs_nbr)[cur], cur_e); /* update cur's lowpoint */ (*lowpoint)[(*dfs_nbr)[cur]] = (*dfs_nbr)[next] < (*lowpoint)[(*dfs_nbr)[cur]] ? (*dfs_nbr)[next] : (*lowpoint)[(*dfs_nbr)[cur]]; /* update least_a (of cur) (always deal with DFIs remember!) */ (*least_a)[(*dfs_nbr)[cur]] = (*dfs_nbr)[next] < (*least_a)[(*dfs_nbr)[cur]] ? (*dfs_nbr)[next] : (*least_a)[(*dfs_nbr)[cur]]; /* get the next edge in cur's adjacency list */ cur_e = A[cur_e].next; } } if (cur_e == NIL) /* we are either at a leaf or have finished scanning cur's adjacency list: backtrack */ { if (pos_v_stack == -1) /* no previous vertex */ { /* no edge left on the stack: DFS ends for this subtree: we visit the next vertex */ ASSERT(pos_e_stack == -1); break; } else { int prev_e; /* Otherwise backtrack and pop cur from the stack as well as the last tree edge added to the tree. We use next to get a new lowpoint value for cur: This value will be min(lowpoint(cur), lowpoint(next)). */ cur = vertex_stack[pos_v_stack--]; prev_e = edge_stack[pos_e_stack--]; next = A[prev_e].end_vertex; (*lowpoint)[(*dfs_nbr)[cur]] = (*lowpoint)[(*dfs_nbr)[cur]] < (*lowpoint)[(*dfs_nbr)[next]] ? (*lowpoint)[(*dfs_nbr)[cur]] : (*lowpoint)[(*dfs_nbr)[next]]; cur_e = A[prev_e].next; } /* we proceed with DFS */ } } } mem_free(vertex_stack); mem_free(edge_stack); /* just for the sake of it, check that all vertices have been visited */ #ifdef ASSERTIONS for (v = 0; v < n; v++) { ASSERT(visited[v]); } #endif mem_free(visited); /* we now order the DFIs wrt lowpoint values: use bucket sort (linear time) */ /* for each lowpoint value, collect the DFIs (in a t_dlcl) with that lowpoint value (IMPORTANT: we want the DFIs since the aim is to rewrite dfs_tree which stores DFIs and not labels!) */ for (v = 0; v < n; v++) /* v is taken as a DFI here */ { t_dlcl *r; r = embedg_dlcl_rec_new(v); temp[(*lowpoint)[v]] = embedg_dlcl_rec_append(temp[(*lowpoint)[v]], r); } /* concatenate these lists now */ lowpoint_list = temp[0]; for (lp = 1; lp < n; lp++) { lowpoint_list = embedg_dlcl_cat(lowpoint_list, temp[lp]); } ASSERT(embedg_dlcl_length(lowpoint_list) == n); lowpoint_order[0] = lowpoint_list->info; for (lp = 1; lp < n; lp++) { lowpoint_list = embedg_dlcl_list_next(lowpoint_list); lowpoint_order[lp] = lowpoint_list->info; } embedg_dlcl_delete(lowpoint_list); mem_free(temp); IF_DEB( fprintf(stdout, "dfs_preprocessing, lowpoint_order\n"); for (lp = 0; lp < n; lp++) fprintf(stdout, "%d ", lowpoint_order[lp]); fprintf(stdout, "\n"); fprintf(stdout, "dfs_preprocessing, lowpoint\n"); for (lp = 0; lp < n; lp++) fprintf(stdout, "%d ", (*lowpoint)[lp]); fprintf(stdout, "\n"); ) /* we now use this order to rewrite dfs_tree such that the DFS children of each vertex are ordered wrt lowpoint values */ for (lp = 0; lp < n; lp ++) /* for each DFI in lowpoint_order[] I know its DFS_parent from dfs_parent[] -- the rest is then trivial */ { int parent; v = lowpoint_order[lp]; /* lowpoint_order stores DFIs as does dfs_parent, so the lot makes sense */ parent = (*dfs_parent)[v]; if (parent != n) /* v may be the root of a DFS tree */ { t_dlcl *temp; temp = embedg_dlcl_rec_new(v); /* this is where the TE_ holding arrays are useful *sigh* */ ASSERT(TE_in_adjl[v] != NIL); temp->in_adjl = TE_in_adjl[v]; ASSERT(TE_twin_in_adjl[v] != NIL); temp->twin_in_adjl = TE_twin_in_adjl[v]; ASSERT(TE_mult[v] != 0 && TE_mult[v] % 2 == 0); temp->mult = TE_mult[v]; new_dfs_tree[parent] = embedg_dlcl_rec_append(new_dfs_tree[parent], temp); } } mem_free(lowpoint_order); mem_free(TE_in_adjl); mem_free(TE_twin_in_adjl); mem_free(TE_mult); /* some checks are in order here */ #ifdef ASSERTIONS for (v = 0; v < n; v++) { ASSERT(embedg_dlcl_length((*dfs_tree)[v]) == embedg_dlcl_length(new_dfs_tree[v])); IF_DEB( fprintf(stdout, "dfs_preprocessing dfs_tree for %d\n", v); embedg_dlcl_print((*dfs_tree)[v]); fprintf(stdout, "dfs_preprocessing new_dfs_tree for %d\n", v); embedg_dlcl_print(new_dfs_tree[v]); ); } #endif sparseg_dlcl_delete(*dfs_tree, n); *dfs_tree = new_dfs_tree; } /* * embedding.c */ /* What: ***** Implementing: The graph is planar: we recover the embedding from the VES structure and check it as well. (Some of these checks will disappear later) ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_EMBED(x) {} #define IF_DEB_CHECK_EMBED(x) {} #define IF_DEB_FACES(x) {} #define IF_VERB(x) {} #define IF_DEB_SCE(x) {} #define IF_CPU(x) {} /* aproto: header embed_graph_protos.h */ #ifndef PLANAR_IN_MAGMA #endif void embedg_embedding (t_ver_sparse_rep *V, t_adjl_sparse_rep *A, t_ver_edge *embed_graph, int n, int e, int nbr_c, int edge_pos, t_dlcl **mult_edges, t_ver_sparse_rep **vertices, t_embed_sparse_rep **embedding) /* recovering the embedding for the (planar) graph - the embedding is returned in vertices and embedding, vertices indexes embedding, the ordered list of edges - edges in the embedding are given as their index in A, the graph's adajacency list - the nbr of edges in the embedding is given as nbr_e_embed: this may be different form the original number of edges when the graph iss not simple */ { int *ver_orient, nbr_comp, nbr_e_embed; IF_CPU( float sttime; float time_to_now; sttime = time_current_user(); ) IF_DEB( fprintf(stdout, "embedding, begin, which edges have been flipped\n"); embedg_VES_print_flipped_edges(embed_graph, n, edge_pos); ) IF_DEB( fprintf(stdout, "embedding, before removing SCE\n"); embedg_VES_print_bigcomps(embed_graph, n); ) /* several things to do: 1. removing the short-cut edges */ embedg_remove_SCE(embed_graph, n, edge_pos); IF_DEB( fprintf(stdout, "embedding, after removing SCE\n"); embedg_VES_print_bigcomps(embed_graph, n); ) /* 2. computing each vertex's orientation (wrt flipped bicomps) */ ver_orient = embedg_vertices_orientation(embed_graph, n); /* 3. merging the remaining virtual vertices with their non-virtual counterpart */ nbr_comp = embedg_merge_remaining_virtual(embed_graph, n); /* actually there is no need to return the nbr of components from the above function but let's do it for the sake of it and for possible checking */ ASSERT(nbr_c == nbr_comp); IF_DEB( fprintf(stdout, "embedding, after merging of remaining vertices\n"); ) /* 4. to be on the safe side: check that the embedding is a valid one for now, we DIE if not */ if (!embedg_is_embed_valid(embed_graph, n, nbr_comp, edge_pos, ver_orient, &nbr_e_embed)) { mem_free(ver_orient); DIE(); } mem_free(ver_orient); ASSERT(nbr_e_embed <= e); /* when the graph is not simple, multiple edges and loops are not in embed_graph[]: they will be added to the final embedding in embedg_recover_embedding below */ /* 5. recover the embedding in preparation for the Magma type, and check it as well */ embedg_recover_embedding(V, A, embed_graph, n, e, mult_edges, vertices, embedding); if (!embedg_check_recov_embedding(n, e, nbr_comp, *vertices, A, *embedding)) { mem_free(*vertices); mem_free(*embedding); IF_CPU( fprintf(stdout, "CPU for embedding recovering %f\n", time_current_user() - sttime); ) DIE(); } IF_DEB_EMBED( fprintf(stdout, "embedding, original graph and embedding\n"); sparseg_adjl_print(V, n, A, FALSE); fprintf(stdout, "\n"); sparseg_adjl_embed_print(*vertices, n, A, *embedding, FALSE); ) IF_CPU( fprintf(stdout, "CPU for embedding recovering %f\n", time_current_user() - sttime); ) } void embedg_remove_SCE (t_ver_edge *embed_graph, int n, int edge_pos) /* remove all the short-cut edges from the embedding */ { int i, c; c = 0; for (i = 2*n; i <= edge_pos; i += 2) /* and edge and its twin occupy consecutive positions in embed_graph: need only to examine one out of two (removing an edge also entails removing its twin of course */ { if (embedg_VES_is_short_cut_edge(embed_graph, n, i)) { IF_DEB_SCE( fprintf(stdout, "remove SCE\n"); embedg_VES_print_edge(embed_graph, n, i); ) embedg_VES_remove_edge(embed_graph, n, i); c++; } } IF_DEB_SCE( fprintf(stdout, "nbr of SCE edges removed %d\n", c); ) } int * embedg_vertices_orientation (t_ver_edge *embed_graph, int n) /* for each vertex return its orientation from the bicomps in embed_graph: perform a DFS of each bicomp */ { int i, vv, prod_sign; int *stack, *ver_orient, to_prev; /* the whole lot makes sense iff the adjacency lists are consistent: this is a very important issue and it might be the case that the ASSERT warrants replacement by a DIE (the check is linear - I think) */ ASSERT(embedg_VES_are_adj_lists_consistent(embed_graph, n)); ver_orient = (int *) mem_malloc(sizeof(int) * n); for (i = 0; i < n; i++) { ver_orient[i] = CCLOCKW; } /* create the stack for the DFS */ stack = (int *) mem_malloc(sizeof(int) * 3*n); to_prev = -1; IF_DEB( fprintf(stdout, "vertex orientation, one line (of vert.) for each bicomp\n"); ) /* now visit all the bicomps, ie, all the virtual vertices in embed_graph */ for (vv = n; vv < 2*n; vv++) { int c, cur, cur_e; boolean NEW_BICOMP; if (embed_graph[vv].link[0] == vv) /* means that vv is disabled and is not the root of a bicomp */ { continue; } c = vv - n; IF_DEB( fprintf(stdout, "%d ", c); ) /* orientation for c (vv is as yet unembedded) is CCLOCKW now find the orientation of all its DFS descendants */ if (embed_graph[c].DFS_parent == n) /* this means that actually c is an isolated vertex: we initialise the sign to CCLOCKW */ { prod_sign = CCLOCKW; } else /* we initialise the sign to CCLOCKW to the sign of c's parent */ { prod_sign = ver_orient[embed_graph[c].DFS_parent]; } /* we must not forget to set c's sign!! (won't be done below) */ ver_orient[c] = prod_sign; NEW_BICOMP = FALSE; cur = c; cur_e = embed_graph[cur].link[0]; ASSERT(embedg_VES_is_edge(n, cur_e)); ASSERT(to_prev == -1); while (TRUE) { while (!embedg_VES_is_tree_edge(embed_graph, n, cur_e) || !embedg_VES_is_vertex(n, embed_graph[cur_e].neighbour) || embed_graph[cur_e].neighbour <= cur) /* want to find a tree edge [cur, u] where u is a descendant of cur */ { cur_e = embed_graph[cur_e].link[0]; while (cur_e == cur) /* back to the vertex where we started from: no edge has been found: cur is a leaf, backtrack */ { if (to_prev == -1) { NEW_BICOMP = TRUE; break; } prod_sign = stack[to_prev--]; cur_e = stack[to_prev--]; /* must advance one more edge */ cur_e = embed_graph[cur_e].link[0]; cur = stack[to_prev--]; } if (NEW_BICOMP) { break; } } if (NEW_BICOMP) { break; } else /* now cur_e is the edge we were looking for, get its sign */ { /* push on stack the current vertex, the edge where we stopped the DFS, AND the sign carried by that vertex and go down one level in the DFS */ stack[++to_prev] = cur; stack[++to_prev] = cur_e; stack[++to_prev] = prod_sign; cur = embed_graph[cur_e].neighbour; prod_sign *= embed_graph[cur_e].sign; ver_orient[cur] = prod_sign; cur_e = embed_graph[cur].link[0]; ASSERT(embedg_VES_is_edge(n, cur_e)); IF_DEB( fprintf(stdout, "%d with sign %d\n", cur, prod_sign); ) } } IF_DEB( fprintf(stdout, "\n"); ) } IF_DEB( fprintf(stdout, "vertex orientation\n"); for (i = 0; i < n; i++) { fprintf(stdout, "%d ", ver_orient[i]); } fprintf(stdout, "\n"); ) mem_free(stack); return ver_orient; } int embedg_merge_remaining_virtual (t_ver_edge *embed_graph, int n) /* after the short-cut edges have been removed and the vertices' orientation computed, one finishes by merging all remaining virtual vertices with their virtual counterpart (without flip of course) and use this routine to return the number of disconnected components of the graph */ { /* at this stage it is easy to see that all remaining virtual vertices are DFS roots (if the graph is not connected) or cut vertices */ int vv, nbr_comp; nbr_comp = 0; for (vv = n; vv < 2*n; vv++) { int v, c; c = vv - n; v = embed_graph[c].DFS_parent; /* must fish out which virtual vertices are actual roots of DFS trees (esp. for the disconnected graph case): roots of DFS trees are those virtual vertices for which v = embed_graph[c].DFS_parent = n */ if (v == n) { nbr_comp++; continue; } if (embed_graph[vv].link[0] == vv) /* means that vv is disabled and is not the root of a bicomp */ { continue; } embedg_VES_merge_simple_bicomps(embed_graph, n, vv, 1, v, 0); /* note: since v is a cut vertex in this intance the bicomp rooted by vv will be merged without flip; therefore we could have done embedg_VES_merge_simple_bicomps(embed_graph, n, vv, 0, v, 1) as well, the important thing being that vin != vvout (see embedg_VES_merge_simple_bicomps) */ } return nbr_comp; } int embedg_nbr_faces (t_ver_edge *embed_graph, int n, int edge_pos, int *ver_orient, int *nbr_e_embed) /* count the number of faces and the number of edges of the embedding */ { int v, e, f, total_e; IF_DEB_FACES( int v; fprintf(stdout, "nbr of faces, the vertices' adj. lists\n"); for (v = 0; v < n; v++) embedg_VES_print_adj_list(embed_graph, n, v, TRUE); ) /* the following is no more than a quick check -- certainly not very useful -- or could be done elsewhere */ total_e = 0; for (e = 2*n; e <= edge_pos; e++) { if (!embedg_VES_is_short_cut_edge(embed_graph, n, e)) { total_e++; } } ASSERT(total_e % 2 == 0); *nbr_e_embed = total_e / 2; /* I now set each edge's orientation QUESTION: do I really need to do this??? so far, when doing a proper face traversal, the way in which the adjacency list of an edge must be traversed is given by the vertex's (in that list) orientation... So this seems sensible to me huh? */ embedg_VES_set_orientation(embed_graph, n, ver_orient); /* I will be using the visited field to enable me to check if all edges have been traversed let's be smart (?!): so far the visited field has been used and set in the following circumstances: + initialisation: set to n + walkup: set to whatever DFI of interest so here we set it to MARK_EMBED(n) */ f = 0; for (e = 2*n; e <= edge_pos; e++) { if (!embedg_VES_is_short_cut_edge(embed_graph, n, e) /* arrghh!!! I must also skip the SCE!!! */ && embed_graph[e].visited != MARK_EMBED(n)) { int ein; IF_DEB_FACES( fprintf(stdout, "nbr of faces, edges not visited\n"); embedg_VES_print_edge(embed_graph, n, e); ) ein = embed_graph[e].sign == CCLOCKW ? 0 : 1; /* the way I enter e in dependent on its sign: all the proper face traversal must obviously be done with the same orientation! */ embedg_VES_walk_proper_face(embed_graph, n, e, ein, TRUE, MARK_EMBED(n)); f++; } } /* counting the faces by traversing all the edges does not account of the face defined by isolated vertices -- we do that now we only need to check which vertices refer to self, ie with no incident edges */ for (v = 0; v < n; v++) { if (embed_graph[v].link[0] == v) { ASSERT(embed_graph[v].link[1] == v); f++; } } return f; } boolean embedg_is_embed_valid (t_ver_edge *embed_graph, int n, int nbr_comp, int edge_pos, int *ver_orient, int *nbr_e_embed) /* use Euler's formula to assertain that the embedding is a valid embedding: f = 2 * nbr_comp + nbr_e_embed - n */ { int v, f; f = embedg_nbr_faces(embed_graph, n, edge_pos, ver_orient, nbr_e_embed); IF_DEB_CHECK_EMBED( fprintf(stdout, "embedding, n: %d\t e: %d\t C: %d\t f: %d\n", n, nbr_e, nbr_comp, f); ) return f == 2 * nbr_comp + *nbr_e_embed - n ? TRUE : FALSE; } /* * ext_face_walk.c */ /* What: ***** Implementing the external face walk of a bicomponent. The concept of an external face --in the context of the VES data structure-- makes only sense when talking about a bicomp. Recall that a vertex is linked together with the edges incident from it in a circular (doubly) linked list (this is the VES structure). One particular feature is that if a vertex v is on the external face of a component and if in the list we have edges e1, e2 such as e1 -> v -> e2 then e1 and e2 border the external face. In other words, in the circular list of vertex v and edges, v is ALWAYS between the two edges bordering the external face Of course, when v is (maybe) pushed into the internal face (by embedding of some edge) then we don't care about this any more (for v that is). ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ void embedg_VES_get_succ_on_ext_face (t_ver_edge *embed_graph, int n, int v, int vin, boolean MARK, int mark, int *s, int *sin) /* find the successor s of v (entered via vin) on the external face -- also return the direction in which s has been entered if MARK true mark the succ. vertex and the edges traversed with mark (the visited field) */ { int e, twin; int vout, ein, eout, tout; ASSERT(embedg_VES_is_vertex(n, v) || embedg_VES_is_virtual_vertex(n, v)); IF_DEB( fprintf(stdout, "get_succ_on_ext_face, of %d:%d\n", v, vin); ) /* find the direction out of the vertex, and get the edge */ vout = vin == 0 ? 1 : 0; e = embed_graph[v].link[vout]; if (embedg_VES_is_virtual_vertex(n, v) && e == v) /* this can happen if a virtual vertex has been "disabled" -- this should not never happen since we can only walk on the external face of a bicomp! */ { *s = v; *sin = vin; return; } /* otherwise we must have an edge: note that it is entirely irrelevant if I walk SCEs: those are precisely there to "jump" over inactive vertices */ ASSERT(embedg_VES_is_edge(n, e)); /* get the twin edge */ twin = embedg_VES_get_twin_edge(embed_graph, n, e); IF_DEB( fprintf(stdout, "get_succ_on_ext_face, edge [%d, %d]\n", v, embed_graph[e].neighbour); fprintf(stdout, "get_succ_on_ext_face, twin edge [%d, %d]\n", embed_graph[e].neighbour, embed_graph[twin].neighbour); ) /* find which of twin's link links a vertex */ tout = embedg_VES_is_vertex(n, embed_graph[twin].link[0]) || embedg_VES_is_virtual_vertex(n, embed_graph[twin].link[0]) ? 0 : 1; /* get this vertex: this is v's successor on the external face */ *s = embed_graph[twin].link[tout]; /* one more thing to do: find the direction in which s was entered */ *sin = embed_graph[*s].link[0] == twin ? 0 : 1; IF_DEB( fprintf(stdout, "get_succ_on_ext_face, succ is %d:%d\n", *s, *sin); ) /* a special case: when the bicomp is a singleton bicomp (ie a single edge) */ if (embed_graph[*s].link[0] == (embed_graph[*s].link[1])) { ASSERT(embed_graph[*s].link[0] = twin); *sin = vin; } /* finally, mark the vertex and edges if so requested */ if (MARK) { embed_graph[*s].visited = mark; embed_graph[e].visited = mark; embed_graph[twin].visited = mark; } } void embedg_VES_get_succ_active_on_ext_face (t_ver_edge *embed_graph, int n, int v, int w, int win, boolean MARK, int mark, int *s, int *sin) /* find the ACTIVE (wrt v) successor s of w (entered via win) on the external face -- also return the direction in which s has been entered if MARK true mark the succ. vertex (and the edge) with mark (the visited field) */ { /* simply repeatedly calls embedg_VES_get_succ_on_ext_face until an active vertex is found */ ASSERT(embedg_VES_is_vertex(n, w) || embedg_VES_is_virtual_vertex(n, w)); embedg_VES_get_succ_on_ext_face(embed_graph, n, w, win, MARK, mark, s, sin); while (embedg_VES_is_ver_inactive(embed_graph, n, v, *s)) { embedg_VES_get_succ_on_ext_face(embed_graph, n, *s, *sin, MARK, mark, s, sin); } ASSERT(!embedg_VES_is_ver_inactive(embed_graph, n, v, *s)); } void embedg_VES_get_succ_ext_active_on_ext_face (t_ver_edge *embed_graph, int n, int v, int w, int win, boolean MARK, int mark, int *s, int *sin) /* find the externally active (wrt v) successor s of w (entered via win) on the external face -- also return the direction in which s has been entered if MARK true mark the succ. vertex (and the edge) with mark (the visited field) */ { ASSERT(embedg_VES_is_vertex(n, w) || embedg_VES_is_virtual_vertex(n, w)); embedg_VES_get_succ_on_ext_face(embed_graph, n, w, win, MARK, mark, s, sin); while (!embedg_VES_is_ver_ext_active(embed_graph, n, v, *s)) { embedg_VES_get_succ_on_ext_face(embed_graph, n, *s, *sin, MARK, mark, s, sin); } ASSERT(embedg_VES_is_ver_ext_active(embed_graph, n, v, *s)); } void embedg_VES_get_succ_pertinent_on_ext_face (t_ver_edge *embed_graph, int n, int v, int w, int win, boolean MARK, int mark, int *s, int *sin) /* find the pertinent (wrt v) successor s of w (entered via win) on the external face -- also return the direction in which s has been entered if MARK true mark the succ. vertex (and the edge) with mark (the visited field) */ { ASSERT(embedg_VES_is_vertex(n, w) || embedg_VES_is_virtual_vertex(n, w)); embedg_VES_get_succ_on_ext_face(embed_graph, n, w, win, MARK, mark, s, sin); while (!embedg_VES_is_ver_pertinent(embed_graph, n, v, *s)) { embedg_VES_get_succ_on_ext_face(embed_graph, n, *s, *sin, MARK, mark, s, sin); } ASSERT(embedg_VES_is_ver_pertinent(embed_graph, n, v, *s)); } /* * mark_kur.c */ /* What: ***** Implementing: Marking the Kuratowski obstruction (in the VES structure): this we do once we know which minor we are talking about (see isolator.c). ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_VERB(x) {} #define IF_DEB_TREE(x) {} #define IF_DEB_EDGES(x) {} #define IF_CPU(x) {} /* aproto: header embed_graph_protos.h */ /* aproto: beginstatic -- don't touch this!! */ static void embedg_VES_walk_mark_part_ext_face (t_ver_edge *, int, int, int, int, int, int); static void embedg_VES_walk_mark_ext_face (t_ver_edge *, int, int, int); static void embedg_VES_walk_mark_part_proper_face (t_ver_edge *, int, int, int, int, int); static boolean embedg_VES_is_part_ext_face_marked (t_ver_edge *, int, int, int, int, int, int); static void embedg_get_u_x (t_ver_edge *, int, int, int, int *); static int embedg_get_least_neigh (t_dlcl **, t_dlcl **, int, int, int); static void embedg_add_mark_u_x (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int *, int); static void embedg_mark_tree_path (t_ver_edge *, int, int, int, int); static void embedg_add_mark_v_w (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int); static void embedg_add_mark_v_w_for_B (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int *, int); static void embedg_mark_x_y_path (t_ver_edge *, int, int *, int *, int, int); /* aproto: endstatic -- don't touch this!! */ #ifndef PLANAR_IN_MAGMA #endif static void embedg_VES_walk_mark_part_ext_face (t_ver_edge *embed_graph, int n, int v, int vin, int from, int to, int mark) /* walk & mark the external face: walk in the direction vin -> v -> vout and mark */ { int cur, curin, next, nextin; embed_graph[from].visited = mark; embed_graph[to].visited = mark; IF_DEB( fprintf(stdout, "part. ext face marked\t"); fprintf(stdout, "%d\t", from); ) next = cur = v; curin = vin; while (next != from) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &next, &nextin); cur = next; curin = nextin; } next = n; while (next != to) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, TRUE, mark, &next, &nextin); cur = next; curin = nextin; IF_DEB( fprintf(stdout, "%d\t", next); ) } IF_DEB( fprintf(stdout, "\n"); ) } static void embedg_VES_walk_mark_ext_face (t_ver_edge *embed_graph, int n, int v, int mark) /* walk & mark the external face, starting & ending at vertex v */ { embedg_VES_walk_mark_part_ext_face(embed_graph, n, v, 0, v, v, mark); } static void embedg_VES_walk_mark_part_proper_face (t_ver_edge *embed_graph, int n, int from_e, int from_ein, int to, int mark) /* walk & mark a proper face starting at EDGE from_e and ending at VERTEX to walk in the direction from_ein -> from_e -> to and mark everything in between */ { int s, cur_e, cur_ein, next_e, next_ein; next_e = s = n; /* this is an invalid value for an edge/vertex */ cur_e = from_e; cur_ein = from_ein; while (s != to) { ASSERT(embedg_VES_is_edge(n, cur_e)); ASSERT(!embedg_VES_is_short_cut_edge(embed_graph, n, cur_e)); embedg_VES_get_succ_on_proper_face(embed_graph, n, cur_e, cur_ein, TRUE, mark, &s, &next_e, &next_ein); cur_e = next_e; cur_ein = next_ein; } } static boolean embedg_VES_is_part_ext_face_marked (t_ver_edge *embed_graph, int n, int v, int vin, int from, int to, int mark) /* simple check to see if all the vertices on the external face walk starting at vin -> v -> vout are marked (with mark) */ { int cur, curin, next, nextin; if (embed_graph[from].visited != mark || embed_graph[to].visited != mark) return FALSE; cur = v; curin = vin; next = n; while (next != from) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &next, &nextin); cur = next; curin = nextin; } while (next != to) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &next, &nextin); if (embed_graph[next].visited != mark) return FALSE; cur = next; curin = nextin; } return TRUE; } boolean embedg_VES_is_ext_face_marked (t_ver_edge *embed_graph, int n, int v, int mark) /* simple check to see if all the vertices on the external face walk starting/ending at v are marked (with mark) */ { return embedg_VES_is_part_ext_face_marked(embed_graph, n, v, 0, v, v, mark); } static void embedg_get_u_x (t_ver_edge *embed_graph, int n, int v, int x, int *u_x) /* x is an externally active vertex (wrt v): we want u_x, the lowest point of "attachement" for the unembedded directed edge [x, u_x] */ { int c; t_dlcl *child_list; ASSERT(embedg_VES_is_ver_ext_active(embed_graph, n, v, x)); if (embed_graph[x].least_ancestor < v) /* then there is a single unembedded back edge (u_x, x), u_x an ancestor of v */ { *u_x = embed_graph[x].least_ancestor; return; } /* else there is a tree path x to d_x and an unembedded back edge (u_x, d_x) get the lowpoint of the first elt. in separated_DFS_child_list of x */ child_list = embed_graph[x].separated_DFS_child_list; ASSERT(!embedg_dlcl_is_empty(child_list)); c = child_list->info; *u_x = embed_graph[c].lowpoint; } static int embedg_get_least_neigh (t_dlcl **dfs_tree, t_dlcl **back_edges, int n, int v, int c) /* get the least neighbour of v >= c, ie a vertex in the sub tree rooted by c somehow this must always succeed */ { int least_n; t_dlcl *tree_l, *back_l, *p; /* neighbours are found in either dfs_tree[v] or back_edges[v] */ tree_l = dfs_tree[v]; back_l = back_edges[v]; ASSERT(!embedg_dlcl_is_empty(tree_l) || !embedg_dlcl_is_empty(back_l)); least_n = n; /* ok, invalid value for any neighbour */ p = tree_l; if (!embedg_dlcl_is_empty(p)) { if (p->info >= c) { least_n = p->info < least_n ? p->info : least_n; } p = embedg_dlcl_list_next(p); while (p != tree_l) { if (p->info >= c) { least_n = p->info < least_n ? p->info : least_n; } p = embedg_dlcl_list_next(p); } } p = back_l; if (!embedg_dlcl_is_empty(p)) { if (p->info >= c) { least_n = p->info < least_n ? p->info : least_n; } p = embedg_dlcl_list_next(p); while (p != back_l) { if (p->info >= c) { least_n = p->info < least_n ? p->info : least_n; } p = embedg_dlcl_list_next(p); } } ASSERT(least_n >= c); /* this is so because of the context where this function is called from */ return least_n; } static void embedg_add_mark_u_x (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int x, int *u_x, int mark) /* marking a Kuratowski homeomorph: marking and adding the unembedded dotted edge (u, x), x an ext. active vertex wrt v */ { int c, d_x; t_dlcl *child_list; ASSERT(embedg_VES_is_ver_ext_active(embed_graph, n, v, x)); if (embed_graph[x].least_ancestor < v) /* then there is a single unembedded back edge (u_x, x), u_x an ancestor of v */ { *u_x = embed_graph[x].least_ancestor; embed_graph[x].visited = mark; embed_graph[*u_x].visited = mark; embedg_VES_add_edge(embed_graph, n, edge_pos, *u_x, x, TRUE, mark); return; } /* else there is a tree path x to d_x and an unembedded back edge (u_x, d_x) get the lowpoint of the first elt. in separated_DFS_child_list of x */ child_list = embed_graph[x].separated_DFS_child_list; ASSERT(!embedg_dlcl_is_empty(child_list)); c = child_list->info; *u_x = embed_graph[c].lowpoint; /* search for the least neighbour of *u_x >= c, that is in the subtree rooted by c */ d_x = embedg_get_least_neigh(dfs_tree, back_edges, n, *u_x, c); ASSERT(d_x >= c); /* this must be true since u_x is incident to a descendant of x (remember: x is externally active) */ /* mark the DFS tree path from d_x to x */ embedg_mark_tree_path(embed_graph, n, d_x, x, mark); /* add the unembedded (u_x, d_x) edge */ embedg_VES_add_edge(embed_graph, n, edge_pos, *u_x, d_x, TRUE, mark); } static void embedg_mark_tree_path (t_ver_edge *embed_graph, int n, int d_x, int x, int mark) /* marking the DFS tree path d_x...x where x is an ancestor of d_x */ { int cur_v, te, twe; ASSERT(d_x >= x); cur_v = d_x; while (cur_v != x) { embed_graph[cur_v].visited = mark; te = embed_graph[cur_v].link[0]; ASSERT(embedg_VES_is_edge(n, te)); while (!embedg_VES_is_tree_edge(embed_graph, n, te) || (embed_graph[te].neighbour > cur_v && embed_graph[te].neighbour != cur_v + n)) /* want to find a tree edge incident to an ancestor of d_x: given that d_x..x is a tree path, we MUST find such an edge! note also that I must take account of the fact that [te].neighbour could be a virtual vertex, in which case it can only be cur_v + n! */ { te = embed_graph[te].link[0]; } ASSERT(embedg_VES_is_tree_edge(embed_graph, n, te)); ASSERT(embed_graph[te].neighbour == embed_graph[cur_v].DFS_parent || embed_graph[te].neighbour == cur_v + n); embed_graph[te].visited = mark; twe = embedg_VES_get_twin_edge(embed_graph, n, te); embed_graph[twe].visited = mark; /* want only to deal with real vertices instead of virtual vertices */ cur_v = embed_graph[te].neighbour < cur_v ? embed_graph[te].neighbour : embed_graph[cur_v].DFS_parent; } embed_graph[x].visited = MARK_MINORS(n); } static void embedg_add_mark_v_w (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int w, int mark) /* marking a Kuratowski homeomorph: marking and adding the unembedded dotted edge (v, w), w is pertinent wrt v */ { int vw, c, d_w; t_dlcl *bicomp_list; if (embed_graph[w].adjacent_to == v) /* then there is a single unembedded back edge (v, w) w an ancestor of w */ { embed_graph[v].visited = mark; embed_graph[w].visited = mark; embedg_VES_add_edge(embed_graph, n, edge_pos, v, w, TRUE, mark); return; } /* else there is a tree path w to d_w and an unembedded back edge (v, d_w) get the last elt in w's bicomp list */ bicomp_list = embed_graph[w].pertinent_bicomp_list; ASSERT(!embedg_dlcl_is_empty(bicomp_list)); vw = (embedg_dlcl_list_last(bicomp_list))->info; c = vw - n; /* search for the least neighbour of v >= c, that is in the subtree rooted by c */ d_w = embedg_get_least_neigh(dfs_tree, back_edges, n, v, c); ASSERT(d_w >= c); /* this must be true since v is incident to a descendant of w (remember: w is pertinent) */ /* mark the DFS tree path from d_w to w */ embedg_mark_tree_path(embed_graph, n, d_w, w, mark); /* add the unembedded (d_w, v) edge */ embedg_VES_add_edge(embed_graph, n, edge_pos, d_w, v, TRUE, mark); } static void embedg_add_mark_v_w_for_B (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int w, int *u_z, int mark) /* marking a Kuratowski homeomorph: marking and adding the unembedded dotted edge (v, w) for minor B: w is pertinent wrt v */ { int vz, z, d_z, d_w; t_dlcl *bicomp_list; /* get the last elt in w's bicomp list */ bicomp_list = embed_graph[w].pertinent_bicomp_list; ASSERT(!embedg_dlcl_is_empty(bicomp_list)); vz = (embedg_dlcl_list_last(bicomp_list))->info; z = vz - n; /* get the lowpoint of z */ *u_z = embed_graph[z].lowpoint; /* search for the least neighbour of *u_z >= z, that is in the subtree rooted by c */ d_z = embedg_get_least_neigh(dfs_tree, back_edges, n, *u_z, z); ASSERT(d_z >= z); /* this must be true since u_z is incident to z or a descendant of z */ /* now do the same for neighbours of v */ d_w = embedg_get_least_neigh(dfs_tree, back_edges, n, v, z); ASSERT(d_w >= z); /* this must be true since v is incident to a descendant of w (remember: w is pertinent) */ /* mark the DFS tree path from d_w to w */ embedg_mark_tree_path(embed_graph, n, d_w, w, mark); /* mark the DFS tree path from d_z to z */ embedg_mark_tree_path(embed_graph, n, d_z, z, mark); /* add & mark the edges (u_z, d_z), (v, d_w) */ embedg_VES_add_edge(embed_graph, n, edge_pos, *u_z, d_z, TRUE, mark); embedg_VES_add_edge(embed_graph, n, edge_pos, v, d_w, TRUE, mark); } static void embedg_mark_x_y_path (t_ver_edge *embed_graph, int n, int *path_v, int *path_e, int nbr_v, int mark) { int i; /* have a look at embedg_iso_get_highest_x_y_path to see that path_e[0] is a dummy (note: path_v and path_e contain nbr_v + 1 elts!) */ embed_graph[path_v[0]].visited = mark; for (i = 1; i <= nbr_v; i++) { int e, twin; embed_graph[path_v[i]].visited = mark; e = path_e[i]; twin = embedg_VES_get_twin_edge(embed_graph, n, e); embed_graph[e].visited = embed_graph[twin].visited = mark; } } void embedg_mark_minor_A (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int vr) { int r, r_c, x, y, w, u_x, u_y, u; ASSERT(embedg_VES_is_virtual_vertex(n, vr)); r_c = vr - n; r = embed_graph[r_c].DFS_parent; /* find the ext. active x & y, and the pertinent w, and mark the external face of the bicomp rooted at vr */ embedg_iso_get_x_y_w(embed_graph, n, v, r, r_c, MARK_MINORS(n), MARK_MINORS(n), MARK_MINORS(n), &x, &y, &w); /* mark the edges (u, x), (u, y), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); /* mark the tree path from r to min(u_x, u_y) */ u = u_x <= u_y ? u_x : u_y; embedg_mark_tree_path(embed_graph, n, r, u, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor A\n"); fprintf(stdout, "v %d\t c %d\t r %d\t r_c %d\t x %d\t y %d\t w %d\t u_x %d\t u_y %d\n", v, c, r, r_c, x, y, w, u_x, u_y); ) } void embedg_mark_minor_B (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w) { int vv, u_x, u_y, vz, u_z, u_max, u_min; vv = c + n; /* mark the external face of the bicomp rooted by v^c */ embedg_VES_walk_mark_ext_face(embed_graph, n, vv, MARK_MINORS(n)); ASSERT(embedg_VES_is_ext_face_marked(embed_graph, n, vv, MARK_MINORS(n))); /* mark the edges (u, x), (u, y) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); /* mark the dotted edges (v, w), (v, u) */ embedg_add_mark_v_w_for_B(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, &u_z, MARK_MINORS(n)); /* mark the tree path from max(u_x, u_y, u_z) to min(u_x, u_y, u_z) */ u_max = u_x > u_y ? u_x : u_y; u_max = u_max > u_z ? u_max : u_z; u_min = u_x < u_y ? u_x : u_y; u_min = u_min < u_z ? u_min : u_z; embedg_mark_tree_path(embed_graph, n, u_max, u_min, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor B\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t u_x %d\t u_y %d\t u_z %d\n", v, c, x, y, w, u_x, u_y, u_z); ) } void embedg_mark_minor_C (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w, int *path_v, int *path_e, int nbr_v, boolean px_attached_high, boolean py_attached_high) { int vv, p_x, p_y, u_x, u_y, u; vv = c + n; p_x = path_v[0]; p_y = path_v[nbr_v]; /* see embedg_iso_get_highest_x_y_path for the above */ if (px_attached_high) /* mark the external face: - from v^c to p_y if py_attached_high - from v^c to y if !py_attached_high not too sure about that one.... from v^c to p_y: so vvin = 0, in x's direction */ { if (py_attached_high) embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, vv, p_y, MARK_MINORS(n)); else embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, vv, y, MARK_MINORS(n)); } else /* symmetric case: mark the external face from v^c to p_x: so vvin = 1, in y's direction */ { if (px_attached_high) embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1, vv, p_x, MARK_MINORS(n)); else embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1, vv, x, MARK_MINORS(n)); } /* mark the edges (u, x), (u, y), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); /* mark the tree path from v to min(u_x, u_y) */ u = u_x <= u_y ? u_x : u_y; embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n)); /* finally, mark the x-y path, ie the vertices in path_v and the edges in path_e */ embedg_mark_x_y_path(embed_graph, n, path_v, path_e, nbr_v, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor C p_x high %d\t p_y high %d\n", px_attached_high, py_attached_high); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y); ) } void embedg_mark_minor_D (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w, int *path_v, int *path_e, int nbr_v, int entry_in_path_e) { int i, vv, p_x, p_y, u_x, u_y, u; vv = c + n; p_x = path_v[0]; p_y = path_v[nbr_v]; /* see embedg_iso_get_highest_x_y_path for the above */ /* mark the lower external face from x to y: we can walk in either direction */ embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, x, y, MARK_MINORS(n)); /* mark the internal path which goes from the x-y path to v - since I haven't stored those vertices/edges I assume that a proper face walk should suffice BUT a walk that say starts at p_x and ends at vv, that is, a walk starting at path_e[1] entered from entry_in_path_e (recall that path_e[0] is a dummy) */ embedg_VES_walk_mark_part_proper_face(embed_graph, n, path_e[1], entry_in_path_e, vv, MARK_MINORS(n)); /* a note of caution here: ALWAYS mark external/internal faces before adding any other edges: since adding edges destroys the faces' consistency (adding edges makes no sense of face since we are in a non-planar situation) */ /* mark the edges (u, x), (u, y), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); /* mark the tree path from v to min(u_x, u_y) */ u = u_x <= u_y ? u_x : u_y; embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n)); /* mark the x-y path, ie the vertices in path_v and the edges in path_e */ embedg_mark_x_y_path(embed_graph, n, path_v, path_e, nbr_v, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor D\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y); ) } minor embedg_mark_minor_E (t_dlcl **dfs_tree, t_dlcl **back_edges, t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w, int *path_v, int *path_e, int nbr_v) /* while marking minor E return which of the minors we are dealing with */ { int vv, p_x, p_y, u_x, u_y, u_w, u, u_max, u_min; vv = c + n; p_x = path_v[0]; p_y = path_v[nbr_v]; /* see embedg_iso_get_highest_x_y_path for the above */ if (!embedg_VES_is_ver_ext_active(embed_graph, n, v, w)) /* minor E1 case: we must find an ext. active z, distinct from w, on the external face p_x..w..p_y */ { int s, sin, cur, curin, z, u_z, u_xy; s = n; /* start searching at vv entered from 0 (in x's direction) -- we MUST reach p_x - hopefully! :) */ cur = vv; curin = 0; while (s != p_x) /* first advance to p_x: we are sure of reaching it */ { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &s, &sin); cur = s; curin = sin; } /* continue the walk on the external face: stop if either s is ext. active OR s == w we'll mark the lot later on */ while ( !(embedg_VES_is_ver_ext_active(embed_graph, n, v, s) && s != p_x) && s != w) { embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &s, &sin); cur = s; curin = sin; } /* now we must decide which symmetry we are in */ if (embedg_VES_is_ver_ext_active(embed_graph, n, v, s)) /* z is between x and w (recall that w is NOT ext. active) */ { z = s; ASSERT(z != w); /* mark the external face from v^c to y in x's direction */ embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, vv, y, MARK_MINORS(n)); /* add/mark dotted edge (u, y) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_xy, MARK_MINORS(n)); } else /* this is the symmetric case: must find z between w and p_y */ { ASSERT(s == w); embedg_VES_get_succ_ext_active_on_ext_face(embed_graph, n, v, cur, curin, FALSE, 0, &s, &sin); /* and z is distinct from p_y! */ z = s; ASSERT(z != p_y); /* mark the external face from v^c to x in y's direction */ embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1, vv, x, MARK_MINORS(n)); /* add/mark dotted edge (u, x) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_xy, MARK_MINORS(n)); } /* now the marked bits which are common to both cases: dotted edges (u, z), (v, w), the x-y path, the tree path (v, min(u_xy, u_z)) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, z, &u_z, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); embedg_mark_x_y_path(embed_graph, n, path_v, path_e, nbr_v, MARK_MINORS(n)); u = u_z <= u_xy ? u_z : u_xy; embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor E1\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t z %d\t w %d\t p_x %d\t p_y %d\t u_xy %d\t u_z %d\n", v, c, x, y, z, w, p_x, p_y, u_xy, u_z); ) return MINOR_E1; } /* in all other cases we get u_x, u_y, u_w back from the ext. active vertices x, y, w resp. again, I CANNOT embed these edges now since that would destroy my external/internal faces */ embedg_get_u_x(embed_graph, n, v, x, &u_x); embedg_get_u_x(embed_graph, n, v, y, &u_y); embedg_get_u_x(embed_graph, n, v, w, &u_w); if (u_w > u_x && u_w > u_y) /* minor E2 case: we mark the whole external face rooted by v^c and the tree path (v, min(u_x, u_y)) */ { embedg_VES_walk_mark_ext_face(embed_graph, n, vv, MARK_MINORS(n)); u = u_x <= u_y ? u_x : u_y; embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n)); /* embed dotted edges (u, x), (u, y) & (u, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, &u_w, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor E2\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\t u_w %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y, u_w); ) return MINOR_E2; } /* two more things common to all remaining cases: mark the dotted edge (v, w) (but we MUST do that later) mark the x-y path */ embedg_mark_x_y_path(embed_graph, n, path_v, path_e, nbr_v, MARK_MINORS(n)); if (u_x < u_y && u_w < u_y) /* minor E3 case: one of the symmetric cases: the external face rooted at v_c from vv to x (in x's direction) the external face rooted at v_c from y to w (in y's direction) the (v, min(u_w, u_x)) tree path */ { embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, vv, p_x, MARK_MINORS(n)); embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1, y, w, MARK_MINORS(n)); u = u_x <= u_w ? u_x : u_w; embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n)); /* embed dotted edges (u, x), (u, y), (u, w), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, &u_w, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor E3/a\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\t u_w %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y, u_w); ) return MINOR_E3; } if (u_y < u_x && u_w < u_x) /* minor E3 case: the other symmetric case: the external face rooted at v_c from vv to y (in y's direction) the external face rooted at v_c from x to w (in x's direction) the (v, min(u_w, u_y)) tree path */ { embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1, vv, p_y, MARK_MINORS(n)); embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, x, w, MARK_MINORS(n)); u = u_y <= u_w ? u_y : u_w; embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n)); /* embed dotted edges (u, x), (u, y), (u, w), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, &u_w, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor E3/b\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\t u_w %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y, u_w); ) return MINOR_E3; } if (p_x != x) /* minor E4 case: one of the symmetric cases: the external face rooted at v_c from vv to w (in x's direction) the external face rooted at v_c from vv to p_y (in y's direction) the tree path from max(u_x, u_y, u_w) to min(u_x, u_y, u_w) */ { embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, vv, w, MARK_MINORS(n)); embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1, vv, p_y, MARK_MINORS(n)); u_max = u_x > u_y ? u_x : u_y; u_max = u_max > u_w ? u_max : u_w; u_min = u_x < u_y ? u_x : u_y; u_min = u_min < u_w ? u_min : u_w; embedg_mark_tree_path(embed_graph, n, u_max, u_min, MARK_MINORS(n)); /* embed dotted edges (u, x), (u, y), (u, w), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, &u_w, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor E4/a\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\t u_w %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y, u_w); ) return MINOR_E4; } if (p_y != y) /* minor E4 case: the other symmetric case: the external face rooted at v_c from vv to w (in y's direction) the external face rooted at v_c from vv to x (in x's direction) (here p_x = x!) the tree path from max(u_x, u_y, u_w) to min(u_x, u_y, u_w) */ { embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1, vv, w, MARK_MINORS(n)); embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0, vv, x, MARK_MINORS(n)); u_max = u_x > u_y ? u_x : u_y; u_max = u_max > u_w ? u_max : u_w; u_min = u_x < u_y ? u_x : u_y; u_min = u_min < u_w ? u_min : u_w; embedg_mark_tree_path(embed_graph, n, u_max, u_min, MARK_MINORS(n)); /* embed dotted edges (u, x), (u, y), (u, w), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, &u_w, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor E$/b\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\t u_w %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y, u_w); ) return MINOR_E4; } /* this is the last case for minor E: when the homeomorph is K5 mark the whole external face rooted at v^c mark the tree path from v to min(u_x, u_y, u_w) */ embedg_VES_walk_mark_ext_face(embed_graph, n, vv, MARK_MINORS(n)); u = u_x < u_y ? u_x : u_y; u = u < u_w ? u : u_w; embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n)); /* embed dotted edges (u, x), (u, y), (u, w), (v, w) */ embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, x, &u_x, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, y, &u_y, MARK_MINORS(n)); embedg_add_mark_u_x(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, &u_w, MARK_MINORS(n)); embedg_add_mark_v_w(dfs_tree, back_edges, embed_graph, n, edge_pos, v, w, MARK_MINORS(n)); IF_DEB( fprintf(stdout, "mark minor E5\n"); fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\t u_w %d\n", v, c, x, y, w, p_x, p_y, u_x, u_y, u_w); ) return MINOR_E5; } /* * proper_face_walk.c */ /* What: ***** Implementing a proper face walk within the VES structure. This is obviously not the same as an external face walk, but is simply the standard face walk in a planar embedding. Not much to say, if only to emphasize that for our purposes here we assume: 1. the short-cut edges have been removed from the VES structure 2. each vertex/edge has been given its orientation 2. the adjacency lists (vertex + plus its incident edges) are consistent: (and this is IMPORTANT) that is, the way to traverse an adj. list (ie what constitute previous and next in the list which actually is a planar embedding at this stage) is indicated by the vertex/edge's orientation try to explain this better another time.... sorry... ++++++++++++++++++++++++++++++++++++++++++++++++++++++ from Simplified O(n) Planarity Algorithms (draft) ************************************ John Boyer JBoyer@PureEdge.com, jboyer@acm.org Wendy Myrvold wendym@csr.uvic.ca ++++++++++++++++++++++++++++++++++++++++++++++++++++++ authors: ******** Paulette Lieby (Magma), Brendan McKay (ANU) Started October 2001 */ #include "planarity.h" #define IF_DEB(x) {} #define IF_DEB_PROPER_FACE(x) {} #define IF_VERB(x) {} /* aproto: header embed_graph_protos.h */ boolean embedg_VES_get_succ_on_proper_face_with_avoidance (t_ver_edge *embed_graph, int n, int e, int ein, int a, boolean MARK, int mark, int *s, int *next_e, int *next_ein) /* find the successor s of embed_graph[e].neighbour (entered via ein) on a proper face traversal which avoids (the vertex) a if a != n also returns the edge next_e such that embed_graph[next_e].neighbour = s (to allow for continuation of the walk) assumes that short-cut edges have been removed and that each edge/vertex has been given its orientation and (more importantly) assumes that adjacency lists are consistent this function has been written especially to retrieve the highest x-y path for the isolator; (see embedg_iso_get_highest_x_y_path) but as I discovered later (when marking an internal face as for minor D) this function is general purpose PLUS: return true if the proper face walk has to skip an edge incident to a (ie had to "avoid" a) PLUS: mark s & next_e if so requested */ { int eout; int twin, twinout; boolean avoid_a; ASSERT(embedg_VES_is_edge(n, e)); ASSERT(!embedg_VES_is_short_cut_edge(embed_graph, n, e)); IF_DEB( fprintf(stdout, "get_succ_on_proper_face, \n"); ) avoid_a = FALSE; /* find the direction out of the edge */ eout = 1 ^ ein; /* get the twin edge */ twin = embedg_VES_get_twin_edge(embed_graph, n, e); /* for each edge we must set the way to get to the next in the adjacency list: adjacency lists are traversed according to the vertex/edges orientation (one unique orientation per list of course) */ if (embed_graph[e].sign != embed_graph[twin].sign) /* invert traversal */ { twinout = 1 ^ eout; } else /* traversal is identical */ { twinout = eout; } /* now, we want the edge previous to twin in twin's adjacency list, ie link[1 ^ twinout] */ *next_e = embed_graph[twin].link[1 ^ twinout]; /* next_e could be a vertex, I need an edge */ if (embedg_VES_is_vertex(n, *next_e) || embedg_VES_is_virtual_vertex(n, *next_e)) /* at this stage all virtual vertices should have been disabled BUT the vertices rooting the bicomps!!! */ { *next_e = embed_graph[*next_e].link[1 ^ twinout]; } ASSERT(embedg_VES_is_edge(n, *next_e)); ASSERT(!embedg_VES_is_short_cut_edge(embed_graph, n, e)); *s = embed_graph[*next_e].neighbour; if (*s == a) /* want to avoid this vertex, so must get yet previous edge in adjacency list */ { avoid_a = TRUE; *next_e = embed_graph[*next_e].link[1 ^ twinout]; if (embedg_VES_is_vertex(n, *next_e) || embedg_VES_is_virtual_vertex(n, *next_e)) { *next_e = embed_graph[*next_e].link[1 ^ twinout]; } ASSERT(embedg_VES_is_edge(n, *next_e)); ASSERT(!embedg_VES_is_short_cut_edge(embed_graph, n, e)); } *s = embed_graph[*next_e].neighbour; ASSERT(*s != a); /* finally (again, because lists are consistent) */ *next_ein = 1 ^ twinout; /* now mark s and next_e if required */ if (MARK) { embed_graph[*s].visited = embed_graph[*next_e].visited = mark; /* ouuh... must mark the twin as well.... but ONLY when we mark the minors.... that is poor design, can we do better???? -- don't think so... (when we mark when counting the faces, we MUST only mark the edge and NOT its twin) */ if (mark == MARK_MINORS(n)) { twin = embedg_VES_get_twin_edge(embed_graph, n, *next_e); embed_graph[twin].visited = mark; } } return avoid_a; } void embedg_VES_get_succ_on_proper_face (t_ver_edge *embed_graph, int n, int e, int ein, int MARK, int mark, int *s, int *next_e, int *next_ein) /* same as above but without avoidance */ { boolean avoid; avoid = embedg_VES_get_succ_on_proper_face_with_avoidance( embed_graph, n, e, ein, n, MARK, mark, s, next_e, next_ein); ASSERT(avoid == FALSE); } void embedg_VES_walk_proper_face (t_ver_edge *embed_graph, int n, int e, int ein, boolean MARK, int mark) /* traversing a proper face starting at edge e which has been entered via ein -- we mark the visited edges with mark if so requested assumes that short-cut edges have been removed and that each edge/vertex has been given its orientation */ { int s, cur_e, cur_ein, next_e, next_ein; next_e = n; /* this is an invalid value for an edge */ IF_DEB_PROPER_FACE( fprintf(stdout, "proper face traversal\n"); ) cur_e = e; cur_ein = ein; while (next_e != e) { ASSERT(embedg_VES_is_edge(n, cur_e)); ASSERT(!embedg_VES_is_short_cut_edge(embed_graph, n, cur_e)); IF_DEB_PROPER_FACE( embedg_VES_print_edge(embed_graph, n, cur_e); ) embedg_VES_get_succ_on_proper_face(embed_graph, n, cur_e, cur_ein, MARK, mark, &s, &next_e, &next_ein); cur_e = next_e; cur_ein = next_ein; } /* note that by doing so we would have marked e and the first of e's endpoints since by exiting the loop e = next_e and s is the actual starting vertex of the walk */ } nauty24r2/testL.dre0000600000604200001440000000605211274163463013101 0ustar bdmusers! tests for 33-64 vertices n=33 $=0 g 0 : 10 11 12 14 15 16 17 18 19 21 22 23; 1 : 11 12 13 15 16 17 18 19 20 22 23 24; 2 : 12 13 14 16 17 18 19 20 21 23 24 25; 3 : 13 14 15 17 18 19 20 21 22 24 25 26; 4 : 14 15 16 18 19 20 21 22 23 25 26 27; 5 : 15 16 17 19 20 21 22 23 24 26 27 28; 6 : 16 17 18 20 21 22 23 24 25 27 28 29; 7 : 17 18 19 21 22 23 24 25 26 28 29 30; 8 : 18 19 20 22 23 24 25 26 27 29 30 31; 9 : 19 20 21 23 24 25 26 27 28 30 31 32; 10 : 0 20 21 22 24 25 26 27 28 29 31 32; 11 : 0 1 21 22 23 25 26 27 28 29 30 32; 12 : 0 1 2 22 23 24 26 27 28 29 30 31; 13 : 1 2 3 23 24 25 27 28 29 30 31 32; 14 : 0 2 3 4 24 25 26 28 29 30 31 32; 15 : 0 1 3 4 5 25 26 27 29 30 31 32; 16 : 0 1 2 4 5 6 26 27 28 30 31 32; 17 : 0 1 2 3 5 6 7 27 28 29 31 32; 18 : 0 1 2 3 4 6 7 8 28 29 30 32; 19 : 0 1 2 3 4 5 7 8 9 29 30 31; 20 : 1 2 3 4 5 6 8 9 10 30 31 32; 21 : 0 2 3 4 5 6 7 9 10 11 31 32; 22 : 0 1 3 4 5 6 7 8 10 11 12 32; 23 : 0 1 2 4 5 6 7 8 9 11 12 13; 24 : 1 2 3 5 6 7 8 9 10 12 13 14; 25 : 2 3 4 6 7 8 9 10 11 13 14 15; 26 : 3 4 5 7 8 9 10 11 12 14 15 16; 27 : 4 5 6 8 9 10 11 12 13 15 16 17; 28 : 5 6 7 9 10 11 12 13 14 16 17 18; 29 : 6 7 8 10 11 12 13 14 15 17 18 19; 30 : 7 8 9 11 12 13 14 15 16 18 19 20; 31 : 8 9 10 12 13 14 15 16 17 19 20 21; 32 : 9 10 11 13 14 15 16 17 18 20 21 22; $$ -cx a=b731e49 o=be4 jcx a=6bda6c8 o=be4 b=ed6bf8d _jcx a=39f266a o=be4 b=a43368b n=63 $=0 g 0 : 6 24 30 33 39 57; 1 : 7 25 31 34 40 58; 2 : 8 26 32 35 41 59; 3 : 9 27 33 36 42 60; 4 : 10 28 34 37 43 61; 5 : 11 29 35 38 44 62; 6 : 0 12 30 36 39 45; 7 : 1 13 31 37 40 46; 8 : 2 14 32 38 41 47; 9 : 3 15 33 39 42 48; 10 : 4 16 34 40 43 49; 11 : 5 17 35 41 44 50; 12 : 6 18 36 42 45 51; 13 : 7 19 37 43 46 52; 14 : 8 20 38 44 47 53; 15 : 9 21 39 45 48 54; 16 : 10 22 40 46 49 55; 17 : 11 23 41 47 50 56; 18 : 12 24 42 48 51 57; 19 : 13 25 43 49 52 58; 20 : 14 26 44 50 53 59; 21 : 15 27 45 51 54 60; 22 : 16 28 46 52 55 61; 23 : 17 29 47 53 56 62; 24 : 0 18 30 48 54 57; 25 : 1 19 31 49 55 58; 26 : 2 20 32 50 56 59; 27 : 3 21 33 51 57 60; 28 : 4 22 34 52 58 61; 29 : 5 23 35 53 59 62; 30 : 0 6 24 36 54 60; 31 : 1 7 25 37 55 61; 32 : 2 8 26 38 56 62; 33 : 0 3 9 27 39 57; 34 : 1 4 10 28 40 58; 35 : 2 5 11 29 41 59; 36 : 3 6 12 30 42 60; 37 : 4 7 13 31 43 61; 38 : 5 8 14 32 44 62; 39 : 0 6 9 15 33 45; 40 : 1 7 10 16 34 46; 41 : 2 8 11 17 35 47; 42 : 3 9 12 18 36 48; 43 : 4 10 13 19 37 49; 44 : 5 11 14 20 38 50; 45 : 6 12 15 21 39 51; 46 : 7 13 16 22 40 52; 47 : 8 14 17 23 41 53; 48 : 9 15 18 24 42 54; 49 : 10 16 19 25 43 55; 50 : 11 17 20 26 44 56; 51 : 12 18 21 27 45 57; 52 : 13 19 22 28 46 58; 53 : 14 20 23 29 47 59; 54 : 15 21 24 30 48 60; 55 : 16 22 25 31 49 61; 56 : 17 23 26 32 50 62; 57 : 0 18 24 27 33 51; 58 : 1 19 25 28 34 52; 59 : 2 20 26 29 35 53; 60 : 3 21 27 30 36 54; 61 : 4 22 28 31 37 55; 62 : 5 23 29 32 38 56. $$ -cx a=94feb37 o=be4000 jcx a=4358010 o=be4000 b=ac2fd47 _jcx a=239f274 o=be4000 b=dcc2427 n=31 s10 % -cx a=7e1f341 o=c037a6 jcx a=b8f4d33 o=14684ae b=bc122ce _jcx a=8688beb o=21c8a03 b=555c2ef q nauty24r2/catg.c0000600000604200001440000000762411405400216012364 0ustar bdmusers/* catg.c version 1.1; B D McKay, Dec 2009 */ #define USAGE "catg [-xv] [infile]..." #define HELPTEXT \ " Copy files to stdout with all but the first header removed.\n\ \n\ -x Don't write a header.\n\ In the absence of -x, a header is written if\n\ there is one in the first input file.\n\ \n\ -v Summarize to stderr.\n" #include "gtools.h" /***********************************************************************/ static FILE* openfile_head(char *filename, char **header) /* Open the file for reading and return a FILE*. If open fails, or the header is malformed, write a message and return NULL. Set *header to point to the header string (statically allocated). A filename of NULL or "-" means stdin. */ { int c,i; char *actname; FILE *f; DYNALLSTAT(char,head,head_sz); if (filename == NULL || strcmp(filename,"-") == 0) { f = stdin; actname = "stdin"; } else { f = fopen(filename,"r"); actname = filename; } if (f == NULL) { fprintf(stderr,">E catg: can't open file %s\n",actname); return NULL; } DYNALLOC1(char,head,head_sz,100,"catg"); c = getc(f); if (c == '>') { i = 0; head[i++] = c; c = getc(f); if (c != '>') { fprintf(stderr,">E catg: bad header in %s\n",actname); fclose(f); return NULL; } head[i++] = c; do { c = getc(f); if (c == EOF) { fprintf(stderr,">E catg: bad header in %s\n",actname); fclose(f); return NULL; } if (i >= head_sz-1) DYNREALLOC(char,head,head_sz,head_sz+100,"catg"); head[i++] = c; } while (c != '<' || head[i-2] != '<'); head[i] = '\0'; } else head[0] = '\0'; *header = head; return f; } /***********************************************************************/ int main(int argc, char *argv[]) { char *infilename,*head; FILE *infile; int nfiles,i,j; char *arg,sw; boolean vswitch,xswitch; boolean badargs; char buff[1024]; size_t nr; DYNALLSTAT(char*,filename,filename_sz); HELP; DYNALLOC1(char*,filename,filename_sz,200,"catg"); xswitch = vswitch = FALSE; nfiles = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('v',vswitch) else SWBOOLEAN('x',xswitch) else badargs = TRUE; } } else { if (nfiles >= filename_sz) DYNREALLOC(char*,filename,filename_sz, filename_sz+200,"catg"); filename[nfiles++] = arg; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } for (i = 0; i < (nfiles == 0 ? 1 : nfiles); ++i) { infilename = (nfiles == 0 ? NULL : filename[i]); infile = openfile_head(infilename,&head); if (infile == NULL) ABORT("catg"); if (i == 0 && !xswitch) fprintf(stdout,"%s",head); while ((nr = fread(buff,1,1024,infile)) > 0) { fwrite(buff,1,nr,stdout); if (ferror(stdout)) { fprintf(stderr,">E catg: error in writing to stdout\n"); ABORT("catg"); } } if (ferror(infile)) { fprintf(stderr,">E catg: error in reading from %s\n", infilename == NULL ? "stdin" : infilename); ABORT("catg"); } fclose(infile); } if (vswitch) { } exit(0); } nauty24r2/configure.ac0000600000604200001440000001641211405400216013563 0ustar bdmusersdnl Process this file with autoconf to produce a configure script. AC_INIT(dreadnaut.c) dnl AC_TRY_CFLAGS (CFLAGS, [ACTION-IF-WORKS], [ACTION-IF-FAILS]) dnl Check if $CC supports a given set of cflags AC_DEFUN([AC_TRY_CFLAGS], [AC_MSG_CHECKING([if $CC supports $1 flags]) SAVE_CFLAGS="$CFLAGS" CFLAGS="$1" AC_TRY_RUN([main(){exit(0);}],[ac_cv_try_cflags_ok=yes], [ac_cv_try_cflags_ok=no],[ac_cv_try_cflags_ok=no]) CFLAGS="$SAVE_CFLAGS" AC_MSG_RESULT([$ac_cv_try_cflags_ok]) if test x"$ac_cv_try_cflags_ok" = x"yes"; then ifelse([$2],[],[:],[$2]) else ifelse([$3],[],[:],[$3]) fi]) dnl CVT_YESNO([YES-NO VARIABLE],[0-1 VARIABLE]) dnl Make a 0-1 output variable from a yes/no shell variable AC_DEFUN(CVT_YESNO,[if test x"$$1" = x"yes"; then $2=1 else $2=0 fi AC_SUBST($2)]) dnl Checks for system features AC_CANONICAL_HOST dnl Checks for C compiler and sets CFLAGS if not set by user user_cflags="$CFLAGS" AC_PROG_CC CFLAGS=$user_cflags MORECFLAGS="" if test x"$user_cflags" = x"" ; then AC_TRY_CFLAGS([-O4],[CFLAGS="$CFLAGS -O4"]); if test x"$ac_cv_try_cflags_ok" = x"no"; then AC_TRY_CFLAGS([-O3],[CFLAGS="$CFLAGS -O3"]); if test x"$ac_cv_try_cflags_ok" = x"no"; then AC_TRY_CFLAGS([-O2],[CFLAGS="$CFLAGS -O2"],[CFLAGS="$CFLAGS -O"]); fi fi if test "$CC" = "gcc" ; then gccver=`gcc --version 2>/dev/null || echo 0.0.0` else gccver=0.0.0 fi case "$host" in *pentium*solaris*) ;; *pentium4*) AC_TRY_CFLAGS([-march=pentium4],[CFLAGS="$CFLAGS -march=pentium4"]);; *pentium3*|*i686*|*athlon*|x86*) AC_TRY_CFLAGS([-march=i686],[CFLAGS="$CFLAGS -march=i686"]);; *pentium2*|*i586*) AC_TRY_CFLAGS([-march=i586],[CFLAGS="$CFLAGS -march=i586"]);; *powerpc*) machtype=`/usr/bin/machine 2>/dev/null || echo unknown` case "$machtype" in ppc740?) AC_TRY_CFLAGS([-mcpu=7400],[CFLAGS="$CFLAGS -mcpu=7400"]) AC_TRY_CFLAGS([-mtune=7400],[CFLAGS="$CFLAGS -mtune=7400"]);; ppc745?) AC_TRY_CFLAGS([-mcpu=7450],[CFLAGS="$CFLAGS -mcpu=7450"]) AC_TRY_CFLAGS([-mtune=7450],[CFLAGS="$CFLAGS -mtune=7450"]) case "$gccver" in *\ 4.[[0-9]].[[0-9]]\ *) AC_TRY_CFLAGS([$CFLAGS -fast], [MORECFLAGS="$MORECFLAGS -fast"]);; esac;; ppc970) AC_TRY_CFLAGS([-mcpu=g5],[CFLAGS="$CFLAGS -mcpu=g5"]) AC_TRY_CFLAGS([-mtune=g5],[CFLAGS="$CFLAGS -mtune=g5"]) AC_TRY_CFLAGS([-fast],[CFLAGS="$MORECFLAGS -fast"]);; *) AC_TRY_CFLAGS([-mpowerpc],[CFLAGS="$CFLAGS -mpowerpc"]);; esac;; *osf*) AC_TRY_CFLAGS([-fast],[CFLAGS="$CFLAGS -fast"]);; *sparcv8*|*sparcv9*) AC_TRY_CFLAGS([-msupersparc],[CFLAGS="$CFLAGS -msupersparc"]) if test x"$ac_cv_try_cflags_ok" = x"no"; then AC_TRY_CFLAGS([-cg92],[CFLAGS="$CFLAGS -cg92"]) if test x"$ac_cv_try_cflags_ok" = x"no"; then AC_TRY_CFLAGS([-xcg92],[CFLAGS="$CFLAGS -xcg92"]) fi fi;; esac fi echo CFLAGS=$CFLAGS echo MORECFLAGS=$MORECFLAGS dnl Checks relevant to Cygwin and other Windows things AC_EXEEXT dnl Checks for header files. dnl AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(stddef.h unistd.h sys/types.h sys/wait.h stdlib.h string.h errno.h) CVT_YESNO(ac_cv_header_stddef_h,header_stddef_h) CVT_YESNO(ac_cv_header_unistd_h,header_unistd_h) CVT_YESNO(ac_cv_header_stdlib_h,header_stdlib_h) CVT_YESNO(ac_cv_header_string_h,header_string_h) CVT_YESNO(ac_cv_header_signal_h,header_signal_h) CVT_YESNO(ac_cv_header_sys_wait_h,header_sys_wait_h) CVT_YESNO(ac_cv_header_sys_types_h,header_sys_types_h) CVT_YESNO(ac_cv_header_errno_h,header_errno_h) AC_TYPE_PID_T CVT_YESNO(ac_cv_type_pid_t,have_pid_t) AC_MSG_CHECKING(if malloc is declared in stdlib.h or malloc.h) AC_EGREP_HEADER([(^|[^a-zA-Z_0-9])malloc[^a-zA-Z_0-9]],stdlib.h, malloc_dec=1,malloc_dec=0) if test $malloc_dec -eq 0; then AC_EGREP_HEADER([(^|[^a-zA-Z_0-9])malloc[^a-zA-Z_0-9]],malloc.h, malloc_dec=2,malloc_dec=0) fi AC_SUBST(malloc_dec) AC_MSG_RESULT($malloc_dec) AC_MSG_CHECKING(if ftell is declared in stdio.h) AC_EGREP_HEADER([(^|[^a-zA-Z_0-9])ftell[^a-zA-Z_0-9]],stdio.h, ftell_dec=1,ftell_dec=0) AC_SUBST(ftell_dec) AC_MSG_RESULT($ftell_dec) AC_MSG_CHECKING(if fdopen is declared in stdio.h) AC_EGREP_HEADER([(^|[^a-zA-Z_0-9])fdopen[^a-zA-Z_0-9]],stdio.h, fdopen_dec=1,fdopen_dec=0) AC_SUBST(fdopen_dec) AC_MSG_RESULT($fdopen_dec) AC_MSG_CHECKING(if popen is declared in stdio.h) AC_EGREP_HEADER([(^|[^a-zA-Z_0-9])popen[^a-zA-Z_0-9]],stdio.h, popen_dec=1,popen_dec=0) AC_SUBST(popen_dec) AC_MSG_RESULT($popen_dec) AC_MSG_CHECKING(if putenv is declared in stdlib.h) AC_EGREP_HEADER([(^|[^a-zA-Z_0-9])putenv[^a-zA-Z_0-9]],stdlib.h, putenv_dec=1,putenv_dec=0) AC_SUBST(putenv_dec) AC_MSG_RESULT($putenv_dec) AC_MSG_CHECKING(if setenv is declared in stdlib.h) AC_EGREP_HEADER([(^|[^a-zA-Z_0-9])setenv[^a-zA-Z_0-9]],stdlib.h, setenv_dec=1,setenv_dec=0) AC_SUBST(setenv_dec) AC_MSG_RESULT($setenv_dec) AC_MSG_CHECKING(if INFINITY is declared in math.h) AC_EGREP_CPP(yes, [#include #include #ifdef INFINITY yes #endif ], has_math_inf=1, has_math_inf=0) AC_SUBST(has_math_inf) AC_MSG_RESULT($has_math_inf) dnl Checks for sizes of integer types; avoid 64-bit if necessary AC_CHECK_SIZEOF(int,4) AC_SUBST(ac_cv_sizeof_int) AC_CHECK_SIZEOF(long,4) AC_SUBST(ac_cv_sizeof_long) AC_CHECK_SIZEOF(long long,0) AC_SUBST(ac_cv_sizeof_long_long) lok=0 testprogs="dreadtest dreadtestS dreadtestS1 dreadtest4K" testprogs="$testprogs dreadtest1 dreadtestW1" AC_SUBST(MORECFLAGS) if test $ac_cv_sizeof_long_long -eq 8; then lok=1 testprogs="$testprogs dreadtestL1 dreadtestL" else if test $ac_cv_sizeof_long -eq 8; then lok=1 fi fi AC_SUBST(lok) AC_SUBST(testprogs) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST CVT_YESNO(ac_cv_c_const,have_const) dnl Checks for library functions. AC_CHECK_FUNC(isatty,have_isatty=1,have_isatty=0) AC_SUBST(have_isatty) AC_CHECK_FUNC(times,have_times=1,have_times=0) AC_SUBST(have_times) AC_CHECK_FUNC(time,have_time=1,have_time=0) AC_SUBST(have_time) AC_CHECK_FUNC(gettimeofday,have_gettimeofday=1,have_gettimeofday=0) AC_SUBST(have_gettimeofday) AC_CHECK_FUNC(times,have_times=1,have_times=0) AC_SUBST(have_times) AC_CHECK_FUNC(getrusage,have_getrusage=1,have_getrusage=0) AC_SUBST(have_getrusage) AC_CHECK_FUNC(perror,have_perror=1,have_perror=0) AC_SUBST(have_perror) AC_CHECK_FUNC(pipe,have_pipe=1,have_pipe=0) AC_SUBST(have_pipe) AC_CHECK_FUNC(wait,have_wait=1,have_wait=0) AC_SUBST(have_wait) AC_CHECK_FUNC(popen,have_popen=1,have_popen=0) AC_SUBST(have_popen) AC_CHECK_FUNC(putenv,have_putenv=1,have_putenv=0) AC_SUBST(have_putenv) AC_CHECK_FUNC(setenv,have_setenv=1,have_setenv=0) AC_SUBST(have_setenv) AC_CHECK_FUNC(getc_unlocked,have_getc_unlocked=1,have_getc_unlocked=0) AC_CHECK_FUNC(flockfile,have_flockfile=1,have_flockfile=0) if test $have_getc_unlocked -a $have_flockfile; then stdio_nolock=1 else stdio_nolock=0 fi AC_SUBST(stdio_nolock) AC_CHECK_PROGS(sort_prog,gsort sort,no_sort_found) AC_MSG_CHECKING(if sort supports the -k switch) if { $sort_prog -k 2,3 /dev/null 2>&1 ; } ; then sort_newparams_ok=1 else sort_newparams_ok=0 fi AC_SUBST(sort_newparams_ok) AC_MSG_RESULT($sort_newparams_ok) AC_OUTPUT(makefile:makefile.in nauty.h:nauty-h.in naututil.h:naututil-h.in gtools.h:gtools-h.in) nauty24r2/naututil.c0000600000604200001440000015503311405400341013310 0ustar bdmusers/***************************************************************************** * * * miscellaneous utilities for use with nauty 2.4. * * None of these procedures are needed by nauty, but all are by dreadnaut. * * * * Copyright (1984-2010) Brendan McKay. All rights reserved. * * Subject to waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 10-Nov-87 : final changes for version 1.2 * * 5-Dec-87 : changes made for version 1.3 : * * - added procedures readinteger() and readstring() * * - replaced all uses of fscanf() by appropriate uses * * of readinteger() or readstring() * * - "N:" is now illegal in readgraph() if N is too large * * or too small * * 28-Sep-88 : renamed to version 1.4 (no changes to this file) * * 23-Mar-89 : changes for version 1.5 : * * - declared key in hash() * * - changed file name to naututil.c * * 29-Mar-89 : - declared workperm[] and workset[], and modified * * many routines to use them. * * - added putmapping() * * - reworked some code in mathon() and rangraph() * * 3-Apr-89 : - changed putorbits() to use O(n) algorithm * * 5-Apr-89 : - modifed readgraph() to not require fresh line * * - changed MAKEEMPTY uses to EMPTYSET uses * * 26-Apr-89 : - moved ptncode() and equitable() to nautaux.c * * - added putquotient() * * 18-Aug-89 : - modified putset() to use "i:j" syntax optionally * * - modified putorbits() to use putset() * * - modified calling sequence for mathon() * * 19-Aug-90 : - changed delimeter arg of copycomment to int * * 14-Oct-90 : renamed to version 1.6 (no changes to this file) * * 23-Jan-91 : changes for version 1.7 : * * - fixed bug in complement() * * 27-Aug-92 : - made linelength <= 0 mean no line breaks * * 5-Jun-93 : renamed to version 1.7+ (no changes to this file) * * 18-Aug-93 : renamed to version 1.8 (no changes to this file) * * 17-Sep-93 : renamed to version 1.9 (no changes to this file) * * 13-Jul-96 : changes for version 2.0 : * * - added dynamic allocation * * - added limit parameter to readstring * * - added readvperm() and sublabel() * * 31-Aug-96 : - converted from RAN to KRAN * * 6-Feb-97 : - corrected DYNALLOC1 call in putmapping * * 10-Dec-97 : - KRAN now initialises automatically * * 9-Jan-00 : - added naututil_check() * * 12-Feb-00 : - some minor code formatting * * 16-Nov-00 : - changes as listed in nauty.h * * 23-Apr-01 : changes for version 2.1 : * * - removed EXTDEFS * * 2-Jun-01 : - added converse() * * 21-Nov-01 : use NAUTYREQUIRED in naututil_check() * * 11-Apr-03 : changes for version 2.2 : * * - added rangraph2() * * 17-Nov-03 : changed INFINITY to NAUTY_INFINITY * * 10-Dec-06 : removed BIGNAUTY * * * *****************************************************************************/ #define ONE_WORD_SETS #include "naututil.h" /* which includes nauty.h, nautinv.h and stdio.h */ #if MAXM==1 #define M 1 #else #define M m #endif long seed = 1; #if !MAXN DYNALLSTAT(permutation,workperm,workperm_sz); DYNALLSTAT(set,workset,workset_sz); #else static permutation workperm[MAXN+2]; /* used for scratch purposes */ static set workset[MAXM]; /* used for scratch purposes */ #endif #ifdef NLMAP #define GETNW(c,f) do c = getc(f); while (c==' '||c=='\t') #define GETNWC(c,f) do c = getc(f); while (c==' '||c==','||c=='\t') #define GETNWL(c,f) do c = getc(f); while (c==' '||c=='\n'||c=='\t') #else #define GETNW(c,f) do c = getc(f); while (c==' '||c=='\t'||c=='\r') #define GETNWC(c,f) do c = getc(f); while (c==' '||c==','||c=='\t'||c=='\r') #define GETNWL(c,f) do c = getc(f); while (c==' '||c=='\n'||c=='\t'||c=='\r') #endif #define ISDIGIT(c) ((c) >= '0' && (c) <= '9') /***************************************************************************** * * * setinter(set1,set2,m) = the number of elements in the intersection of * * the sets set1 and set2. * * * *****************************************************************************/ int setinter(set *set1, set *set2, int m) { setword x; #if MAXM==1 if (x = *set1 & *set2) return POPCOUNT(x); else return 0; #else int count,i; count = 0; for (i = m; --i >= 0;) if ((x = (*set1++) & (*set2++)) != 0) count += POPCOUNT(x); return count; #endif } /***************************************************************************** * * * setsize(set1,m) = the number of elements in the set set1. * * * *****************************************************************************/ int setsize(set *set1, int m) { #if MAXM==1 if (set1 != 0) return POPCOUNT(*set1); else return 0; #else int count,i; setword x; count = 0; for (i = m; --i >= 0;) if ((x = *set1++) != 0) count += POPCOUNT(x); return count; #endif } /***************************************************************************** * * * flushline(f) reads from f until '\n' or EOF. * * If non-trivial characters are skipped, the user is informed. * * * *****************************************************************************/ void flushline(FILE *f) { boolean msg; int c; msg = FALSE; while ((c = getc(f)) != EOF && c != '\n') if (msg) PUTC((char)c,ERRFILE); else if (c != ' ' && c != '\t' && c != '\f' && c != '\r' && c != ',') { msg = TRUE; fprintf(ERRFILE,"input skipped : '%c",(char)c); } if (msg) fprintf(ERRFILE,"'\n\n"); } /***************************************************************************** * * * readinteger(f,&i) reads an optionally-signed integer from f, preceded by * * any amount of white space. The function value returned is TRUE if an * * integer was found, FALSE otherwise. * * * *****************************************************************************/ boolean readinteger(FILE *f, int *p) { int c,ans,minus; GETNWL(c,f); if (!ISDIGIT(c) && c != '-' && c != '+') { if (c != EOF) ungetc((char)c,f); return FALSE; } minus = c == '-'; ans = (c == '-' || c == '+' ? 0 : c - '0'); c = getc(f); while (ISDIGIT(c)) { ans *= 10; ans += c - '0'; c = getc(f); } if (c != EOF) ungetc((char)c,f); *p = (minus ? -ans : ans); return TRUE; } /***************************************************************************** * * * readstring(f,s,slen) reads a non-white string from f, preceded by any * * amount of white space. The function value returned is TRUE if a * * non-white char was found, FALSE otherwise. The string itself goes into * * s terminated by a null character. A null string is in s if no string is * * found. At most slen chars are stored in s, including the null. * * * *****************************************************************************/ boolean readstring(FILE *f, char *s, int slen) { int c; char *slim; slim = s + slen - 1; GETNWL(c,f); if (c == EOF) { *s = '\0'; return FALSE; } if (s <= slim) *s++ = c; c = getc(f); while (c != ' ' && c != '\n' && c != '\t' && c != '\r' && c != EOF) { if (s <= slim) *s++ = c; c = getc(f); } if (s <= slim) *s = '\0'; else *slim = '\0'; if (c != EOF) ungetc((char)c,f); return TRUE; } /***************************************************************************** * * * getint(f) reads an integer from f, optionally preceded by '=' * * and white space. -1 is returned if the attempt was unsuccessful. * * * *****************************************************************************/ int getint(FILE *f) { int i,c; GETNWL(c,f); if (c != '=') ungetc((char)c,f); if (readinteger(f,&i)) return i; else return -1; } /***************************************************************************** * * * putset(f,set1,curlenp,linelength,m,compress) writes the set set1 to * * file f using at most linelength characters per line (excluding '\n'). * * A value of linelength <= 0 dictates no line breaks at all. * * *curlenp is the number of characters on the line so far; it is updated. * * A range j1,j1+1,...,j2 for j2-j1>=2 is written as "j1:j2" if compress * * is nonzero (eg. TRUE); otherwise each element is written separately. * * No final '\n' is written. labelorg is used. * * * * FUNCTIONS CALLED: nextelement(),itos() * * * *****************************************************************************/ void putset(FILE *f, set *set1, int *curlenp, int linelength, int m, boolean compress) { int slen,j1,j2; char s[40]; j1 = -1; while ((j1 = nextelement(set1,m,j1)) >= 0) { j2 = j1; if (compress) { while (nextelement(set1,m,j2) == j2 + 1) ++j2; if (j2 == j1+1) j2 = j1; } slen = itos(j1+labelorg,s); if (j2 >= j1 + 2) { s[slen] = ':'; slen += 1 + itos(j2+labelorg,&s[slen+1]); } if (linelength > 0 && *curlenp + slen + 1 >= linelength) { fprintf(f,"\n "); *curlenp = 3; } fprintf(f," %s",s); *curlenp += slen + 1; j1 = j2; } } /***************************************************************************** * * * readgraph(f,g,digraph,prompt,edit,linelength,m,n) reads a graph g from f. * * Commands: (There is always a "current vertex" v, initially labelorg; * * n is an unsigned integer.) * * n : add edge (v,n) * * -n : delete edge (v,n) * * n: : set v := n, and exit if v >= n. * * ? : type neighbours of vertex v * * ; : increment v, and exit if v >= n. * * . : exit * * ! : skip rest of input line * * * * If digraph==FALSE, loops are illegal and (x,y) => (y,x) * * If edit==FALSE, the graph is initialized to empty. * * If prompt==TRUE, prompts are written to PROMPTFILE. * * linelength is a limit on the number of characters per line caused by '?' * * A value of linelength <= 0 dictates no line breaks at all. * * labelorg is used. * * * * FUNCTIONS CALLED : putset() * * * *****************************************************************************/ void readgraph(FILE *f, graph *g, boolean digraph, boolean prompt, boolean edit, int linelength, int m, int n) { int v,c; int curlen,w; graph *gv; boolean neg; if (!edit) for (v = 0, gv = g; v < n; ++v, gv += M) EMPTYSET(gv,m); v = 0; gv = g; neg = FALSE; while (TRUE) { GETNWC(c,f); if (ISDIGIT(c)) { ungetc((char)c,f); readinteger(f,&w); w -= labelorg; if (neg) { neg = FALSE; if (w < 0 || w >= n || !digraph && w == v) fprintf(ERRFILE,"illegal edge (%d,%d) ignored\n\n", v+labelorg,w+labelorg); else { DELELEMENT(gv,w); if (!digraph) DELELEMENT(GRAPHROW(g,w,M),v); } } else { GETNWC(c,f); if (c == ':') if (w < 0 || w >= n) fprintf(ERRFILE, "illegal vertex number %d ignored\n\n", w+labelorg); else { v = w; gv = GRAPHROW(g,v,M); } else { ungetc((char)c,f); if (w < 0 || w >= n || !digraph && w == v) fprintf(ERRFILE,"illegal edge (%d,%d) ignored\n\n", v+labelorg,w+labelorg); else { ADDELEMENT(gv,w); if (!digraph) ADDELEMENT(GRAPHROW(g,w,M),v); } } } } else switch(c) { case ';': neg = FALSE; ++v; if (v >= n) return; gv = GRAPHROW(g,v,M); break; case '?': neg = FALSE; fprintf(PROMPTFILE,"%2d : ",v+labelorg); curlen = 5; putset(PROMPTFILE,gv,&curlen,linelength,M,FALSE); fprintf(PROMPTFILE,";\n"); break; case '\n': neg = FALSE; if (prompt) fprintf(PROMPTFILE,"%2d : ",v+labelorg); break; case EOF: case '.': return; case '-': neg = TRUE; break; case '!': do c = getc(f); while (c != '\n' && c != EOF); if (c == '\n') ungetc((char)c,f); break; default : fprintf(ERRFILE,"illegal char '%c' - use '.' to exit\n\n", (char)c); } } } /***************************************************************************** * * * putgraph(f,g,linelength,m,n) writes a list of the edges of g to f * * using at most linelength characters per line (excluding '\n'). * * A value of linelength <= 0 dictates no line breaks at all. * * labelorg is used. * * * * FUNCTIONS CALLED: putset() * * * *****************************************************************************/ void putgraph(FILE *f, graph *g, int linelength, int m, int n) { int i,curlen; set *pg; for (i = 0, pg = g; i < n; ++i, pg += M) { fprintf(f,"%3d : ",i+labelorg); curlen = 7; putset(f,pg,&curlen,linelength,M,FALSE); fprintf(f,";\n"); } } /***************************************************************************** * * * putmapping(f,lab1,org1,lab2,org2,linelength,n) writes n pairs * * (lab1[i]+org1)-(lab2[i]+org2) to file f in increasing order of lab1[i]. * * lab1 and lab2 are assumed to be permutations. At most linelength * * characters (excluding '\n') are written per line. * * A value of linelength <= 0 dictates no line breaks at all. * * * * FUNCTIONS CALLED: itos(),putstring() * * * *****************************************************************************/ void putmapping(FILE *f, int *lab1, int org1,int *lab2, int org2, int linelength, int n) { int i,curlen,slen; char s[60]; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"putmapping"); #endif for (i = 0; i < n; ++i) workperm[lab1[i]] = lab2[i]; curlen = 0; for (i = 0; i < n; ++i) { slen = itos(i+org1,s); s[slen++] = '-'; slen += itos(workperm[i]+org2,&s[slen]); if (linelength > 0 && curlen + slen + 1 > linelength) { putstring(f,"\n "); curlen = 2; } PUTC(' ',f); putstring(f,s); curlen += slen + 1; } PUTC('\n',f); } /***************************************************************************** * * * putorbits(f,orbits,linelength,n) writes the orbits to f as lists * * of integers separated by semicolons. No more than linelength characters * * (excluding '\n') are written per line. * * A value of linelength <= 0 dictates no line breaks at all. * * labelorg is used. * * * * FUNCTIONS CALLED: itos(),putset() * * * *****************************************************************************/ void putorbits(FILE *f, int *orbits, int linelength, int n) { int i,j; int m,curlen; m = (n + WORDSIZE - 1) / WORDSIZE; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"putorbits"); DYNALLOC1(set,workset,workset_sz,m,"putorbits"); #endif for (i = n; --i >= 0;) workperm[i] = 0; for (i = n; --i >= 0;) if ((j = orbits[i]) < i) { workperm[i] = workperm[j]; workperm[j] = i; } curlen = 0; for (i = 0; i < n; ++i) if (orbits[i] == i) { EMPTYSET(workset,m); j = i; do { ADDELEMENT(workset,j); j = workperm[j]; } while (j > 0); putset(f,workset,&curlen,linelength-1,m,TRUE); PUTC(';',f); ++curlen; } PUTC('\n',f); } /***************************************************************************** * * * putquotient(f,g,lab,ptn,level,linelength,m,n) writes the quotient matrix * * of g defined by the partition at the given level. Precisely, for each * * cell W, it writes the number w of the least vertex in W, then the size * * of W, then the number of times w is joined FROM each cell. A complete * * join is written as "*", while an empty join is written as "-". No more * * than linelength characters (excluding '\n') are written per line unless * * linelength is very small. A value of linelength <= 0 dictates no line * * breaks at all. labelorg is used. * * * * FUNCTIONS CALLED: itos() * * * *****************************************************************************/ void putquotient(FILE *f, graph *g, int *lab, int *ptn, int level, int linelength, int m, int n) { int i; char s[50]; int ic,curlen,v,w,cell1,cell2,numcells,jc,csize,k; set *gw; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"putquotient"); DYNALLOC1(set,workset,workset_sz,m,"putquotient"); #endif numcells = 0; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} w = lab[cell1]; for (i = cell1 + 1; i <= cell2; ++i) if (lab[i] < w) w = lab[i]; workperm[numcells++] = w; } for (ic = cell1 = 0; ic < numcells; ++ic, cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} EMPTYSET(workset,M); for (i = cell1; i <= cell2; ++i) ADDELEMENT(workset,lab[i]); v = workperm[ic]; csize = cell2 - cell1 + 1; if (v + labelorg < 10) { s[0] = ' '; curlen = 1; } else curlen = 0; curlen += itos(v+labelorg,&s[curlen]); s[curlen++] = '['; curlen += itos(csize,&s[curlen]); fprintf(f,"%s",s); if (csize < 10) { fprintf(f,"] :"); curlen += 4; } else { fprintf(f,"] :"); curlen += 3; } for (jc = 0; jc < numcells; ++jc) { w = workperm[jc]; gw = GRAPHROW(g,w,m); k = setinter(gw,workset,M); if (k == 0 || k == csize) { if (linelength > 0 && curlen + 2 > linelength) { fprintf(f,"\n "); curlen = 4; } if (k == 0) fprintf(f," -"); else fprintf(f," *"); curlen += 2; } else { i = itos(k,s); if (linelength > 0 && curlen + i + 1 > linelength) { fprintf(f,"\n "); curlen = 4; } fprintf(f," %s",s); curlen += i + 1; } } fprintf(f,"\n"); } } /***************************************************************************** * * * putptn(f,lab,ptn,level,linelength,n) writes the partition at the given * * level as sorted lists of integers separated by semicolons. No more than * * linelength characters (excluding '\n') are written per line. * * A value of linelength <= 0 dictates no line breaks at all. * * labelorg is used. * * * * FUNCTIONS CALLED: itos(),putset() * * * *****************************************************************************/ void putptn(FILE *f, int *lab, int *ptn, int level, int linelength, int n) { int i; int curlen,m; m = (n + WORDSIZE - 1) / WORDSIZE; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"putptn"); #endif PUTC('[',f); curlen = 1; i = 0; while (i < n) { EMPTYSET(workset,m); while (TRUE) { ADDELEMENT(workset,lab[i]); if (ptn[i] > level) ++i; else break; } putset(f,workset,&curlen,linelength-2,m,TRUE); if (i < n-1) { fprintf(f," |"); curlen += 2; } ++i; } fprintf(f," ]\n"); } /***************************************************************************** * * * putcanon(f,canonlab,canong,linelength,m,n) writes the label canonlab * * and the graph canong to f, using at most linelength characters * * (excluding '\n') per line. labelorg is used. * * A value of linelength <= 0 dictates no line breaks at all. * * * * FUNCTIONS CALLED: writeperm(),putgraph() * * * *****************************************************************************/ void putcanon(FILE *f, int *canonlab, graph *canong, int linelength, int m, int n) { int i; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"putcanon"); #endif for (i = 0; i < n; ++i) workperm[i] = canonlab[i]; writeperm(f,workperm,TRUE,linelength,n); putgraph(f,canong,linelength,m,n); } /***************************************************************************** * * * readptn(f,lab,ptn,&numcells,prompt,n) reads a partition from f * * and establishes it in (lab,ptn). * * The format can be just a number, which is fixed alone, or an arbitrary * * partition [...|...|...]. Ranges x:y can be used. * * labelorg is used. * * * *****************************************************************************/ void readptn(FILE *f, int *lab, int *ptn, int *numcells, boolean prompt, int n) { int i,j; int c,v1,v2,m; m = (n + WORDSIZE - 1) / WORDSIZE; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"readptn"); #endif GETNW(c,f); if (c == '=') GETNW(c,f); if (ISDIGIT(c)) { ungetc((char)c,f); readinteger(f,&v1); v1 -= labelorg; if (v1 >= 0 && v1 < n) fixit(lab,ptn,numcells,v1,n); else { fprintf(ERRFILE,"vertex out of range (%d), fixing nothing\n\n", v1+labelorg); unitptn(lab,ptn,numcells,n); } return; } if (c != '[') { ungetc((char)c,f); fprintf(ERRFILE,"illegal partition, fixing nothing\n\n"); unitptn(lab,ptn,numcells,n); return; } EMPTYSET(workset,m); *numcells = 0; for (i = 0; i < n; ++i) ptn[i] = NAUTY_INFINITY; i = 0; j = -1; while (TRUE) { GETNWC(c,f); if (ISDIGIT(c)) { ungetc((char)c,f); readinteger(f,&v1); v1 -= labelorg; GETNWC(c,f); if (c == ':') if (!readinteger(f,&v2)) { fprintf(ERRFILE,"unfinished range\n\n"); v2 = v1; } else v2 -= labelorg; else { ungetc((char)c,f); v2 = v1; } while (v1 <= v2) { if (v1 < 0 || v1 >= n || ISELEMENT(workset,v1)) fprintf(ERRFILE,"illegal or repeated number : %d\n\n", v1+labelorg); else { ADDELEMENT(workset,v1); lab[++j] = v1; } ++v1; } } else if (c == '|' || c == ']' || c == EOF) { if (j >= i) { ++*numcells; ptn[j] = 0; } if (c == '|') i = j + 1; else if (j == n - 1) return; else { i = j + 1; ++*numcells; for (j = 0; j < n; ++j) if (!ISELEMENT(workset,j)) lab[i++] = j; ptn[n-1] = 0; return; } } else if (c == '\n') { if (prompt) fprintf(PROMPTFILE,"] "); } else fprintf(ERRFILE,"illegal character '%c' in partition\n\n",c); } } /***************************************************************************** * * * unitptn(lab,ptn,&numcells,n) establishes the partition with one cell. * * * *****************************************************************************/ void unitptn(int *lab,int *ptn, int *numcells, int n) { int i; for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = NAUTY_INFINITY; } ptn[n-1] = 0; *numcells = 1; } /***************************************************************************** * * * cellstarts(ptn,level,cell,m,n) sets the set cell to contain the indices * * of the starts in ptn of the partition at level level. * * * *****************************************************************************/ void cellstarts(int *ptn, int level, set *cell, int m, int n) { int i; EMPTYSET(cell,m); i = 0; while (i < n) { ADDELEMENT(cell,i); while (ptn[i] > level) ++i; ++i; } } /***************************************************************************** * * * fixit(lab,ptn,&numcells,fixedvertex,n) establishes the partition * * with one cell {fixedvertex} and all the other vertices (if any) in * * another cell. * * * *****************************************************************************/ void fixit(int *lab, int *ptn, int *numcells, int fixedvertex, int n) { int i; for (i = 1; i < n; ++i) { lab[i] = i; ptn[i] = 1; } lab[0] = fixedvertex; lab[fixedvertex] = 0; ptn[0] = 0; ptn[n-1] = 0; if (n == 1) *numcells = 1; else *numcells = 2; } /***************************************************************************** * * * sethash(s,n,seed,key) is a function whose value depends only on the * * set s, a long seed, and an integer key. It is intended to be independent * * of the word size provided long ints have at least 32 bits. n is the * * underlying universal set size. * * 28 bits of seed and 15 bits of key are significant. * * The result is in the low 28 bits. * * * *****************************************************************************/ long sethash(set *s, int n, long seed, int key) { int i,j,lsh,rsh; long l,res,salt,lshmask; setword si; lsh = key & 0xF; rsh = 28 - lsh; salt = (key >> 4) & 0x7FFL; res = seed & 0xFFFFFFFL; lshmask = (1L << lsh) - 1; j = 0; for (i = 0; ; ++i) { si = s[i]; l = SWCHUNK0(si); res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; if ((j += 16) >= n) break; #if WORDSIZE > 16 l = SWCHUNK1(si); res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; if ((j += 16) >= n) break; #if WORDSIZE == 64 l = SWCHUNK2(si); res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; if ((j += 16) >= n) break; l = SWCHUNK3(si); res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; if ((j += 16) >= n) break; #endif #endif } return res; } /***************************************************************************** * * * hash(setarray,length,key) is a function whose value depends only on the * * first 'length' entries of the array 'setarray', and the value of key. * * key should be in the range 1..31 and preferably odd. * * This works best if long ints have at least 32 bits, but it's valid anyway.* * * *****************************************************************************/ long hash(set *setarray, long length, int key) { long code; set *sptr; code = length; sptr = setarray + length; while (--sptr >= setarray) code = (code<>(32-key)) + *sptr); return code; } /***************************************************************************** * * * readperm is like readvperm without the last argument. It is provided * * only for backward compatibility. * * * *****************************************************************************/ void readperm(FILE *f, permutation *perm, boolean prompt, int n) { int nv; readvperm(f,perm,prompt,n,&nv); } /***************************************************************************** * * * readvperm(f,perm,prompt,n,nv) reads a permutation of order n from * * f, terminated by a semicolon. Any repeated or illegal numbers or * * characters are reported then ignored. Missing numbers are filled in * * in numerical order. A prompt is issued for each line if prompt!=FALSE. * * labelorg is used. *nv is set equal to the number of numbers actually * * given. Ranges like v1:v2 are allowed. * * * *****************************************************************************/ void readvperm(FILE *f, permutation *perm, boolean prompt, int n, int *nv) { int i; int m,c,v1,v2; m = (n + WORDSIZE - 1) / WORDSIZE; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"readperm"); #endif EMPTYSET(workset,m); i = 0; while (TRUE) { GETNWC(c,f); if (c == ';' || c == EOF) break; if (ISDIGIT(c)) { ungetc((char)c,f); readinteger(f,&v1); v1 -= labelorg; GETNWC(c,f); if (c == ':') if (!readinteger(f,&v2)) { fprintf(ERRFILE,"unfinished range\n\n"); v2 = v1; } else v2 -= labelorg; else { ungetc((char)c,f); v2 = v1; } if (v1 < 0 || v1 >= n || v2 >= n || v1 > v2) { if (v1 < v2) fprintf(ERRFILE, "illegal range in permutation : %d:%d\n\n", v1+labelorg,v2+labelorg); else fprintf(ERRFILE, "illegal number in permutation : %d\n\n", v1+labelorg); } else for (; v1 <= v2; ++v1) { if (!ISELEMENT(workset,v1)) { perm[i++] = v1; ADDELEMENT(workset,v1); } else fprintf(ERRFILE, "repeated number in permutation : %d\n\n", v1+labelorg); } } else { if (c == '\n' && prompt) fprintf(PROMPTFILE,"+ "); if (c != '\n') fprintf(ERRFILE,"bad character '%c' in permutation\n\n", (char)c); } } *nv = i; for (v1 = 0; v1 < n; ++v1) if (!ISELEMENT(workset,v1)) perm[i++] = v1; } /***************************************************************************** * * * ranperm(perm,n) creates a random permutation in perm. * * * *****************************************************************************/ void ranperm(permutation *perm, int n) { int i,j,t; for (i = n; --i >= 0; ) perm[i] = i; for (i = n; --i > 0; ) { j = KRAN(i+1); t = perm[i]; perm[i] = perm[j]; perm[j] = t; } } /***************************************************************************** * * * relabel(g,perm,lab,workg,m,n) replaces g by g^perm, using workg as * * scratch space. If lab!=NULL, it is taken as a labelling vector and * * also permuted. * * * * FUNCTIONS CALLED: updatecan() * * * *****************************************************************************/ void relabel(graph *g, int *lab, permutation *perm, graph *workg, int m, int n) { long li; int i; for (li = (long)M * (long)n; --li >= 0;) workg[li] = g[li]; updatecan(workg,g,perm,0,M,n); if (lab != NULL) { for (i = 0; i < n; ++i) workperm[perm[i]] = i; for (i = 0; i < n; ++i) lab[i] = workperm[lab[i]]; } } /***************************************************************************** * * * sublabel(g,perm,nperm,workg,m,n) replaces g by g^perm, using workg as * * scratch space. perm is a partial vector, of length nperm, where it is * * known that the elements of perm are distinct. * * * *****************************************************************************/ void sublabel(graph *g, permutation *perm, int nperm, graph *workg, int m, int n) { long li; int i,j,k; int newm; set *gi,*wgi; for (li = (long)m * (long)n; --li >= 0;) workg[li] = g[li]; newm = (nperm + WORDSIZE - 1) / WORDSIZE; for (li = (long)newm * (long)nperm; --li >= 0;) g[li] = 0; for (i = 0, gi = (set*)g; i < nperm; ++i, gi += newm) { wgi = GRAPHROW(workg,perm[i],m); for (j = 0; j < nperm; ++j) { k = perm[j]; if (ISELEMENT(wgi,k)) ADDELEMENT(gi,j); } } } /***************************************************************************** * * * copycomment(fin,fout,delimiter) copies fin to fout until either EOF or * * the character 'delimiter' is read. The delimiter itself isn't written. * * Escape sequences \n,\t,\b,\r,\f,\\,\',\",\\n are recognised. Otherwise, * * '\' is ignored. * * * *****************************************************************************/ void copycomment(FILE *fin, FILE *fout, int delimiter) { int c,backslash; backslash = FALSE; while ((c = getc(fin)) != EOF && (c != delimiter || backslash)) if (backslash) { switch (c) { case '\n': break; case 'n': PUTC('\n',fout); break; case 't': PUTC('\t',fout); break; case 'b': PUTC('\b',fout); break; case 'r': PUTC('\r',fout); break; case 'f': PUTC('\f',fout); break; case '\\': PUTC('\\',fout); break; case '\'': PUTC('\'',fout); break; case '"': PUTC('"',fout); break; default: PUTC(c,fout); } backslash = FALSE; } else if (c == '\\') backslash = TRUE; else PUTC(c,fout); } /***************************************************************************** * * * mathon(g1,m1,n1,g2,m2,n2) performs a Mathon doubling operation on g1, * * leaving the result in g2. * * m1,n1 and m2,n2 are the values of m,n before and after the operation. * * * *****************************************************************************/ void mathon(graph *g1, int m1, int n1, graph *g2, int m2, int n2) { int i,j,ii,jj; long li; set *rowptr,*gp; for (li = (long)m2 * (long)n2; --li >= 0;) g2[li] = 0; for (i = 1; i <= n1; ++i) { ii = i + n1 + 1; gp = GRAPHROW(g2,0,m2); /* unnecessarily convoluted code */ ADDELEMENT(gp,i); /* needed to avoid compiler bug */ gp = GRAPHROW(g2,i,m2); /* in MSDOS version */ ADDELEMENT(gp,0); gp = GRAPHROW(g2,n1+1,m2); ADDELEMENT(gp,ii); gp = GRAPHROW(g2,ii,m2); ADDELEMENT(gp,n1+1); } for (i = 0, rowptr = g1; i < n1; ++i, rowptr += m1) for (j = 0; j < n1; ++j) if (j != i) { ii = i + n1 + 2; jj = j + n1 + 2; if (ISELEMENT(rowptr,j)) { gp = GRAPHROW(g2,i+1,m2); ADDELEMENT(gp,j+1); gp = GRAPHROW(g2,ii,m2); ADDELEMENT(gp,jj); } else { gp = GRAPHROW(g2,i+1,m2); ADDELEMENT(gp,jj); gp = GRAPHROW(g2,ii,m2); ADDELEMENT(gp,j+1); } } } /***************************************************************************** * * * rangraph(g,digraph,invprob,m,n) makes a random graph (or digraph if * * digraph!=FALSE) with edge probability 1/invprob. * * * *****************************************************************************/ void rangraph(graph *g, boolean digraph, int invprob, int m, int n) { int i,j; long li; set *row,*col; for (li = (long)m * (long)n; --li >= 0;) g[li] = 0; for (i = 0, row = g; i < n; ++i, row += m) if (digraph) { for (j = 0; j < n; ++j) if (KRAN(invprob) == 0) ADDELEMENT(row,j); } else for (j = i + 1, col = GRAPHROW(g,j,m); j < n; ++j, col += m) if (KRAN(invprob) == 0) { ADDELEMENT(row,j); ADDELEMENT(col,i); } } /***************************************************************************** * * * rangraph2(g,digraph,p1,p2,m,n) makes a random graph (or digraph if * * digraph!=FALSE) with edge probability p1/p2. * * * *****************************************************************************/ void rangraph2(graph *g, boolean digraph, int p1, int p2, int m, int n) { int i,j; long li; set *row,*col; for (li = (long)m * (long)n; --li >= 0;) g[li] = 0; for (i = 0, row = g; i < n; ++i, row += m) if (digraph) { for (j = 0; j < n; ++j) if (KRAN(p2) < p1) ADDELEMENT(row,j); } else for (j = i + 1, col = GRAPHROW(g,j,m); j < n; ++j, col += m) if (KRAN(p2) < p1) { ADDELEMENT(row,j); ADDELEMENT(col,i); } } /***************************************************************************** * * * putdegs(f,g,linelength,m,n) writes the degree of each vertex of g to * * file f, using at most linelength characters per line (excluding '\n'). * * A value of linelength <= 0 dictates no line breaks at all. * * labelorg is used. * * * * FUNCTIONS CALLED : itos(),putstring(),setsize() * * * *****************************************************************************/ void putdegs(FILE *f, graph *g, int linelength, int m, int n) { char s[60]; int i,j,v1,v2,deg,curlen; graph *gp; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"putdegs"); #endif for (i = 0, gp = g; i < n; ++i, gp += M) workperm[i] = setsize(gp,m); curlen = 0; v1 = 0; while (v1 < n) { deg = workperm[v1]; v2 = v1; for (v2 = v1; v2 < n - 1 && workperm[v2+1] == deg; ++v2) {} j = itos(v1+labelorg,s); if (v2 > v1) { s[j++] = '-'; j += itos(v2+labelorg,&s[j]); } s[j++] = ':'; j += itos(deg,&s[j]); s[j] = ' '; s[j+1] = '\0'; if (linelength > 0 && curlen + j >= linelength) { PUTC('\n',f); curlen = 0; } curlen += j + 1; putstring(f,s); v1 = v2 + 1; } PUTC('\n',f); } /***************************************************************************** * * * complement(g,m,n) replaces the graph g by its complement * * No loops are created unless there are loops present, in which case the * * loops are also complemented. * * * *****************************************************************************/ void complement(graph *g, int m, int n) { boolean loops; int i,j; graph *gp; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"complement"); #endif loops = FALSE; for (i = 0, gp = g; i < n && !loops; ++i, gp += M) if (ISELEMENT(gp,i)) loops = TRUE; EMPTYSET(workset,m); for (i = 0; i < n; ++ i) ADDELEMENT(workset,i); for (i = 0, gp = g; i < n; ++i, gp += M) { for (j = 0; j < M; ++j) gp[j] = workset[j] & ~gp[j]; if (!loops) DELELEMENT(gp,i); } } /***************************************************************************** * * * converse(g,m,n) replaces the digraph g by its converse. * * There is no effect on an undirected graph. * * * *****************************************************************************/ void converse(graph *g, int m, int n) { int i,j; graph *gi,*gj; for (i = 0, gi = g; i < n; ++i, gi += M) for (j = i+1, gj = gi+M; j < n; ++j, gj += M) if ((ISELEMENT(gi,j)!=0) + (ISELEMENT(gj,i)!=0) == 1) { FLIPELEMENT(gi,j); FLIPELEMENT(gj,i); } } /***************************************************************************** * * * naututil_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void naututil_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in naututil.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in naututil.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in naututil.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: naututil.c version mismatch\n"); exit(1); } } /***************************************************************************** * * * naututil_freedyn() - free the dynamic memory in this module * * * *****************************************************************************/ void naututil_freedyn(void) { #if !MAXN DYNFREE(workperm,workperm_sz); DYNFREE(workset,workset_sz); #endif } nauty24r2/dreadtest.c0000600000604200001440000014071511274163463013442 0ustar bdmusers/***************************************************************************** * * * This is the main file for dreadnaut() version 2.4, which is a test-bed * * for nauty() version 2.4. * * * * ACTUALLY IT ISN'T. This is a modified edition of dreadnaut that performs * * tests of conformity. Instead of reporting the results of computations to * * the human, it compares them to values stored in the input and reports any * * differences. * * It is assumed that "long int" has at least 32 bits. * * In the following, # is a hex value (without 0x) that is compared to a * * hash certificate of the specified value. An error message is given if * * they don't match exactly. * * The following no longer have their old meanings: * * a # - compare the generators * * b # - compare the canonical labelling and the labelled graph * * o # - compare the orbits * * & # - compare the partition * * S # - compare the statistics * * C - run tests on bits, sets, etc. * * * * Copyright (1984-2007) Brendan McKay. All rights reserved. * * Subject to the waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 1-Sep-02 - Initial write starting at dreadnaut.c * * 17-Nov-03 - Change INFINITY to NAUTY_INFINITY * * 23-Nov-06 - Fix for version 2.4. * * * *****************************************************************************/ #include "naututil.h" /* which includes nauty.h, which includes stdio.h */ #include "nautinv.h" /* which includes nauty.h, which includes stdio.h */ #define PM(x) ((x) ? '+' : '-') #define SS(n,sing,plur) (n),((n)==1?(sing):(plur)) #define WORKSIZE 60 #define INFILE fileptr[curfile] #define OUTFILE outfile #if !MAXN DYNALLSTAT(graph,g,g_sz); DYNALLSTAT(graph,canong,canong_sz); DYNALLSTAT(graph,savedg,savedg_sz); DYNALLSTAT(setword,workspace,workspace_sz); DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(int,savedlab,savedlab_sz); DYNALLSTAT(permutation,perm,perm_sz); DYNALLSTAT(set,active,active_sz); #else static graph g[MAXM*1L*MAXN]; static graph canong[MAXM*1L*MAXN]; static graph savedg[MAXM*1L*MAXN]; static setword workspace[MAXM*2L*WORKSIZE]; static int lab[MAXN]; static int ptn[MAXN]; static int orbits[MAXN]; static int savedlab[MAXN]; static permutation perm[MAXN]; static set active[MAXM]; #endif static DEFAULTOPTIONS_GRAPH(options); static statsblk stats; static int curfile; static FILE *fileptr[MAXIFILES]; static FILE *outfile; static char def_ext[] = DEFEXT; static boolean firstpath; /* used in usernode() */ #define U_NODE 1 /* masks for u values */ #define U_AUTOM 2 #define U_LEVEL 4 #define U_TCELL 8 /* At version 2.4, usertcellproc() is gone */ #define U_REF 16 #ifndef NODEPROC #define NODEPROC usernode #else extern void NODEPROC(graph*,int*,int*,int,int,int,int,int,int); #endif #ifndef AUTOMPROC #define AUTOMPROC userautom #else extern void AUTOMPROC(int,permutation*,int*,int,int,int); #endif #ifndef LEVELPROC #define LEVELPROC userlevel #else extern void LEVELPROC(int*,int*,int,int*,statsblk*,int,int,int,int,int,int); #endif #ifndef REFPROC #define REFPROC NULL #else extern void REFPROC(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); #endif #ifndef INVARPROC #define INVARPROC NULL #define INVARPROCNAME "none" #else extern void INVARPROC(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); #define INVARPROCNAME "user-defined" #endif static struct invarrec { void (*entrypoint)(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); char *name; } invarproc[] = {INVARPROC, INVARPROCNAME, NULL, "none", twopaths, "twopaths", adjtriang, "adjtriang", triples, "triples", quadruples, "quadruples", celltrips, "celltrips", cellquads, "cellquads", cellquins, "cellquins", distances, "distances", indsets, "indsets", cliques, "cliques", cellcliq, "cellcliq", cellind, "cellind", adjacencies, "adjacencies", cellfano, "cellfano", cellfano2, "cellfano2"}; #define NUMINVARS ((int)(sizeof(invarproc)/sizeof(struct invarrec))) #ifdef NLMAP #define GETNW(c,f) do c = getc(f); while (c==' '||c=='\t') #define GETNWC(c,f) do c = getc(f); while (c==' '||c==','||c=='\t') #define GETNWL(c,f) do c = getc(f); while (c==' '||c=='\n'||c=='\t') #else #define GETNW(c,f) do c = getc(f); while (c==' '||c=='\t'||c=='\r') #define GETNWC(c,f) do c = getc(f); while (c==' '||c==','||c=='\t'||c=='\r') #define GETNWL(c,f) do c = getc(f); while (c==' '||c=='\n'||c=='\t'||c=='\r') #endif static void help(FILE*, int); static void userautom(int,permutation*,int*,int,int,int); static void usernode(graph*,int*,int*,int,int,int,int,int,int); static void userlevel(int*,int*,int,int*,statsblk*,int,int,int,int,int,int); #ifdef EXTRADECLS EXTRADECLS #endif static long afound; /***************************************************************************** * * * gethex(f) reads a long hex integer from f, optionally preceded by '=' * * and white space. -1 is returned if the attempt was unsuccessful. * * Not much error checking. * * * *****************************************************************************/ static long gethex(FILE *f) { int c; long i; GETNWL(c,f); if (c != '=') ungetc((char)c,f); if (fscanf(f,"%lx",&i) == 1) return i; else return -1; } /***************************************************************************** * * * permhash(s,n,seed,key) is a function whose value depends only on the * * permutation s, a long seed, and an integer key. It is intended to be * * independent of the machine and whether permutation has 16 or 32 bits. * * n is the length. * * 28 bits of seed and 15 bits of key are significant. * * The result is in the low 28 bits. * * * *****************************************************************************/ static long permhash(permutation *s, int n, long seed, int key) { int i,j,lsh,rsh; long l,res,salt,lshmask; long si; lsh = key & 0xF; rsh = 28 - lsh; salt = (key >> 4) & 0x7FFL; res = seed & 0xFFFFFFFL; lshmask = (1L << lsh) - 1; j = 0; for (i = 0; i < n; ++i) { si = s[i]; l = si & 0xFFFFL; res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; l = si >> 16; res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; } return res; } /***************************************************************************** * * * inthash(s,n,seed,key) is a function whose value depends only on the * * int array p, a long seed, and an integer key. It is intended to be * * independent of the machine and whether int has 16 or 32 bits. * * 64 bits is also ok provided the values are not above 2^31-1. * * n is the length. * * 28 bits of seed and 15 bits of key are significant. * * The result is in the low 28 bits. * * * *****************************************************************************/ static long inthash(int *s, int n, long seed, int key) { int i,j,lsh,rsh; long l,res,salt,lshmask; long si; lsh = key & 0xF; rsh = 28 - lsh; salt = (key >> 4) & 0x7FFL; res = seed & 0xFFFFFFFL; lshmask = (1L << lsh) - 1; j = 0; for (i = 0; i < n; ++i) { si = s[i]; l = si & 0xFFFFL; res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; l = si >> 16; res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt) & 0xFFFFFFFL; } return res; } /***************************************************************************** * bit_tests() Run some configuration tests * *****************************************************************************/ static int bit_tests(void) { int i,j,bad; setword w; printf("NAUTYVERSION=%s NAUTYVERSIONID=%d NAUTYREQUIRED=%d\n", NAUTYVERSION,NAUTYVERSIONID,NAUTYREQUIRED); printf("MAXN=%d MAXM=%d WORDSIZE=%d NAUTY_INFINITY=%d", MAXN,MAXM,WORDSIZE,NAUTY_INFINITY); #ifdef SYS_UNIX printf(" SYS_UNIX"); #endif #ifdef SYS_CRAY printf(" SYS_CRAY"); #endif printf("\n"); bad = 0; if (SIZEOF_INT != sizeof(int)) { printf(" ***** NOTE: sizeof problem (int) *****\n"); ++bad; } if (SIZEOF_LONG != sizeof(long)) { printf(" ***** NOTE: sizeof problem (long) *****\n"); ++bad; } #if SIZEOF_LONGLONG > 0 if (SIZEOF_LONGLONG != sizeof(long long)) { printf(" ***** NOTE: sizeof problem (long long) *****\n"); ++bad; } #endif if (8*sizeof(setword) < WORDSIZE) { printf("\n ***** NOTE: WORDSIZE mismatch *****\n"); ++bad; } if (8*sizeof(setword) > WORDSIZE) { printf("\n WORDSIZE < 8*sizeof(setword) [This is legal.]\n"); } for (i = 0; i < WORDSIZE; ++i) { w = ALLMASK(i); if (POPCOUNT(w) != i) { printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i); ++bad; } } for (i = 0; i < WORDSIZE; ++i) { w = BITMASK(i); if (POPCOUNT(w) != WORDSIZE-i-1) { printf("\n ***** POPCOUNT(BITMASK) error %d *****\n\n",i); ++bad; } } for (i = 0; i < WORDSIZE; ++i) if (POPCOUNT(ALLMASK(i)) != i) { printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i); ++bad; } for (i = 0; i < WORDSIZE; ++i) if (FIRSTBIT(BITT[i]) != i) { printf("\n ***** FIRSTBIT(BITT) error %d *****\n\n",i); ++bad; } w = ALLBITS; for (i = 0; i < WORDSIZE; ++i) { TAKEBIT(j,w); if (j != i) { printf("\n ***** TAKEBIT error %d *****\n\n",i); ++bad; } } for (i = 0; i < WORDSIZE; ++i) if (POPCOUNT(BITT[i]) != 1) { printf("\n ***** POPCOUNT(BITT) error %d *****\n\n",i); ++bad; } for (i = 0; i < WORDSIZE; ++i) { w = 0; for (j = 1; j <= WORDSIZE; ++j) { w |= BITT[(j*97+i)%WORDSIZE]; if (POPCOUNT(w) != j) { printf("\n ***** POPCOUNT(w) error %d %d *****\n\n",i,j); ++bad; } } } if (bad) printf("\nXXXXXXX %d errors found XXXXXXX\n",bad); return bad; } /***************************************************************************** * * * This is a program which illustrates the use of nauty. * * Commands are read from stdin, and may be separated by white space, * * commas or not separated. Output is written to stdout. * * For a short description, see the nauty User's Guide. * * * *****************************************************************************/ int main(int argc, char *argv[]) { int m,n,newm,newn; boolean gvalid,ovalid,cvalid,pvalid,minus,prompt,doquot; int i,worksize,numcells,refcode,umask,qinvar; int oldorg; char *s1,*s2,*invarprocname; int c,d; long li; unsigned long uli; set *gp; double timebefore,timeafter; char filename[200]; int sgn,sgorg,nperm; int bad,multiplicity; boolean options_writeautoms,options_writemarkers; long zseed; long need,found; curfile = 0; fileptr[curfile] = stdin; prompt = FALSE; outfile = stdout; options_writeautoms = options_writemarkers = TRUE; n = m = 1; worksize = 2*WORKSIZE; #if !MAXN n = WORDSIZE; DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut"); DYNALLOC1(int,lab,lab_sz,n,"dreadnaut"); DYNALLOC1(int,ptn,ptn_sz,n,"dreadnaut"); DYNALLOC1(setword,workspace,workspace_sz, worksize,"dreadnaut"); DYNALLOC1(int,orbits,orbits_sz,n,"dreadnaut"); DYNALLOC1(permutation,perm,perm_sz,n,"dreadnaut"); DYNALLOC1(set,active,active_sz,m,"dreadnaut"); n = 1; #endif ran_init(37); bad = 0; umask = 0; pvalid = FALSE; gvalid = FALSE; ovalid = FALSE; cvalid = FALSE; minus = FALSE; labelorg = oldorg = 0; multiplicity = 1; options.userautomproc = userautom; #ifdef INITIALIZE INITIALIZE; #endif invarprocname = "none"; if (prompt) { fprintf(PROMPTFILE,"Dreadnaut version %s.\n",NAUTYVERSION); fprintf(PROMPTFILE,"> "); } nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); nautinv_check(WORDSIZE,1,1,NAUTYVERSIONID); nautil_check(WORDSIZE,1,1,NAUTYVERSIONID); naututil_check(WORDSIZE,1,1,NAUTYVERSIONID); naugraph_check(WORDSIZE,1,1,NAUTYVERSIONID); while (curfile >= 0) if ((c = getc(INFILE)) == EOF || c == '\004') { fclose(INFILE); --curfile; if (curfile >= 0) prompt = FALSE; } else switch (c) { case '\n': /* possibly issue prompt */ if (prompt) fprintf(PROMPTFILE,"> "); minus = FALSE; break; case ' ': /* do nothing */ case '\t': #ifndef NLMAP case '\r': #endif case '\f': break; case '-': /* remember this for next time */ minus = TRUE; break; case '+': /* forget - */ case ',': case ';': minus = FALSE; break; case '<': /* new input file */ minus = FALSE; if (curfile == MAXIFILES - 1) fprintf(ERRFILE,"exceeded maximum input nesting of %d\n\n", MAXIFILES); if (!readstring(INFILE,filename,200)) { fprintf(ERRFILE, "missing file name on '>' command : ignored\n\n"); break; } if ((fileptr[curfile+1] = fopen(filename,"r")) == NULL) { for (s1 = filename; *s1 != '\0'; ++s1) {} for (s2 = def_ext; (*s1 = *s2) != '\0'; ++s1, ++s2) {} fileptr[curfile+1] = fopen(filename,"r"); } if (fileptr[curfile+1] != NULL) { ++curfile; prompt = FALSE; if (prompt) fprintf(PROMPTFILE,"> "); } else fprintf(ERRFILE,"can't open input file\n\n"); break; case '>': /* new output file */ if ((d = getc(INFILE)) != '>') ungetc((char)d,INFILE); if (minus) { minus = FALSE; if (outfile != stdout) { fclose(outfile); outfile = stdout; } } else { if (!readstring(INFILE,filename,200)) { fprintf(ERRFILE, "improper file name, reverting to stdout\n\n"); outfile = stdout; break; } OPENOUT(outfile,filename,d=='>'); if (outfile == NULL) { fprintf(ERRFILE, "can't open output file, reverting to stdout\n\n"); outfile = stdout; } } break; case '!': /* ignore rest of line */ do c = getc(INFILE); while (c != '\n' && c != EOF); if (c == '\n') ungetc('\n',INFILE); break; case 'n': /* read n value */ minus = FALSE; i = getint(INFILE); if (i <= 0 || (MAXN && i > MAXN) || (!MAXN && i > NAUTY_INFINITY-2)) fprintf(ERRFILE, " n can't be less than 1 or more than %d\n\n", MAXN ? MAXN : NAUTY_INFINITY-2); else { gvalid = FALSE; ovalid = FALSE; cvalid = FALSE; pvalid = FALSE; n = i; m = (n + WORDSIZE - 1) / WORDSIZE; #if !MAXN worksize = 2 * m * WORKSIZE; DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut"); DYNALLOC1(int,lab,lab_sz,n,"dreadnaut"); DYNALLOC1(int,ptn,ptn_sz,n,"dreadnaut"); DYNALLOC1(setword,workspace,workspace_sz, worksize,"dreadnaut"); DYNALLOC1(int,orbits,orbits_sz,n,"dreadnaut"); DYNALLOC1(permutation,perm,perm_sz,n,"dreadnaut"); DYNALLOC1(set,active,active_sz,m,"dreadnaut"); #endif } break; case 'g': /* read graph */ minus = FALSE; readgraph(INFILE,g,options.digraph,prompt,FALSE, options.linelength,m,n); gvalid = TRUE; cvalid = FALSE; ovalid = FALSE; break; case 'e': /* edit graph */ minus = FALSE; readgraph(INFILE,g,options.digraph,prompt,gvalid, options.linelength,m,n); gvalid = TRUE; cvalid = FALSE; ovalid = FALSE; break; case 'r': /* relabel graph and current partition */ minus = FALSE; if (gvalid) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif readvperm(INFILE,perm,prompt,n,&nperm); relabel(g,(pvalid ? lab : NULL),perm,canong,m,n); cvalid = FALSE; ovalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case 'R': /* form subgraph */ if (gvalid) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif readvperm(INFILE,perm,prompt,n,&nperm); if (minus && nperm == n || !minus && nperm == 0) fprintf(ERRFILE,"can't form null graph\n\n"); else if (minus) { sublabel(g,perm+nperm,n-nperm,canong,m,n); n = n - nperm; } else { sublabel(g,perm,nperm,canong,m,n); n = nperm; } cvalid = FALSE; pvalid = FALSE; ovalid = FALSE; m = (n + WORDSIZE - 1) / WORDSIZE; } else fprintf(ERRFILE,"g is not defined\n\n"); minus = FALSE; break; case '_': /* complement graph or converse digraph */ minus = FALSE; if ((d = getc(INFILE)) != '_') ungetc((char)d,INFILE); if (gvalid) { if (d == '_') converse(g,m,n); else complement(g,m,n); cvalid = FALSE; ovalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case '@': /* copy canong into savedg */ minus = FALSE; if (cvalid) { #if !MAXN DYNALLOC2(graph,savedg,savedg_sz,n,m,"dreadnaut"); DYNALLOC1(int,savedlab,savedlab_sz,n,"dreadnaut"); #endif sgn = n; for (li = (long)n * (long)m; --li >= 0;) savedg[li] = canong[li]; for (i = n; --i >= 0;) savedlab[i] = lab[i]; sgorg = labelorg; } else fprintf(ERRFILE,"h is not defined\n\n"); break; case '#': /* compare canong to savedg */ if ((d = getc(INFILE)) != '#') ungetc((char)d,INFILE); if (cvalid) { if (sgn > 0) { if (sgn != n) fprintf(OUTFILE, "h and h' have different sizes.\n"); else { for (li = (long)n * (long)m; --li >= 0;) if (savedg[li] != canong[li]) break; if (li >= 0) fprintf(OUTFILE,"h and h' are different.\n"); else { fprintf(OUTFILE, "h and h' are identical.\n"); if (d == '#') putmapping(OUTFILE,savedlab,sgorg, lab,labelorg,options.linelength,n); } } } else fprintf(ERRFILE,"h' is not defined\n\n"); } else fprintf(ERRFILE,"h is not defined\n\n"); break; case 'j': /* relabel graph randomly */ minus = FALSE; if (gvalid) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif ranperm(perm,n); relabel(g,(pvalid ? lab : NULL),perm,canong,m,n); cvalid = FALSE; ovalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case 'v': /* write vertex degrees */ minus = FALSE; if (gvalid) putdegs(OUTFILE,g,options.linelength,m,n); else fprintf(ERRFILE,"g is not defined\n\n"); break; case '%': /* do Mathon doubling operation */ minus = FALSE; if (gvalid) { #if !MAXN if (2L * ((long)n + 1L) > NAUTY_INFINITY-2) { fprintf(ERRFILE, "n can't be more than %d\n\n",NAUTY_INFINITY-2); break; } #else if (2L * ((long)n + 1L) > MAXN) { fprintf(ERRFILE,"n can't be more than %d\n\n",MAXN); break; } #endif newn = 2 * (n + 1); newm = (newn + WORDSIZE - 1) / WORDSIZE; #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif for (li = (long)n * (long)m; --li >= 0;) canong[li] = g[li]; #if !MAXN DYNALLOC2(graph,g,g_sz,newn,newm,"dreadnaut"); DYNALLOC1(int,lab,lab_sz,newn,"dreadnaut"); DYNALLOC1(int,ptn,ptn_sz,newn,"dreadnaut"); worksize = 2*WORKSIZE*newm; DYNALLOC1(setword,workspace,workspace_sz, worksize,"dreadnaut"); DYNALLOC1(int,orbits,orbits_sz,newn,"dreadnaut"); DYNALLOC1(permutation,perm,perm_sz,newn,"dreadnaut"); DYNALLOC1(set,active,active_sz,newm,"dreadnaut"); #endif mathon(canong,m,n,g,newm,newn); m = newm; n = newn; cvalid = FALSE; ovalid = FALSE; pvalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case 's': /* generate random graph */ minus = FALSE; i = getint(INFILE); if (i <= 0) i = 2; rangraph(g,options.digraph,i,m,n); gvalid = TRUE; cvalid = FALSE; ovalid = FALSE; break; case 'q': /* quit */ if (bad == 0) printf("OK"); printf("\n"); exit(bad); break; case '"': /* copy comment to output */ minus = FALSE; copycomment(INFILE,OUTFILE,'"'); break; case 'I': /* do refinement and invariants procedure */ if (!pvalid) unitptn(lab,ptn,&numcells,n); cellstarts(ptn,0,active,m,n); doref(g,lab,ptn,0,&numcells,&qinvar,perm,active,&refcode, options.userrefproc ? options.userrefproc : (m == 1 ? refine1 : refine), options.invarproc,0,0, options.invararg,options.digraph,m,n); fprintf(OUTFILE," %d cell%s; code = %x", SS(numcells,"","s"),refcode); if (options.invarproc != NULL) fprintf(OUTFILE," (%s %s)",invarprocname, (qinvar == 2 ? "worked" : "failed")); fprintf(OUTFILE,"\n"); if (numcells > 1) pvalid = TRUE; break; case 'i': /* do refinement */ if (!pvalid) unitptn(lab,ptn,&numcells,n); cellstarts(ptn,0,active,m,n); if (options.userrefproc) (*options.userrefproc) (g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); else if (m == 1) refine1(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); else refine(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); fprintf(OUTFILE," %d cell%s; code = %x\n", SS(numcells,"","s"),refcode); if (numcells > 1) pvalid = TRUE; break; case 'x': /* execute nauty */ minus = FALSE; ovalid = FALSE; cvalid = FALSE; if (!gvalid) { fprintf(ERRFILE,"g is not defined\n\n"); break; } if (pvalid) { /* fprintf(OUTFILE,"[fixing partition]\n"); */ options.defaultptn = FALSE; } else options.defaultptn = TRUE; options.outfile = outfile; if (options.getcanon) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif } firstpath = TRUE; options.writeautoms = FALSE; options.writemarkers = FALSE; for (i = 0; i < multiplicity; ++i) { afound = 1; nauty(g,lab,ptn,NULL,orbits,&options,&stats,workspace, worksize,m,n,canong); options.writeautoms = FALSE; options.writemarkers = FALSE; } if (stats.errstatus != 0) fprintf(ERRFILE, "nauty returned error status %d [this can't happen]\n\n", stats.errstatus); else { if (options.getcanon) cvalid = TRUE; ovalid = TRUE; /* fprintf(OUTFILE, "%d orbit%s",SS(stats.numorbits,"","s")); if (stats.grpsize2 == 0) fprintf(OUTFILE,"; grpsize=%.0f",stats.grpsize1+0.1); else { while (stats.grpsize1 >= 10.0) { stats.grpsize1 /= 10.0; ++stats.grpsize2; } fprintf(OUTFILE,"; grpsize=%12.10fe%d", stats.grpsize1,stats.grpsize2); } fprintf(OUTFILE,"; %d gen%s", SS(stats.numgenerators,"","s")); fprintf(OUTFILE,"; %lu node%s",SS(stats.numnodes,"","s")); if (stats.numbadleaves) fprintf(OUTFILE," (%lu bad lea%s)", SS(stats.numbadleaves,"f","ves")); fprintf(OUTFILE,"; maxlev=%d\n", stats.maxlevel); fprintf(OUTFILE,"tctotal=%lu",stats.tctotal); if (options.getcanon) fprintf(OUTFILE,"; canupdates=%lu",stats.canupdates); fprintf(OUTFILE,"\n"); if (options.invarproc != NULL && options.maxinvarlevel != 0) { fprintf(OUTFILE,"invarproc \"%s\" succeeded %lu/%lu", invarprocname,stats.invsuccesses,stats.invapplics); if (stats.invarsuclevel > 0) fprintf(OUTFILE," beginning at level %d.\n", stats.invarsuclevel); else fprintf(OUTFILE,".\n"); } */ } break; case 'f': /* read initial partition */ if (minus) { pvalid = FALSE; minus = FALSE; } else { readptn(INFILE,lab,ptn,&numcells,prompt,n); pvalid = TRUE; } break; case 't': /* type graph */ minus = FALSE; if (!gvalid) fprintf(ERRFILE,"g is not defined\n\n"); else putgraph(OUTFILE,g,options.linelength,m,n); break; case 'T': /* type graph preceded by n, $ and g commands */ minus = FALSE; if (!gvalid) fprintf(ERRFILE,"g is not defined\n\n"); else { fprintf(OUTFILE,"n=%d $=%d g\n",n,labelorg); putgraph(OUTFILE,g,options.linelength,m,n); fprintf(OUTFILE,"$$\n"); } break; case 'u': /* call user procs */ if (minus) { umask = 0; minus = FALSE; } else { umask = getint(INFILE); if (umask < 0) umask = ~0; } if (umask & U_NODE) options.usernodeproc = NODEPROC; else options.usernodeproc = NULL; if (umask & U_AUTOM) options.userautomproc = AUTOMPROC; else options.userautomproc = userautom; if (umask & U_LEVEL) options.userlevelproc = LEVELPROC; else options.userlevelproc = NULL; if (umask & U_TCELL) fprintf(ERRFILE,"usertcellproc() gone at version 2.4\n\n"); if (umask & U_REF) options.userrefproc = REFPROC; else options.userrefproc = NULL; break; case 'o': /* type orbits */ minus = FALSE; need = gethex(INFILE); if (ovalid) { found = inthash(orbits,n,761L,3); if (found != need) { printf("\nERROR: need=%lx found=%lx\n",need,found); ++bad; } else printf("+"); fflush(stdout); } else fprintf(ERRFILE,"orbits are not defined\n\n"); break; case 'b': /* type canonlab and canong */ minus = FALSE; need = gethex(INFILE); if (cvalid) { zseed = n; for (i = 0, gp = canong; i < n; ++i, gp += m) zseed = sethash(gp,n,zseed,3109); found = inthash(lab,n,165,2) ^ zseed; if (found != need) { printf("\nERROR: need=%lx found=%lx\n",need,found); ++bad; } else printf("+"); fflush(stdout); } else fprintf(ERRFILE,"automorphisms are not defined\n\n"); break; case 'z': /* type hashcode for canong */ minus = FALSE; if (cvalid) { zseed = n; for (i = 0, gp = canong; i < n; ++i, gp += m) zseed = sethash(gp,n,zseed,321); fprintf(OUTFILE,"[%7lx",zseed); for (i = 0, gp = canong; i < n; ++i, gp += m) zseed = sethash(gp,n,zseed,3109); fprintf(OUTFILE," %7lx",zseed); for (i = 0, gp = canong; i < n; ++i, gp += m) zseed = sethash(gp,n,zseed,4317); fprintf(OUTFILE," %7lx]\n",zseed); } else fprintf(ERRFILE,"h is not defined\n\n"); break; case 'c': /* set getcanon option */ options.getcanon = !minus; minus = FALSE; break; case 'w': /* read size of workspace */ minus = FALSE; worksize = getint(INFILE); #if !MAXN DYNALLOC1(setword,workspace,workspace_sz,worksize,"dreadnaut"); #else if (worksize > 2*MAXM*WORKSIZE) { fprintf(ERRFILE, "too big - setting worksize = %d\n\n", 2*MAXM*WORKSIZE); worksize = 2*MAXM*WORKSIZE; } #endif break; case 'l': /* read linelength for output */ options.linelength = getint(INFILE); minus = FALSE; break; case 'y': /* set tc_level field of options */ options.tc_level = getint(INFILE); minus = FALSE; break; case 'M': /* set multiplicity */ multiplicity = getint(INFILE); if (multiplicity <= 0) multiplicity = 1; minus = FALSE; break; case 'k': /* set invarlev fields of options */ options.mininvarlevel = getint(INFILE); options.maxinvarlevel = getint(INFILE); minus = FALSE; break; case 'K': /* set invararg field of options */ options.invararg = getint(INFILE); minus = FALSE; break; case '*': /* set invarproc field of options */ minus = FALSE; d = getint(INFILE); if (d >= -1 && d <= NUMINVARS-2) { options.invarproc = invarproc[d+1].entrypoint; invarprocname = invarproc[d+1].name; if (options.invarproc != NULL) { options.mininvarlevel = 0; options.maxinvarlevel = 1; if (options.invarproc == indsets || options.invarproc == cliques || options.invarproc == cellind || options.invarproc == cellcliq) options.invararg = 3; else options.invararg = 0; } } else fprintf(ERRFILE,"no such vertex-invariant\n\n"); break; case 'a': /* set writeautoms option */ minus = FALSE; need = gethex(INFILE); if (ovalid) { if (afound != need) { printf("\nERROR: need=%lx found=%lx\n",need,afound); ++bad; } else printf("+"); fflush(stdout); } else fprintf(ERRFILE,"automorphisms are not defined\n\n"); break; case 'C': /* check bit and set operations */ minus = FALSE; bit_tests(); break; case 'm': /* set writemarkers option */ options_writemarkers = !minus; minus = FALSE; break; case 'p': /* set cartesian option */ options.cartesian = !minus; minus = FALSE; break; case 'd': /* set digraph option */ if (options.digraph && minus) gvalid = FALSE; options.digraph = !minus; minus = FALSE; break; case '$': /* set label origin */ if ((d = getc(INFILE)) == '$') labelorg = oldorg; else { ungetc((char)d,INFILE); oldorg = labelorg; i = getint(INFILE); if (i < 0) fprintf(ERRFILE,"labelorg must be >= 0\n\n"); else labelorg = i; } break; case '?': /* type options, etc. */ minus = FALSE; fprintf(OUTFILE,"m=%d n=%d labelorg=%d",m,n,labelorg); if (!gvalid) fprintf(OUTFILE," g=undef"); else { uli = 0; for (i = 0, gp = g; i < n; ++i, gp += m) uli += setsize(gp,m); if (options.digraph) fprintf(OUTFILE," arcs=%lu",uli); else fprintf(OUTFILE," edges=%lu",uli/2); } fprintf(OUTFILE," options=(%cc%ca%cm%cp%cd", PM(options.getcanon),PM(options_writeautoms), PM(options_writemarkers),PM(options.cartesian), PM(options.digraph)); if (umask & 31) fprintf(OUTFILE," u=%d",umask&31); if (options.tc_level > 0) fprintf(OUTFILE," y=%d",options.tc_level); if (options.mininvarlevel != 0 || options.maxinvarlevel != 0) fprintf(OUTFILE," k=(%d,%d)", options.mininvarlevel,options.maxinvarlevel); if (options.invararg > 0) fprintf(OUTFILE," K=%d",options.invararg); if (multiplicity > 1) fprintf(OUTFILE," M=%d",multiplicity); fprintf(OUTFILE,")\n"); fprintf(OUTFILE,"linelen=%d worksize=%d input_depth=%d", options.linelength,worksize,curfile); if (options.invarproc != NULL) fprintf(OUTFILE," invarproc=%s",invarprocname); if (pvalid) fprintf(OUTFILE,"; %d cell%s",SS(numcells,"","s")); else fprintf(OUTFILE,"; 1 cell"); fprintf(OUTFILE,"\n"); if (OUTFILE != PROMPTFILE) fprintf(PROMPTFILE,"m=%d n=%d depth=%d labelorg=%d\n", m,n,curfile,labelorg); break; case '&': /* list the partition and possibly the quotient */ need = gethex(INFILE); if ((d = getc(INFILE)) == '&') doquot = TRUE; else { ungetc((char)d,INFILE); doquot = FALSE; } minus = FALSE; if (pvalid) { for (i = 0; i < n; ++i) if (ptn[i] > n) ptn[i] = n; found = inthash(lab,n,4123,12) ^ inthash(ptn,n,4123,12); } else found = 1001; if (found != need) { printf("\nERROR: need=%lx found=%lx\n",need,found); ++bad; } else printf("+"); fflush(stdout); if (doquot) { /* if (!pvalid) unitptn(lab,ptn,&numcells,n); putquotient(OUTFILE,g,lab,ptn,0,options.linelength,m,n); */ } break; case 'h': /* type help information */ case 'H': minus = FALSE; printf("a, o, & are reassigned and output is suppressed\n"); printf("Use dreadnaut for other functions\n"); break; default: /* illegal command */ fprintf(ERRFILE,"'%c' is illegal - type 'h' for help\n\n",c); flushline(INFILE); if (prompt) fprintf(PROMPTFILE,"> "); break; } /* end of switch */ return 0; } /***************************************************************************** * * * help(f,i) writes help information to file f (i = 0,1). * * * *****************************************************************************/ static void help(FILE *f, int i) { #define H(ss) fprintf(f," %s\n",ss); if (i == 0) { H("+- a : write automs v : write degrees *=# : select invariant:") H(" b : write canong w=# : set worksize") H("+- c : canonise x : run nauty -1 = user-defined") H("+- d : digraph or loops y=# : set tc_level 0 = none") H(" e : edit graph z : write hashcode 1 = twopaths") H("-f, f=#, f=[...] : set colours 2 = adjtriang(K=0,1)") H(" g : read graph $=# : set origin 3 = triples") H(" h,H : help $$ : restore origin 4 = quadruples") H(" i : refine ? : type options 5 = celltrips") H(" I : refine using invar _ : compl __ : conv 6 = cellquads") H(" j : relabel randomly % : Mathon doubling 7 = cellquins") H("k=# # : set invar levels & : type colouring 8 = distances(K)") H(" K=# : set invar param && : + quotient matrix 9 = indsets(K)") H(" l=# : set line length >ff : write to file 10 = cliques(K)") H("+- m : write markers >>ff : append to file 11 = cellcliq(K)") H(" n=# : set order -> : revert to stdout 12 = cellind(K)") H(" o : write orbits numnodes,numcells,stats->numorbits,stats->numgenerators); */ } nauty24r2/formats.txt0000600000604200001440000001137211405401174013515 0ustar bdmusersDescription of graph6 and sparse6 encodings ------------------------------------------- Brendan McKay, bdm@cs.anu.edu.au Updated May 2005. General principles: All numbers in this description are in decimal unless obviously in binary. Apart from the header, there is one object per line. Apart from the header and the end-of-line characters, all bytes have a value in the range 63-126 (which are all printable ASCII characters). A file of objects is a text file, so whatever end-of-line convention is locally used is fine). Bit vectors: A bit vector x of length k can be represented as follows. Example: 1000101100011100 (1) Pad on the right with 0 to make the length a multiple of 6. Example: 100010110001110000 (2) Split into groups of 6 bits each. Example: 100010 110001 110000 (3) Add 63 to each group, considering them as bigendian binary numbers. Example: 97 112 111 These values are then stored one per byte. So, the number of bytes is ceiling(k/6). Let R(x) denote this representation of x as a string of bytes. Small nonnegative integers: Let n be an integer in the range 0-68719476735 (2^36-1). If 0 <= n <= 62, define N(n) to be the single byte n+63. If 63 <= n <= 258047, define N(n) to be the four bytes 126 R(x), where x is the bigendian 18-bit binary form of n. If 258048 <= n <= 68719476735, define N(n) to be the eight bytes 126 126 R(x), where x is the bigendian 36-bit binary form of n. Examples: N(30) = 93 N(12345) = N(000011 000000 111001) = 126 66 63 120 N(460175067) = N(000000 011011 011011 011011 011011 011011) = 126 126 63 90 90 90 90 90 Description of graph6 format. ---------------------------- Data type: simple undirected graphs of order 0 to 68719476735. Optional Header: >>graph6<< (without end of line!) File name extension: .g6 One graph: Suppose G has n vertices. Write the upper triangle of the adjacency matrix of G as a bit vector x of length n(n-1)/2, using the ordering (0,1),(0,2),(1,2),(0,3),(1,3),(2,3),...,(n-1,n). Then the graph is represented as N(n) R(x). Example: Suppose n=5 and G has edges 0-2, 0-4, 1-3 and 3-4. x = 0 10 010 1001 Then N(n) = 68 and R(x) = R(010010 100100) = 81 99. So, the graph is 68 81 99. Description of sparse6 format. ------------------------------ Data type: Undirected graphs of order 0 to 68719476735. Loops and multiple edges are permitted. Optional Header: >>sparse6<< (without end of line!) File name extension: .s6 General structure: Each graph occupies one text line. Except for end-of-line characters, each byte has the form 63+x, where 0 <= x <= 63. The byte encodes the six bits of x. The encoded graph consists of: (1) The character ':'. (This is present to distinguish the code from graph6 format.) (2) The number of vertices. (3) A list of edges. (4) end-of-line Loops and multiple edges are supported, but not directed edges. Number of vertices n: 1, 4, or 8 bytes N(n) as above. This is the same as graph6 format. List of edges: Let k be the number of bits needed to represent n-1 in binary. The remaining bytes encode a sequence b[0] x[0] b[1] x[1] b[2] x[2] ... b[m] x[m] Each b[i] occupies 1 bit, and each x[i] occupies k bits. Pack them together in bigendian order, and pad up to a multiple of 6 as follows: 1. If (n,k) = (2,1), (4,2), (8,4) or (16,5), and vertex n-2 has an edge but n-1 doesn't have an edge, and there are k+1 or more bits to pad, then pad with one 0-bit and enough 1-bits to complete the multiple of 6. 2. Otherwise, pad with enough 1-bits to complete the multiple of 6. These rules are to match the gtools procedures, and to avoid the padding from looking like an extra loop in unusual cases. Then represent this bit-stream 6 bits per byte as indicated above. The vertices of the graph are 0..n-1. The edges encoded by this sequence are determined thus: v = 0 for i from 0 to m do if b[i] = 1 then v = v+1 endif; if x[i] > v then v = x[i] else output {x[i],v} endif endfor In decoding, an incomplete (b,x) pair at the end is discarded. Example: :Fa@x^ ':' indicates sparse6 format. Subtract 63 from the other bytes and write them in binary, six bits each. 000111 100010 000001 111001 011111 The first byte is not 63, so it is n. n=7 n-1 needs 3 bits (k=3). Write the other bits in groups of 1 and k: 1 000 1 000 0 001 1 110 0 101 1 111 This is the b/x sequence 1,0 1,0 0,1 1,6 0,5 1,7. The 1,7 at the end is just padding. The remaining parts give the edges 0-1 0-2 1-2 5-6. nauty24r2/genrang.c0000600000604200001440000002714311274163463013103 0ustar bdmusers/* genrang.c version 1.4; B D McKay, Aug 8, 2008 */ #define USAGE \ "genrang [-P#|-P#/#|-e#|-r#|-R#] [-l#] [-m#] [-a] [-s|-g] [-S#] [-q] n num [outfile]" #define HELPTEXT \ " Generate random graphs.\n\ n : number of vertices\n\ num : number of graphs\n\ \n\ -s : Write in sparse6 format (default)\n\ -g : Write in graph6 format\n\ -P#/# : Give edge probability; -P# means -P1/#.\n\ -e# : Give the number of edges\n\ -r# : Make regular of specified degree\n\ -R# : Make regular of specified degree but output\n\ as vertex count, edgecount, then list of edges\n\ -l# : Maximum loop multiplicity (default 0)\n\ -m# : Maximum multiplicity of non-loop edge (default and minimum 1)\n\ -l and -m are only permitted with -R and -r without -g\n\ -a : Make invariant under a random permutation\n\ -S# : Specify random generator seed (default nondeterministic)\n\ -q : suppress auxiliary output\n\ \n\ Incompatible: -P,-e,-r,-R; -s,-g,-R; -R,-a; -s,-g & -l,-m.\n" #define MAXREG 88 /* Max value for -r or -R switch */ /************************************************************************* Oct 27, 2004 : corrected handling of -P values **************************************************************************/ #include "gtools.h" /*************************************************************************/ static void perminvar(graph *g, permutation *perm, int m, int n) /* Add to g the least number of edges needed to make perm an automorphism. */ { int i,j,ii,jj; set *gi,*gpi; for (i = 0, gi = (set*)g; i < n; ++i, gi += m) { gpi = g + m * 1L * perm[i]; for (j = -1; (j = nextelement(gi,m,j)) >= 0; ) if (!ISELEMENT(gpi,perm[j])) { ii = perm[i]; jj = perm[j]; while (ii != i || jj != j) { ADDELEMENT(g+m*1L*ii,jj); ii = perm[ii]; jj = perm[jj]; } } } } /**************************************************************************/ static void ranedges(long e, graph *g, int m, int n) /* Random graph with n vertices and e edges */ { unsigned long ln,li,nc2,ned,sofar; set *gi,*gj; int i,j; ln = n; nc2 = (ln&1) ? ln*((ln-1)/2) : (ln/2)*(ln-1); if (e + e > nc2) ned = nc2 - e; else ned = e; sofar = 0; for (li = m*ln; --li != 0;) g[li] = 0; g[0] = 0; while (sofar < ned) { i = KRAN(n); do { j = KRAN(n); } while (i == j); gi = GRAPHROW(g,i,m); if (!ISELEMENT(gi,j)) { ADDELEMENT(gi,j); gj = GRAPHROW(g,j,m); ADDELEMENT(gj,i); ++sofar; } } if (ned != e) complement(g,m,n); } /**************************************************************************/ static void makeranreg(int *cub, int degree, int multmax, int loopmax, int n) /* Make a random regular graph in cub[]. Each consecutive degree entries of cub[] is set to the neighbours of one vertex. The length of cub had better be at least degree*n */ { long i,j,k,v,w,nn,mult; boolean ok; set *gi; #if MAXN int deg[MAXN],p[MAXREG*MAXN]; #else DYNALLSTAT(int,deg,deg_sz); DYNALLSTAT(int,p,p_sz); DYNALLSTAT(int,loops,loops_sz); DYNALLOC1(int,deg,deg_sz,n,"genrang"); DYNALLOC2(int,p,p_sz,degree,n,"genrang"); DYNALLOC1(int,loops,loops_sz,n,"genrang"); #endif nn = n; for (i = j = 0; i < nn; ++i) for (k = 0; k < degree; ++k) p[j++] = i; do { ok = TRUE; for (j = degree*nn-1; j >= 1; j -= 2) { i = KRAN(j); k = p[j-1]; p[j-1] = p[i]; p[i] = k; } for (i = 0; i < nn; ++i) deg[i] = loops[i] = 0; for (j = degree*nn-1; j >= 1;) { v = p[j--]; w = p[j--]; if (v == w && ++loops[v] > loopmax) { ok = FALSE; break; } if (v != w && multmax < degree) { mult = 0; for (i = deg[w]; --i >= 0;) if (cub[degree*w+i] == v && ++mult >= multmax) break; if (i >= 0) { ok = FALSE; break; } } cub[degree*w+deg[w]++] = v; cub[degree*v+deg[v]++] = w; } } while (!ok); } /**************************************************************************/ static void ranregR(FILE *f, int degree, int multmax, int loopmax, int n) /* Make a random regular graph of order n and degree d and write it in f, as number of vertices, number of edges, list of edges */ { long i,j,k,l; set *gi; int loops; #if MAXN int cub[MAXREG*MAXN]; #else DYNALLSTAT(int,cub,cub_sz); DYNALLOC2(int,cub,cub_sz,degree,n,"genrang"); #endif makeranreg(cub,degree,multmax,loopmax,n); fprintf(f,"%d %ld\n",n,n*(long)degree/2); l = j = 0; for (i = 0; i < n; ++i) { loops = 0; for (k = 0; k < degree; ++k, ++j) if (i < cub[j] || i == cub[j] && (++loops & 1) == 0) { if (l > 0 && l % 5 == 0) fprintf(f,"\n"); fprintf(f," %ld %d",i,cub[j]); ++l; } } fprintf(f,"\n"); } /**************************************************************************/ static void ranreg(int degree, graph *g, int m, int n) /* Make a random simple regular graph of order n and degree d and return it in g. */ { int i,j,k; set *gi; #if MAXN int cub[MAXREG*MAXN]; #else DYNALLSTAT(int,cub,cub_sz); DYNALLOC1(int,cub,cub_sz,degree*n,"genrang"); #endif makeranreg(cub,degree,1,0,n); j = 0; for (i = 0, gi = (set*)g; i < n; ++i, gi += m) { EMPTYSET(gi,m); for (k = 0; k < degree; ++k) { ADDELEMENT(gi,cub[j]); j++; } } } /**************************************************************************/ static void ranreg_sg(int degree, sparsegraph *sg, int multmax, int loopmax, int n) /* Make a sparse random regular graph of order n and degree d * and return it in sg. */ { int i,j,k,k0,deg,loops,nde; #if MAXN int cub[MAXREG*MAXN]; #else DYNALLSTAT(int,cub,cub_sz); DYNALLOC1(int,cub,cub_sz,degree*n,"genrang"); #endif makeranreg(cub,degree,multmax,loopmax,n); SG_ALLOC(*sg,n,degree*n,"genrang"); sg->nv = n; j = nde = 0; for (i = 0; i < n; ++i) { sg->v[i] = k0 = i*degree; loops = deg = 0; for (k = 0; k < degree; ++k, ++j) { if (cub[j] == i) { /* Loops are in cub twice but sg once */ ++loops; if ((loops&1)) sg->e[k0+deg++] = i; } else sg->e[k0+deg++] = cub[j]; } sg->d[i] = deg; nde += deg; } sg->nde = nde; } /**************************************************************************/ /**************************************************************************/ int main(int argc, char *argv[]) { int m,n,codetype; int argnum,j; char *arg,sw; boolean badargs; boolean gswitch,sswitch,qswitch,Sswitch,Rswitch,lswitch; boolean aswitch,P1switch,P2switch,eswitch,rswitch,mswitch; long numgraphs,nout,P1value,P2value,evalue,rvalue; nauty_counter ln,nc2; int Svalue,loopmax,multmax; static FILE *outfile; char *outfilename; sparsegraph sg; boolean usesparse; #if MAXN graph g[MAXM*1L*MAXN]; permutation perm[MAXN]; #else DYNALLSTAT(graph,g,g_sz); DYNALLSTAT(permutation,perm,perm_sz); #endif HELP; gswitch = sswitch = qswitch = Sswitch = Rswitch = FALSE; aswitch = P1switch = P2switch = eswitch = rswitch = FALSE; lswitch = mswitch = FALSE; outfilename = NULL; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('g',gswitch) else SWBOOLEAN('s',sswitch) else SWBOOLEAN('a',aswitch) else SWBOOLEAN('q',qswitch) else SWLONG('P',P1switch,P1value,"genrang -P") else SWLONG('/',P2switch,P2value,"genrang -P") else SWLONG('e',eswitch,evalue,"genrang -e") else SWLONG('r',rswitch,rvalue,"genrang -r") else SWLONG('R',Rswitch,rvalue,"genrang -R") else SWINT('S',Sswitch,Svalue,"genrang -S") else SWINT('l',lswitch,loopmax,"genrang -l") else SWINT('m',mswitch,multmax,"genrang -m") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) { if (sscanf(arg,"%d",&n) != 1 || n < 1) badargs = TRUE; } else if (argnum == 2) { if (sscanf(arg,"%ld",&numgraphs) != 1 || numgraphs < 1) badargs = TRUE; } else if (argnum == 3) outfilename = arg; else badargs = TRUE; } } if ((gswitch!=0) + (sswitch!=0) > 1) gt_abort(">E genrang: -gs are incompatible\n"); if (gswitch) codetype = GRAPH6; else codetype = SPARSE6; if (P1switch && !P2switch) { P2value = P1value; P1value = 1; } else if (P2switch && !P1switch) { P1value = 1; P1switch = TRUE; } if (P1switch && (P1value < 0 || P2value <= 0 || P1value > P2value)) gt_abort(">E genrang: bad value for -P switch\n"); if ((P1switch!=0) + (eswitch!=0) + (rswitch!=0) + (Rswitch!=0) > 1) gt_abort(">E genrang: -Per are incompatible\n"); if ((sswitch!=0) + (gswitch!=0) + (Rswitch!=0) > 1) gt_abort(">E genrang: -sgR are incompatible\n"); if ((aswitch!=0) + (Rswitch!=0) > 1) gt_abort(">E genrang: -aR are incompatible\n"); if (!lswitch) loopmax = 0; if (!mswitch) multmax = 1; if ((loopmax>0 || multmax>1) && !(Rswitch || rswitch && !gswitch)) gt_abort(">E genrang: -l,-m need -R or -r without -g\n"); if (multmax < 1 || loopmax < 0) gt_abort(">E genrang: bad value for -l or -m\n"); if (argnum < 2 || argnum > 3) badargs = TRUE; if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!Sswitch) { #ifdef INITSEED INITSEED; ran_init(seed); #endif } else ran_init(Svalue); if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } m = (n + WORDSIZE + 1) / WORDSIZE; usesparse = rswitch && !aswitch && codetype==SPARSE6; #if !MAXN if (!Rswitch && !usesparse) { DYNALLOC2(graph,g,g_sz,n,m,"genrang"); if (aswitch) DYNALLOC1(permutation,perm,perm_sz,n,"genrang"); } #endif rswitch = rswitch || Rswitch; if (rswitch && rvalue > MAXREG) { fprintf(stderr, ">E -r/-R is only implemented for degree <= %d\n",MAXREG); exit(1); } ln = n; nc2 = ln*loopmax + ln*(ln-1)/2*multmax; if (eswitch && evalue > nc2) { fprintf(stderr, ">E There are no graphs of order %d and %ld edges\n", n,evalue); exit(1); } if (rswitch && ((n&1) != 0 && (rvalue&1) != 0 || rvalue > (n-1)*multmax+2*loopmax)) { fprintf(stderr, ">E There are no such graphs of order %d and degree %ld\n", n,rvalue); exit(1); } if (!P1switch) { P1value = 1; P2value = 2; } SG_INIT(sg); for (nout = 1; nout <= numgraphs; ++nout) { if (eswitch) ranedges(evalue,g,m,n); else if (Rswitch) ranregR(outfile,rvalue,multmax,loopmax,n); else if (rswitch && usesparse) ranreg_sg(rvalue,&sg,multmax,loopmax,n); else if (rswitch && !usesparse) ranreg(rvalue,g,m,n); else rangraph2(g,FALSE,P1value,P2value,m,n); if (Rswitch) continue; if (aswitch) { ranperm(perm,n); perminvar(g,perm,m,n); } if (codetype == SPARSE6) if (usesparse) { sortlists_sg(&sg); writes6_sg(outfile,&sg); } else writes6(outfile,g,m,n); else writeg6(outfile,g,m,n); } exit(0); } nauty24r2/nug.pdf0000600000604200001440000137665411274163472012621 0ustar bdmusers%PDF-1.4 %ÐÔÅØ 5 0 obj << /S /GoTo /D (section.0) >> endobj 8 0 obj (How to use this Guide.) endobj 9 0 obj << /S /GoTo /D (section.1) >> endobj 12 0 obj (Introduction.) endobj 13 0 obj << /S /GoTo /D (section.2) >> endobj 16 0 obj (The Algorithm.) endobj 17 0 obj << /S /GoTo /D (section.3) >> endobj 20 0 obj (Data Structures.) endobj 21 0 obj << /S /GoTo /D (section.4) >> endobj 24 0 obj (Size limits.) endobj 25 0 obj << /S /GoTo /D (section.5) >> endobj 28 0 obj (Parameters.) endobj 29 0 obj << /S /GoTo /D (section.6) >> endobj 32 0 obj (Output.) endobj 33 0 obj << /S /GoTo /D (section.7) >> endobj 36 0 obj (Examples.) endobj 37 0 obj << /S /GoTo /D (section.8) >> endobj 40 0 obj (User-defined procedures.) endobj 41 0 obj << /S /GoTo /D (section.9) >> endobj 44 0 obj (Vertex-invariants.) endobj 45 0 obj << /S /GoTo /D (section.10) >> endobj 48 0 obj (Writing programs which call nauty.) endobj 49 0 obj << /S /GoTo /D (section.11) >> endobj 52 0 obj (Programming with sparse representation.) endobj 53 0 obj << /S /GoTo /D (section.12) >> endobj 56 0 obj (Variations.) endobj 57 0 obj << /S /GoTo /D (section.13) >> endobj 60 0 obj (Installing nauty and dreadnaut.) endobj 61 0 obj << /S /GoTo /D (section.14) >> endobj 64 0 obj (Efficiency.) endobj 65 0 obj << /S /GoTo /D (section.15) >> endobj 68 0 obj (dreadnaut.) endobj 69 0 obj << /S /GoTo /D (section.16) >> endobj 72 0 obj (gtools.) endobj 73 0 obj << /S /GoTo /D (section.17) >> endobj 76 0 obj (Recent changes.) endobj 77 0 obj << /S /GoTo /D (section.18) >> endobj 80 0 obj (Sample programs which call nauty.) endobj 81 0 obj << /S /GoTo /D (subsection.18.1) >> endobj 84 0 obj (nautyex1.c : Packed form with static allocation) endobj 85 0 obj << /S /GoTo /D (subsection.18.2) >> endobj 88 0 obj (nautyex2.c : Packed form with dynamic allocation) endobj 89 0 obj << /S /GoTo /D (subsection.18.3) >> endobj 92 0 obj (nautyex3.c : Finding the whole automorphism group) endobj 93 0 obj << /S /GoTo /D (subsection.18.4) >> endobj 96 0 obj (nautyex4.c : Sparse form with dynamic allocation) endobj 97 0 obj << /S /GoTo /D (subsection.18.5) >> endobj 100 0 obj (nautyex5.c : Determining an isomorphism, sparse form) endobj 101 0 obj << /S /GoTo /D (section.19) >> endobj 104 0 obj (Graph formats used by gtools programs) endobj 105 0 obj << /S /GoTo /D (section.20) >> endobj 108 0 obj (Help texts for gtools programs) endobj 109 0 obj << /S /GoTo /D [110 0 R /FitV ] >> endobj 135 0 obj << /Length 1213 /Filter /FlateDecode >> stream xÚµWMsÛ6½ëWàVj&DñMòÖÄvݦӴµ•ôç“°Ä’RA²¶Û?ßI–J:<´—@F–oß~àaAÐt½ ë»ÕâÛïi‚ÁJ1‰Vˆ*Š)aHÉ 'L¡U>Gî»çå—Õ{°V/­e‚)€5˜}lý¦]Æœ°èº/ ãÞI>-“,2¶-·ßdXÀ>  )¢s¡˜|¡8Šy†É<ô;kšB»o™Š.±[“èçü'½di´§&P†3åHC€B•B3¢¸#„{KÎ%8#u¦1O —(fÃoo}ivÚvµiœ‡rmÜÊ£‹m½ë;cý_·yišÜ8h¤0I 2œ9pô¶o;««r`ætYЕÿëcSþ¹„X\nºC0(&˜¥ibèB\î—1ük¬Õá­Û¼Xy†„ò&ìïý†˜ù˘™Ä4e€ï‡ˆï‹ú»¼Åºé±)z¬û±âÄ ƒ(ƒôrÿᇭ‹À‡Q¿ ¸¤‘õ•o|å€]èˆTšPœHȜȀC³puÆ/­ûz— Ьk`÷ãæzá)RœI9€ œ ×>“P¾ô]Ð@’è‡ø£çÖmýÚ·Æ“î6eë·†fÆîa!!B›Ñ g?6ÎYgÁ ¬EŸ»6ø*¨ô lô—¾«ÊÆxšC{ÄÆ®Ö[[v›z.w>áæRwÚCBOóÞšv.¦˜À¼-ÿ 4«².»ÙxrŠ£is[î:/1'é€F 5Ý…ôçÐá6¸‡s®kÇy6õz‰ÝYÓés&j_˜$ÚöÝ®VÝÜú'¯žt½«æ#ÀqÒæŽPј"äå$W³]d.>-S²Õ™§¸l¼`Hi[zY{¥b‰SÉÏNÙÔ™þݹ¦/›õ¡äkÐJÕ­ßxÜ”¹ó¿ñaæºªŽšt”š€‹d¹¹;ÐÉÐóQ¶ 5‚L§a„c•гP¦ã×y]‡PTôg9ChÚ½NYíÖ†‹JÏR•½göZ­\iZ;·I)Ÿ<mYvqŒ$:a8UóÒœ`ɦº)Æàà Ü*Á¨°FèÌ8éq|™.ÍàNØYò¦„í N‘f‚g—ÆÙŘ¶ÕÆŒÅ)Œé¬8f¹`êDýJ¸$ûó.½±ìÃŒ£Tpµ.Um«v´žpU³¯§_J˜ ä)E¼1¹ñ2Ž÷pÔu³ž¯`tJ%o±=¨£Ëb˜æjŠJ1‡©ä¿Õxzv§TøÚê] ù°µµîÚÃÔSx9¹wq<²qvq]±³¦{Eäi ߪä´lrt3Õ.\ªæ© ÊñÎ$2û¿h³´!=¥ý÷ë8¢7æÁX÷R8 ùÿ¾Z-þXЀ *CAÁ$ ÿy½øü… öß#‚9öÇÁªF.W‚ºJTèvñ[xÈqx~d® ŒTbw&¥“}Sœ<€ŽO%Þ`\ÆŠö7p›h›»ûdãŸm¿Û ³ÀîïÂïÝû×ÊðÖðƒt,c˜kÜèxóˆ!º'Tßäeuš‰ýz^F$Î(èo ˜Ê±9’øœ ‰ endstream endobj 110 0 obj << /Type /Page /Contents 135 0 R /Resources 134 0 R /MediaBox [0 0 612 792] /Parent 146 0 R /Annots [ 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R 116 0 R 117 0 R 118 0 R 119 0 R 120 0 R 121 0 R 122 0 R 123 0 R 124 0 R 125 0 R 126 0 R 127 0 R 128 0 R 129 0 R 130 0 R 131 0 R 132 0 R ] >> endobj 111 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 444.879 83.692 454.576] /Subtype /Link /A << /S /GoTo /D (section.0) >> >> endobj 112 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 430.433 83.692 440.13] /Subtype /Link /A << /S /GoTo /D (section.1) >> >> endobj 113 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 415.987 83.692 425.684] /Subtype /Link /A << /S /GoTo /D (section.2) >> >> endobj 114 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 401.542 83.692 411.239] /Subtype /Link /A << /S /GoTo /D (section.3) >> >> endobj 115 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 387.096 83.692 396.793] /Subtype /Link /A << /S /GoTo /D (section.4) >> >> endobj 116 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 372.65 83.692 382.347] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 117 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 358.204 83.692 367.901] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 118 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 343.758 83.692 353.455] /Subtype /Link /A << /S /GoTo /D (section.7) >> >> endobj 119 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 329.312 83.692 339.009] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 120 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.847 314.867 83.692 324.564] /Subtype /Link /A << /S /GoTo /D (section.9) >> >> endobj 121 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 300.421 83.692 310.118] /Subtype /Link /A << /S /GoTo /D (section.10) >> >> endobj 122 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 285.975 83.692 295.672] /Subtype /Link /A << /S /GoTo /D (section.11) >> >> endobj 123 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 271.529 83.692 281.226] /Subtype /Link /A << /S /GoTo /D (section.12) >> >> endobj 124 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 257.083 83.692 266.78] /Subtype /Link /A << /S /GoTo /D (section.13) >> >> endobj 125 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 242.637 83.692 252.334] /Subtype /Link /A << /S /GoTo /D (section.14) >> >> endobj 126 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 228.192 83.692 237.889] /Subtype /Link /A << /S /GoTo /D (section.15) >> >> endobj 127 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 213.746 83.692 223.443] /Subtype /Link /A << /S /GoTo /D (section.16) >> >> endobj 128 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 199.3 83.692 208.997] /Subtype /Link /A << /S /GoTo /D (section.17) >> >> endobj 129 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 184.854 83.692 194.551] /Subtype /Link /A << /S /GoTo /D (section.18) >> >> endobj 130 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 170.408 83.692 180.105] /Subtype /Link /A << /S /GoTo /D (section.19) >> >> endobj 131 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [69.994 155.962 83.692 165.659] /Subtype /Link /A << /S /GoTo /D (section.20) >> >> endobj 132 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [75.196 141.517 83.042 148.657] /Subtype /Link /A << /S /GoTo /D (refs) >> >> endobj 136 0 obj << /D [110 0 R /XYZ 72 720 null] >> endobj 137 0 obj << /D [110 0 R /XYZ 72 720 null] >> endobj 134 0 obj << /Font << /F17 138 0 R /F16 139 0 R /F18 140 0 R /F14 141 0 R /F32 142 0 R /F33 143 0 R /F34 144 0 R /F13 145 0 R >> /ProcSet [ /PDF /Text ] >> endobj 157 0 obj << /Length 3060 /Filter /FlateDecode >> stream xÚ]sã¶ñý~…ÞBÍX0‚_¹étrIã\.—éäÜt2I`–PS¤† Ïq_ú×»‹(QÆ9×>\, ì÷2]íVéêæUêÇ7·¯®¿Í䊗Lð\®nïW¥X•iÅR™¯n›Õ¯IºÞp.òä»~ñäq½ÉÊ<{'«=`o,Ín&Óh¶þýöûëoyµâœÕy.rºÚd)“iF„o÷š°ðü–LòR3hÕtjc ÉÒŠÔãÐïu.ò?Ö¢L>/– vú-åÅÖèn-ªd$àýÔmGÓwª5#â?xÜ+pè­ŸYs8¶šæêxlÍVáN‹Œ­6UÅd]­6¸—1´U Ã£Ý­7p¤¦ƒêÔN7ôñhÆ}?á ™€S=J§i]Ð;#Þ`FM åø¢gËÖ™§Éínƒ,ˆÓ_ (gœütójõ«ÛÃs¿N*à :½ÕÖªÁšî¾ÊßÐ÷f‹Döô Zä^@«ÁÒÝZýˆì9ûA«Ìóx«X^Hâí->@ZŸqÆ"Í´"¾â†Ìka3<ÍX™ÎFóuÌ®jVÉK³²DŸ®Pº+À1[/1bžæ¬Ìg+v *ó;-˘ÌfÔ+ Ì^¯ô׫’¦ï¾éÀ½rf½öj¦SUBóÞl5}ßM~3<Ž3VQ¦LÔùRsQGP "ø2‘‘/#àýÐôJx»xÙ Ð 3‰®ø{tzKÚ;\¢ýhéF@ÎmÅXY‚íÕÐ,!a£í§®±¨½B‚éÀ±Ž£þC¡Ï²AI휓ã~ÑO¯žù  *í5Ÿ¨}Ûq@ž…У7îþ>¢ÉgþßQÚNàÉ'À¿™õ†S ÕÇ” ¨iýyJ ˆ" îà”)—‰2­ºk=CjüÄË\S)™€pæ©îÇñøåõõÖ2ÕML7SÓ51ž¥d5Úò-jÆg¶K³4f¨Ë«Ù*îšÃ5Þïi!’ËKæ9ËŠy½üF Îd%–^ä H®o£¢á/á\%~´£ŸpñÆ»üp ×ítg·ƒ¹#7F0´ G÷žÆÙ’ñÃÙ„ ²>GoŒÝNÖÆä zoW|žœ ›=¦‚ 戃׆´ŠÓqC¯A€Uå…+çÌ>M“ eWb¿ü\ÈY*ä…N4[‹{®ÛáæÎt׸iÁ5>7 õƽþKò†t‹‰¢Zü2üœÈ_f, ¹÷IÝÛ_Ò…b}(f1!„äM|Ž*–ÕÕIÁó4FQ2œ¡Æè”L–3F3¬³Æ"Mä5§xÖúáþ`¯b‹šåiŸâl¥§ÛiûW¸ ¼g^Äù•ºF[’)&@#}»¬Æà· úeÄ" «õp0e*uíB¤7ȶ×Yž¬ª³¥Îº+AžƒúöÓ‘¦x0ŽŠïXGýäem<4a‹:bô•¼)4¨ç"‹FDŠ8[d7(šàú%‘(å^I¦+-’îô Æ~ û ÚkÂ!Üy© K{|g÷‹Õ~¸3£]3Su[áòE)èò°h<²jmO Žj»Æñ”Ï:©e.BÖ½eßÌ”À¤•÷•më²áSÒHB&MÉ‚èIïÅ!+Fgäi[ë|³£Ðj äÁÑèOv,Æ®‹¾¢B‡g¡C‚Ü)ë‚Lnâd èªÝõ[îôAAN ñk¿~2ÏHê‹#ùý5ùݾÜÈè™zåéBÁ!J/ØyÿÞÅzJ©7%(åý¨ñ9¥„qM!©:OÓp…Ê)Rg80ì KóWÎL.ëô×hÁé•€Jêpf9ŽìÁg7–—9,B|]¥;ú<¸ðƒ3kº­Ÿ~"ÇsUi8`®5Šg9Ïÿ'|ºù‡Õ÷êL —n4¦ª8= ¶ A(wÆÙÍ 1µC{B„—ã˜ð‹*K¾R²NH½}xZW‚ÖDòD+‰›A?Òöwfxð«o\µ†ßy直& ²ä§©1Þw†{œ=á{°€¾Ã =¯’wú£{¦\¼}²F=ø•÷jx …ï :†ôtÞsÓMï7ýärÿ§V_Qµù5w£v‹<ù  ôüÊÚ´ÜöªÓW1ñ~ã¼+Ú[¼]¬ížæ%Ô']§PÙçÍ`ºH$:¿ü‹ÛÓy :%Óaó?qnòDËïŸ'´¾mB‘Ü8­üÏ:ç0Q¯ýIFŒ"NéîðЫ˜ÕýÝ%{S«Gì]à¶Œ¾óõ²t­Œ†&V“5 è‚Ðc‘îÜ?<¯4AÁލrmØïªé‡Žì<êN7hæð¤o¿ð¤½‡Yk|ˆ¬Œ ¦Þ=Ä^>pÍŽ2ùF ;…‚“iP€þ`°§4’"ÀÊ;`õ@KÔÃ:ÇøÑª=AÜm³¬JÞî\Ä£„oŽ÷øH«÷= çSÇ‘ò@?h©ƒõ.¦²ÃðãS€ ü¶˜hF1½Ê”ÒÏŸûWªrÏ.`ø&ŰWGK_¡þÈýãô-í¿ÇJÕ/v3Æï ͺHás™¨iÏ2%+Š9=|Á§‰Oø4t<ÍžUF˜ £èÁ+ ·Ü—òPÃðÄ5—¢ŽGðsF›œI —ç&|lûÃÁw­_&¿L?^¹ÀNçVgmLîtæ:0áR¯çNÌ›kU\ù6’õ2}o¡\ž)\S-Ëî»ig£¹ÌùÿYfbQmÔ“"WXT¤…K•qØc1´ÛSë°ö:×£/Ê„µ¦Ë§a3uC‚ “Vu» |kLŸDżߋ¯‚ñS-ˆæ{ŸÏé¡‹‘Í9+O¥f”*T'ønÔàh æy!B&É2¨Ñ–íÓÐ]ñ}g'Ô¤#evî‡PçHNÎ)#¦Ý£ë þç);ñÒöÍSçü^ÓÆ;ð¥`E%ÿ¾Ê©íz§®á>µãŽãjï$ø²@¾@%s,óä«w¾økA#†”~G¬2xKϦàõ0I)'@¸\ˆPÖ¬æsñ¸Ö9`B¶{ θ”çZÇ)¬9 î~º´ž¦ÎAS—ˆ/Û[ ·²z±B†bµžõ6TwØ­@ÒeBåFÊ ¥±£ªŠäý:vP%ôŒÁc4rVåىƆeò% e^0ÜG^ô‚EzÖ9HÓø­E=›}. v”]¤vß÷ИI`…„¹’ JeM°48…Iøh}ëòvÑœ²ò¹âœl«¬ƒ%AzJßÛ~À¿ΗÁ.ìP§Öþü ì¸üAƒ$¸g†šÙŽgW?D"ÿé÷E×{'âÏü+k>ïiBÿ¼J¨]œ:³§~}“žPIMàÂksD) 2cÕ©¹õ’ãÙ³Öl£y=»2M#€«'Ïýs”¾`¥œéÿ%jj‚É“û9®sRäÏ[ZK:ØÒÊ^¼,¨n–‘™µ7•,•u,ɰ6æžò‚•§^Ô“ëë`"³bÎòtÑÐD6›×Ñ9™|L6üJ ÿúKq[Clzò÷ì ‰„O0EÃñœx¦º„èy‘…ßÂÍX!_ÖÀ8Ó@â°§z®1ö_½™Ó$€t}·Ñ–ŸéäEÌ’Ueý\*h¸2Ù¶ÊZm£E`¤šµ rhDb/Äñç( m”¦™Ÿ§69Ï@±ðç.^'ƒS—@ä¾ù”‡Ñ0ÙBà°45~´f×a`—[¢çÂYm ÷ãDsQ³ªªB4?ÇùÛí«ÿ…rP+ endstream endobj 156 0 obj << /Type /Page /Contents 157 0 R /Resources 155 0 R /MediaBox [0 0 612 792] /Parent 146 0 R /Annots [ 133 0 R 148 0 R 149 0 R 150 0 R 151 0 R 152 0 R 153 0 R 154 0 R ] >> endobj 133 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [412.968 659.875 426.666 672.495] /Subtype /Link /A << /S /GoTo /D (section.15) >> >> endobj 148 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [176.097 583.528 189.796 596.148] /Subtype /Link /A << /S /GoTo /D (section.18) >> >> endobj 149 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [318.9 564.633 512.037 577.584] /Subtype/Link/A<> >> endobj 150 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [146.027 531.623 523.288 544.574] /Subtype/Link/A<> >> endobj 151 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [364.887 402.791 372.732 412.488] /Subtype /Link /A << /S /GoTo /D (cite.pgi) >> >> endobj 152 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [223.247 373.9 231.092 383.596] /Subtype /Link /A << /S /GoTo /D (cite.pgi) >> >> endobj 153 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [108.917 268.661 116.763 278.358] /Subtype /Link /A << /S /GoTo /D (cite.saucy) >> >> endobj 154 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [470.791 111.502 478.637 125.45] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 158 0 obj << /D [156 0 R /XYZ 72 720 null] >> endobj 6 0 obj << /D [156 0 R /XYZ 72 720 null] >> endobj 10 0 obj << /D [156 0 R /XYZ 72 515.352 null] >> endobj 14 0 obj << /D [156 0 R /XYZ 72 184.047 null] >> endobj 155 0 obj << /Font << /F34 144 0 R /F18 140 0 R /F38 159 0 R /F45 160 0 R /F17 138 0 R /F41 161 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 166 0 obj << /Length 4612 /Filter /FlateDecode >> stream xÚíïáȺ)oR¹Hl4xxß_ »y¸a7ßÅÂÿx÷ÕþÄÝ çU­µ¸y÷áÆŠË\Å”¾ywóï›÷§ãíÔls|láAÕ›ýá¾=ÐØþ Ñw0ðéVØM{Ë7‡c·mü¥;>v==ãwÍg=ÒÀ¶Ýíh‘.Lï÷ÇêöN3½ùáÃí¾ûç?üIñBáT%™…xÿƒINÓd}c«Ú2޳LeÔͯl-i^˜4?­«j.n’YMŸÝSV –¿¾%Ÿí)ÖíyØ{FäæŽÝ¾¾Æ1ƒ¨ísq&+ Õ[ áN)W9Ž ‹Êè0ÈAsíl[Qqgâ¶\õÀ ™EE]1£Ç‰ÇÇ&{ aáõKO‘E«ª¬”)Z–•(*Yå”{“ᤪNw^ƒºí-ÊþiC… –4î·A!/¡PdPØ¡˜¾iI¼Ÿéc]xÚgÕéŠÕúM Ë¡ØïÜпáô~h04¶j×z'óH¼ãªRÊüÜ*MI ‹jö¯û#&P§6 òGúð<‰>}&µÀëÍûÛ;á6û#L}¤¯F¹£yÀà~ÞvO¬4.ÝOíÓÐîà×D¾¡ 8óÇ£J#+11êÐõ»ö¸ÇÕ”"¾…Õ@Aov¹“[´âã¯IPÅèÊX5Ç0O˜‘<ZŠ0ÖÙuG„ù3 îûökzúå±Ûµô›&+kZOêñ¾¶8`>G-Yi6Á<‚öò¬Áîaó Ê}¿ûL_–˜ô3ëO5TtzÁ ðžÞUÚŽø`Øœ<óJÊ –ïsàrY©(XÈhtÁ\XR°‡æùñëÜòH[ CTà:»«j7Í ‹>{>lO·ðïtlŠ`×¼XÕ¼âjÒL?æåZENËÂk+Ãä8ãSXC-`e¥EÖVÂc\ä-ù) ¨–hb‘é»Ð\ꂳBëØ9A&#޾E­½*Êh+í–d[¨@'4é@E³² Esf}s{ÇÍ. Æ‘­K×ä¥5efͿdžþÙñß74öS"ÙOJïâ¦ûýœÃœ®øì¤:Qš Ø$øNÖÎ[ªA¤(ˆ‡•P/àJ´ ZlÞBYW¢^JÊì̦bÎ¥t—¥¿ÿ¼Ád¦×prôá¡{jÚK§³°ˆ>Ü¥’azb´S?ºA‹ƒ¡Àèk ¬WXDþ§ ~ÐûJ®@óŽYŠ o³ AT:šÂ,š4ì>¹x¿d€r•© ©ùé$œ?éc~?ÉÕb¿3 ydº’>U1û©°Š‰{È‹VmízŠ}ŸA°˜bÝœ ûNLùkV$ Ì\uŽJ&™YŠTEeÙD¾ÏÙ=¹´¯ÜÓ»¤pðæþc³=¨8Òˆðï >ùFþ«¬Ô>žcçLC¨z‗œxy’Ô›¹pˆ¾ Ê\´±ßç7@FL,¶Epa5nÎ-öŒF¬a½†F>v\z×Ò:•°·0½G.mÉôCÄ&ôÒô/$Né_Þœ6³çw ÿhCÀß–}ø8CÂÿÍøsý¬@§¼no^Ú[dö~±/ ¢È–€R×î‚›Ah@ïèf„ØCp¢NŠÁ È…=BÁ”‰ÏOÇýÓþðüØ O@vç@Éù¤Ãé9ï#²Š×“ʦ(ÚQ€í ¶ÜíO‡öž>‘¶ôE/’Õ•1Ž ¸-y¨õh•äô¼—ËSœï'ÃCó]b{çÃKá‰Ó¬Væm®y Zè莖 äC‡Ó”½dí=bÊ.ǹVob½ÀÐ<çn,Î%¼p^ŒEåäu}ª´¾® ìoz‰Iü¦‰7 tøK×o‘3ؘ ¢Œ jrAŒ²Ì ySÿgéJ†Ç¡{è;̱l›‰}DÎLÜa× Ç @æÚè¹·°Ý÷÷£¶uvóÔ6~x<>æ™…ÃÏ­vWÃrž:Õá¯mX¹YugÇ”Šs¥Ô\ !M½"lœðrç34CK[ àwU[å³ ¶²ö…Ç)fMõu}ÖÇt6Í”V½3Üm~èG‚´!Žó)3'äh?­6÷‡˜‡b"pXøççøƒ¨(cŸål{•µAùšè¢<6C؉œ(ÿÔÒ¦ž´9’Út…uyf7ÞÖÿå6$‘àùÁëXØ+0¼Øœ†S³£Ç…YÁé0)c¦‹cycn¬~(øÍuUg} äªlsÀÏãöZæbž½½’¹ë2u.…½nÍ/É\È5™ ™ÚTe¹·©ø¿Á,õ qtTË$&š–±ìy@7É<ËGŸ.Êû7ù5„š˜˜¯Xã*ûÜq0§ÀýÄXÁ«J’çÖ™³&ʽÓÌkz´fÌ1nóË1™À­ ì‹ש©çWÊ^ôçìAÑ18Oœ©e©ddŽž ÿ;x&s a*Y?›VA-Å_¥x–[(‰%ÞÄ‹x1ož'Ÿìµj‰ÚÉv}È…ĽÑÑg³ëˆ~%¿œú5„,H3ŸHôw…↭í[ó_Ir^ÔŽÜT,j«/`A÷F’ùá*gmøgsK§yTƒÎ“1eõc6¹¶ÄõÏyÄpñ–¼þ7gé‚«­,|@žw•®¤­?“' ðÞ¶˜®rõ¢`hžÚeÁzèþ« ¹¶f(Ô@³½J %î.Ô‘CÏ$ûû÷kúšú³¦25| ?8„0 ¾ïú{,K‡Ú-|ˆùÎRÝV˜L¼}Y4NÎ6U]/êÜ,5ÃX9 ìš~ßwô„Øåf¿O» 0ƃqaY>ƒ…I$“Æ“pf…n®p´ßœúíèÉ,ùÛƒ›É‹ø®£ÉzȘÂM0°ŠˆZn>ìaã>ÄŒøa*0œˆº²æzzY&üÛÌü²3­B#䊠S™4ã—ÏÌ8á^X; Ò TŠXô{PmÀdSu¥4…2+šLÌÏïKѦ”âeÑ1¶zŒQ1¯•û‘’Á‘°¤¸\ÆP•ˆìŒž’_òþaiÿŸÊVÀëJéM÷ÐïÞ‰˜cØj8³ýulÝ«)¡™Ô€’Cú¶Níëq^†öÃi׃k‡ar²HÔB_ ú9¨ä¶Mp"ãrÁÅÉèâÿÝKÿÿÃ~·ÛûL<5N½üô͈ÇvYÕŒOÃý¡ÅŒ-D |ùÓ¹sfE%ìäèüåôüìïÞ¥TcV¨ž~M¾ÌÆÐ÷]Jö,2%S’‹LíÜ8ëU]úθ—m(JÎ;ô½J§Nª~þÜÓ7§è§DÄQðÚá©?=‘;{ ÏtyBn>µ‡»Àk¬i»h=9’OL—)ýJkÚ·Ù>Òh„ ÒȤKl‘OÎûeo¬™^BÛuiñB÷5üÒ9ýŠVö1Ü3E…­êß+â·ÁŠX•¬X7 –Be©ST\·Ü×;6X®Yã¬å|ؤY£äSiÁ¯@®Ñµ™]8 ×D-¸® ‚QèîÎ+‘èQá5ªeg(i€§ A1¾¡ô<è±Å~G¼/¹òŸZ%Ÿm1iËÕKodØeÆH¯ÑÉè4ÉWßœº²ç¤—ݨrOè´ð÷¨j66íçç ôO¹¤3‚ò†¡½ß)t¨¤ðÏõÜ-ˆwÜH5W‰t¹¥Üèô=0¯/߀€Ñšk·bKg¼ ìèqŒÝ:ÑÝ?‹³yeäšuK“í,+4ƒ~Š5ðK…ÞÈ'ã‹p"ëìC¼òªDýÿýR¯wJÍ¥NñYX¹†Ú…æ Ø4Îñ|ÿ×SwlÞïÚ|G:ÓÌž™DoÅ„CH l4rÜgYý¾>k*œŒ:Uýº-v‚*Æ©%Ç|ÆîäsA’yßä2i!»/tÛÏ M÷±AÍMMÌY˜Í‘ Œ->8ž*þÛ|ï*—°ðYOÄ•’E—7Àx{qq™·ÑFŠÝ âI¨çZòùÐn»¡Ý}ÎJŽ_A®D«ºˆV`_cÒ«óT²º€2­Áá+1¦.T÷Àò¹Ùå4E<$ˆqV(Ø8•Þ"RG'–» _>f=~02V¾h½Ÿóþ¯Š·‚¼†a›{¦ƒ±‰ˆO-xñŽ8wÄÙxG°a •zÀFCü¦ tièã©ïþzjǾ"PrfÙf‡÷‡Pÿh'ÍòŠñ.u¸\˜öîÇÀ:¹Ki¦[“6&ïqø¡#æ Fn²y”_ÍyÚó”/z€¥ž‹\Úý©íñxc^¢X°´Njj•Ô¡+–¿œ'r°m"ïŸ )S IÚÔˆ±¸!­¼kD‚#/7$ÄUš¿¬w¶ñÆÛ”¥ú8²L¬è_Tìza ©¾ü}ã-ë.œ†ËÿGhÆûÁø1qUq´Ð Bl/#ÒëÊé¤V@V°.gëÍé™vCˆÛx½‡A'†­i}¼Ü°Aí⣞émêaa²­ ,]ØØåuIÅÑÇÓ€—Oðé= Ïæ®ŽÏ¸LÍ>Íéx+yþF˜4>5ž¶ XjÀÈÑþùx4ü|؃¡ ð$Þ„°z³Å9ôô<Åà8ï¾¶‡. …t=ý?‚…Æ„ö¹Ï„Æ+‰1•Œ¡ ›û¶1<_‡¶9L= øÃCÛ¢£Æìæ'¬ñøe$è|v;úph±/Âë%Ììïã–¹ëEÖT&ÞÈì÷”²æi;ÐÙY¶ðöŒÖgß…m÷ý‡Ó[O¸1K'"G‘ÐÊ€ã8©—O> õœÏ.|²òš­egu ¡§ïƒ2³Ð‘n¤7õ¨ïñ „›:˜øNnOžü²ëAë{©ëPûš.F,ßPC”c×\Kˆ7˜_Ž;¥°snn¤È[ªuˆ à!uáku¹Ã…ûαÜ=J}é%Ë4ÍùŠëÜ™‰ßß·Á,Š—^Žgw+°bW!Åœ_š2ù·©´G|‹â"’oq3¤Vt3„¾_#4(º…KyÃv5£½öôÕh8.<=´àäú†øîÚù/ˆCá!U0Ö^V0øš9‘{µÊkDIòÌû4 3ÅŽƒ^±‡Ë¿øjÞ‡J(gÑãoïÛ,1ðl [ [‘yL¸ù\{Nñ\°º}cmú椫4¯/bI‰y÷Nî6¦ ‡·}áK/‘^8ñâ¦]À¥¿9IºH÷‡¶÷‡·¥+l %Üo|ú~\¢˜pÏíB•îòe$nS2W*ÀÄ_¬#)º®þnö607½½1t¹ÀH‡/oTà~¼{ôP!Ó†“A6=+[ô0è7_H>ºhÙõ—ip âKp(Y¥]ÓÁˆRã?¢ ¢ƒJé ºbL=2€fL¿aÍßàà‚ ËÙ¤|÷Õ%“ޤ endstream endobj 165 0 obj << /Type /Page /Contents 166 0 R /Resources 164 0 R /MediaBox [0 0 612 792] /Parent 146 0 R >> endobj 167 0 obj << /D [165 0 R /XYZ 72 720 null] >> endobj 170 0 obj << /D [165 0 R /XYZ 72 400.332 null] >> endobj 164 0 obj << /Font << /F18 140 0 R /F41 161 0 R /F39 168 0 R /F17 138 0 R /F14 141 0 R /F42 169 0 R /F34 144 0 R /F45 160 0 R >> /ProcSet [ /PDF /Text ] >> endobj 176 0 obj << /Length 2036 /Filter /FlateDecode >> stream xÚ¥XKÛ8¾÷¯ÐQÚŒøDí-³y {l¦&™[¢m²äÑ#Iï¯ß*VI–e‚Å‘Åb±_‹N¢c”Dïþþòôðê6‘”¢HS=¢\EybEbÒ詊>Å­›Æ–ñËîϧ½z'íšY[!S8]Yv}U·ÇÝ^ç6;üñÐ=Qú©ñŸ“TŠÝ>-TüngUÜõÄå]¹Sy|"Î/8öýè¿Ñ©F®OU2²Èçs¿°f7fÈD˜\Î,jKŒTB§zfùç–}R‹<-f–¯A+ÒðäpòeEqd™Q7Q»ÃÖÑ…9œÄr?'*ß<]Š$3‹{‡< ÂËھ ÑÞ$$©h/0&c=ëñ„œY<ž<òøâú±ë®%ú±‰~è»ó¦o øOÉ«†Z2[å¢È°ú‘Z[âK¶ÌÈ„L@ÃÛ3úè…Téý¥qe@ *Ägqé›fS³ÄˆBý$lJ¤‹ßÖ‡­üQ÷D‚ ž7l!©È„ºFa3œ)xÄþ-3‘؅㸥s!”½Æº­6¯„̲{ÓïqŸåæ·$Ùí¥J¶õ–€'ÿ?¿1þ‘a™&Bw°¬|EApˆ>[@òW¾DjLDŠðù¿¦ztÏ'ú°Ú=®n=oZ‚ +îri^Pæhp¡M–Œþøƒ¤O‹Å…XÆPj=BÙ2JÅO³~K¦÷¾e{¶½Œ1 øI¶ï|JÒ[§¹Ë‹‚”õ­ïCâÃ4ÎD²JßrÑ…ið(Äü‰„Æ=‡úáça¥c Ç\vëÒ‹ ‹´²¢Ðöosð¬' ‚…Và ©ÁB+ÒLÓÚë–cõ&nÑÛ6® ñ¯áòy~ëvj¾<­I¿žÆîÜõ—S=œâ Oωƒcï.'–Ó3íÐM-Ë^r Èm\X.†d>Érˆmvë“·†kãšÊx˜æXáìÖe¨^ªâc=ߪÈBJypgÿÝ®`>îA Ðb™p~_éÚ®­K׬·Ùk|€vvæ]¢n1ê`c¸ ·ö„žÒ¢õ<8ÐÔ˜tgO[ËÅ¢°T ×M³”-‚}Êî|i@uJw %FöäÏ|Èú¦l~œ¾_O¼VÓzoÅ]ï¢øx…ç¶ÃÔŒT>á^h“HF=ö‹8øøþ$¼D]dôIÆrIéoJJÝßÎìKž–ÔÂTž*Â’G«zðö[é/¨‚±Tå Ö~uij\ß¼q¨ÁIžK7øàêÔ@pˆÃέ§!ÌãhŒd0Ç¡–„cúºrœ\3Ë§Š ülY°õÃÐÑ=u}Xlê !–=’/Çæœl8ðõ¼¬:u!iÚuI°ËüPÚ¾ìÀTÀ6˜ èÈÒ»ï4pM\®z¡ùr“ ¿ ‰1ÛÉZB®zÀdjk:ÛCòŒfLAƯp5?Ïà™ù€ÓŒ¦Ã §ÊÃeß  1¤íTÓ¦ñ»ú8¯Âø×Ö ‹kãÔ`—R˜9Þç¿9LBȬá¹^Jç%3GHëL„iÀž@˜Úá *‚û÷?†‘#¸MpÛk©¯×â@sBŽ4Ø=ƒë¡XÀê\°‘ÅNÉ« W–~*äÄûe˜ÎT‘€›º4Aƒ®¯uënk ?ˮ馞v_sFÓÔJ5M /¦”´l#PG×ýÈ¡C2¶Ã}äû†Z¾°Ðò`œ%/Lg /ô棯¬[e‚oR_ƒ‹õ=„3:9¾&óX¬¹c`<Ã5F`J¶Á€o rÌ?'Ò| 0È´"pé5Ëa¸>nƒ`¦¹iÜøUÁh‘Î`ÍRN®µyZXªh|×ñ ÝÍI°º سj8 oþDâÃÿohMsZRHƹ¡yºbãGн}ÈPYónMõÂðn\[´õåÈ‘HZE½èRlÞ>=H®E2ƒ—e®"•h‘YTžþzBÑ2‰È;˜ðêÃYFoº‡Ão–;³ìg©û•Øð·ËÝ£#ƒÇ¾) ¸Y‘Y~'/Õ mýÕÖ·K¥ÂHæ"ëúXX­{¿ýlxÆäà¿rnÿ÷QF «–®ôæoŸÅªùK›s¡$¼³ñí¢u"læ¦RèL‘ ˆŠ”*߸1ô5iüÛØOP!6b«ë…Hƒ“Ì/ÖóÖQžãËÓcðãW裶„¸Òåqšý, ߤT“¡>†Z‚T¼Æà®õG¼…‘×íoXš/k¤É ±ZèX+fâý™¡ùs=ÌRyÇÏ5dëX›¹.í3xžª»' 6ƒuã÷c}æ„†Ò ÝðZHšßQù_?¾ùíÃoÅ5å~y!îÊ4uœU¿£eÌLë5§)Ú€ó©mü0ÜÕ¡þç8½i¾+¡7Ûˆ›ÊÂÿ?ަC¤NoÇÍ´×Èj~Ž{ïÈìð°uÜœhÅIO¯âœë¬¥tÈCwH wÖã~ CÄd,°€Ü6#Òx­Á­ amNú˜ûò_ºµeT endstream endobj 175 0 obj << /Type /Page /Contents 176 0 R /Resources 174 0 R /MediaBox [0 0 612 792] /Parent 146 0 R /Annots [ 171 0 R 172 0 R ] >> endobj 173 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./fig1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 179 0 R /BBox [0 0 223 183] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 180 0 R >>/Font << /R8 181 0 R/R9 182 0 R>> >> /Length 183 0 R /Filter /FlateDecode >> stream xœÝW»ŽS1íý.é^ìñ»EBÔlÒ!ª Ý%ÅBA³Ï<üDd©7isÏœyØsmçI›ÝjCŸú}º¨÷wI?üR~ú·²ú»b^ß}RÑm ú¢|ä­MFŸÕA“r"&¤€LWœÕ#šYý0óÝ8rsÿîr‰a­‘ð…¾Xù{P¾ø½”(ù^&0BÒ>#@ì)"Õæ™fxR>šÝ¤Nû²ª;FçhÜaF7Nw1g3|3Dó[øžZUÏ™Ÿ¨Ð›©…"›@V|À”N*E†@©!8 À“J)p>•Ž~UwœØ¸Crãt—´ø.2Q#6ŒÔD½dÎ s3µ, CoßT ¿“S1)-Žb*ݲmê†ÉùTL¶0“a™(S1202õ’ùº0¯½Z˜« Ùë:„Â}Rð=öä29,¾¦#ð¤Šc³F¬ê†É9wh¹OšØAš} Dó»ò=Óªž3ç…¹™Zøl³ÐÏœKC¹î—–6FÙøúéÄ› 5¥še²"uký8ÝE`C÷GÏh×B EI4Ñ”ÏþëJ˜¦8˜û¥ÃºâÑÃÜ/ÊÚ/Ѧ©_¢Y»­cYÒeÅ›Xú¡ûnýÒcW>¬Ý¶dγ3µð˜¶sòÝÇùØ’›Ùu…i0ÜQ³îwè¡r/™¥^ ¯0åâ¾û4Éo<بœfÑU®MF¶tÖ$õù¬˜ú„zØ®×ÿ·¥båªÈÈ‚k Ö{Ä’Ý hÚ»èßÄ¡^ô>¨'|}ù¹~.úÃdvÐÇ{%?¬™RvTÌñ¢Þ|ÁKžú™9øúöøCáµ|sQ¿!ë‘q•üoÙbËä ŠËF ølܰP 3ìžÙ’±­–?fCµ°Õ¢³ÈKCmz*TaÜU˜òž¨÷[LÏÅp ›7» :•&¢JK$!± ɧZ!X´s·Ì;»ñY&§8ŠÑÝîçè8ÏzÃ+¸ã±ðWÆnYoÅï“> endobj 180 0 obj << /Type /ExtGState /OPM 1 >> endobj 181 0 obj << /BaseFont /Helvetica /Type /Font /Subtype /Type1 >> endobj 182 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 183 0 obj 794 endobj 171 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [155.937 587.364 163.783 597.061] /Subtype /Link /A << /S /GoTo /D (cite.pgi) >> >> endobj 172 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [271.497 539.909 279.343 549.606] /Subtype /Link /A << /S /GoTo /D (cite.pgi) >> >> endobj 177 0 obj << /D [175 0 R /XYZ 72 720 null] >> endobj 178 0 obj << /D [175 0 R /XYZ 212.26 193.133 null] >> endobj 18 0 obj << /D [175 0 R /XYZ 72 150.373 null] >> endobj 174 0 obj << /Font << /F34 144 0 R /F18 140 0 R /F41 161 0 R /F14 141 0 R /F45 160 0 R /F38 159 0 R >> /XObject << /Im1 173 0 R >> /ProcSet [ /PDF /Text ] >> endobj 188 0 obj << /Length 3611 /Filter /FlateDecode >> stream xÚÍ[Ys#·~ׯ`R•„ª¬`ÜÀØñC\Þu6åŠc[‰«²Þ‡‘8+Òæ!sÈ•í_Ÿn4æ$f(ŠòñÂÁ`ÀnàCw£»ðÉÝ„O>»àñùÉõů„ŸÁ2cääúÝÄg̘lâ¸g\›Éõlòfú÷Ë·×ÿüà•ê4‹@&4)‹5êR“’Ye«FßrÃo.¥›þty¥t6}˜/nñu¯†O.¥ŸTΗø%­Kj¾*òuüJåþù†ªÍ;â¯E‡?LKYuà¿©> ŚǺ7TŸùªÉ»Ã2W·à©®æªZ|”¦!µ®ZˆGиÖM?㥇«Qå:5ãå¾™ÎSɘ̲^gºt:¹; L¾ ©ZÄùÜ÷Û¢,Ö8Ç»bFoP~Bjxw@ËN®„fZ[¢dÚäÛm^ɼ¦çßr&Eé*)Çš +Zrü°ÙÎR£ÑŠq[¸|A|æÅ¶H±ÖD_õX‹CÖU‹€ ,7«‚J˜ý o.¯à·ØÆ&û[DiNo»y¾£Ò7Øô‹¯>ýúõÿ^¦fLrÉ´jO½Lõ‹Ö÷{®{:c2Õ’&I´¿‘u Ë2ïªìòJk>½ž4ÿZj_;Ó³Ø!P6ÃÏ<5«Ú…¿µN¾h¾-ˆ`÷ ð)©Ùž3Û â7Wíì1ªí›Î„-‹w;*í6ôÜ.îæA3ém÷Ãb7_¬é½È£éNªôCˆÌÑ¢|®g½ÿçe¹_: ).µ÷‘å*_Gø ÎN.¶TeÖcž±ŒËã"¯L=ù \ŸÝ¼ B\]SÚe¡eoAìÊ3XîZ%)"S¼VÐïR}õ`@kô>ib|[â)2oÓµ²6½¢‰ŒYῤ±(š\1 Ê{æÊ,áÛuX`º}5ï`©ILágC=ÇúhÔ|wfë»H‰wÛü~ŽëëúPÅÈîa±\R 6va+gÛpδ­Qº¿D'ëöûŸIÅUž™F6ÛUìàzM7·€…îékš¹ä­e°$ÞÛ²H²µŒË¬Í·šàÝ‚gôZafEÅC‡*ƒAã~zŸ‡Eõû`ü_÷eQRé¼E…Mi¤÷EfõȨ#©AqæLÖ^e6}½‹Ý‹lá!€¥ûF½°ã§àá³åÁkÚ#š³¬ÑÝuªã° Ãìõ¯‹kÓLð6¬% ¹0ÓÅŽêæÐßÔÂG£t«d‡¤`œŸ¾žÄÎäËÝÌ;(d\´•“ÑïMf™m\‚¤=Q,k\Ÿ«]zôÌ5Îß°-–½x$/ög:”éÃv·¸­¿FhÛÊß4„¿îŠS£ƒ•IÁødwbo5óÙwùmÔŸT*‚W¹F]‹ê=¬I¦å'ê!?Q´Œ8h”ŸþI¯QZædß Tþà" еÐFVF¬4¨k°í6-ïƒñ eÒüJúuAÿCá¨þÛ TÃ5– Zë˜u²e¼PÁ „ÎEæåŽÔËyIßò*XÒà†ö<¤r·ÝßîöÛ¸¤£G³OÖ ‰Vn=(Zh$ê¯ÐÅrV~˜ïÚÙÅz—´êOcý~(ônl¸¬hµ2ÿXZ$á½£);¦ ëÊÃã:;+,—îɽ-¶Å--;P[ÌÛp˜üÏæ¾¤Æ·›ýºò¾Qñ*·%DÑI“ .™7CƒÕÃ…(A¥ AO§ìûtìfmR‡Í"êV„ Ø+W*N;voZ¢L®ï*Íãà—E^¦g;&š¶’±2 aÐÊÿRÐÌÒÖS ÿ|Ð ¿.NgCÊ|..EZd¤Ó¿'‘™ØæyO¾þ Û^¼¼¾øá>o ¦1tvr»ºxó–Ofð B;¦@ìB˸ 6Ã-'__|I™×.SO>’Ò`fËo^¾þìש7Î7™­GÍÈC:ÀM_R×›ãbu¿,Vm‡+×ÕR¹Ñ—‹Í:zå|³_Æö1 ¦—ýçóÏ“ˆ; ‹·ì^.~.!ÏS°¾i.B>îÈÒPhš• $åFpÀ©†û=¨cÒ/þ²nõ"Eį¡A°3DL€cœ=žXq^§T#&cÒo§×@k dÜíó%•Éb…°6ª+T6-+u.ÓQ½dÜë#«÷¾7ª~ Â5ùƒÙ u”†5isYíÂÄø÷`·ì¨BüÚ¡6„(¬ýš’Œ±™îeD)®"¶Z£ T:¿t<ÕP&ÚÆ?©Ž}Õä Zy`@ím^F1ÀKYX±ŒGUÅ´¥ò` ‰„ZÝñ„ùÀ]«&áØ,bG"ÕÖ@wUÒYy –UvÓr :‰Ù…øÝX{а’¸»e•;þDJ^uíß«K/§_i ¯’þøV¹¾¸ü%C=o™j–ÚEZrU#sc0ÁÓ n\ý¥i)ýarz=à54Íã6š^¤s0»'hò›ä,1Ì£}Ø[Ä™Ò/Zúõ¡\˨›ýîª]÷®š¯<¶_„ˆv¿°5O‡å3J-2ôϺZ]Mpñ#Kî. ÖlZ¹ADäãSo1á(HU$Ç ßÁ‡ú±*£³¡¤ËP=ªЯòÛä6&3¼¿9”Q9kB²_tL§©’4júWzˆä¥ƒ!ºö¿ÒéaЊf×ïw3§ÕøÓûº™ÚAÓ&Ÿ·? [‘™9f«.5'šĨÝR=ûE›¼rù¸î§1¡&X ÞMc¶¦6aÁ­÷Ƕ|Z;G”A7Óï Ä,fŒ¬/¥×Mý‘B`¾. {e¾ý©ê}?Äpê–‹2þ;xQáOq³”2?›ý¶Œ¦Ý‰àæt·°kG H”(õÊ£ÇWÆúC’ óØ[JüëV„µÝìfåº3æ˜?ÓÙT0Éܵü­Hu]o?˜°‹]©>ͨ°Ê[mæáå=û!ïK8&}×ùºËïËn()Z[iE±®7.W/(4½ÙÇ ªƒÙÍe“2\æ÷q/õuúÜ_^êgp9N´Σ'&æÓcr6&D¹T„1¾uç2æ´É_ÏÀlBLxÖÓ´/Q0ê¯N©u¢‘Ñ5© ó`±F žEØ ¢ø?ABc\uFh@sÄõíB?¼6Ì(Ä nDè˜ÉýXæT'k#hQ«J–J)Ó NP“*ç‡i Ã5R=aP `8L·•GhI;ŒÀF]\~3`NÔ!0"C¿Û>0è÷g:‹Àðß ˜Ó•FÓTG&LÄJ+˜€±ŽÐ€8Ÿk1FCæ´=O¥•°™‰4¬á'ñS™‚þšgâ @r°ŽGxjP¦ …ù9x„±Œ‹O‘à)13-žÀ³EOèóH€)íϢѣÝy¢¦$sv”†QcŽŠ<¸;ú™„\ÌUi{-­ÏÀ²’Õ6K5"¬ç³¬EµÍÒŒÈê‰,ÓS#ãYÓËÁjÊQÜ (‰F=”åÝ ®WRòì ;øi Öû3a×0túHíšäéìOdšs.Yæâ –?à}2Ó$XbœÄ1¼Ñ?æ\CN9Iô]PíOÔ¤q*ó¤9ï01ç§3M‚&­9 w>‘<v‹‘„#µëœò@üilÓ€·ÙŽx,'óL‚u$x;Š7h§sö™·¤wÃ^€?‘oñ6_7‚øÉL“x™q=Èës˜ª!‚Ÿ^.ðZMø\Buõ—XñÁ땜|ºZ_Ö;U“«HöªE7DFàDRÊ0)£o÷jqWŸ»—ÒfÓ¿Ã}¯°×ÙÜ3ÂíëX¨.„óâù.µÕ)þ²wç"-)»»%Õsre-˜7¹’xˆ:õ:ÚpUçè8Òí]òWðÏ7ÐÆÆ@½&Gç–2^ë°õÍ* ·‰tëoñ>©‹˜\¼|u)è"Z§J]¼†σkX®¾†åp0n6¼Â½' —·>-Z݉û°!KÝÙV¬.²„Itš§¾>ïå¼¾V*<]˜§|ð.ñmg%5 ûÀ"\ðó£WB„w¬¹{ûèËæõ½%9ýb]õ'v³}OWD¸]„×x¸º,7ËØ÷ZÆD,•*©ãZÞÜ#QÌWEKöº¢Ü?ø^i¼NØ^[{yÿ&… š endstream endobj 187 0 obj << /Type /Page /Contents 188 0 R /Resources 186 0 R /MediaBox [0 0 612 792] /Parent 146 0 R /Annots [ 185 0 R ] >> endobj 184 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./data.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 191 0 R /BBox [0 0 99 102] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 192 0 R >>/Font << /R8 193 0 R>> >> /Length 194 0 R /Filter /FlateDecode >> stream xœÝT»n1 ìõ*‘õh©mßl`'†·°Sä÷CФv‘.­qÀÝ E‡é-¦ b’ýîGøòÐâóï0­ñá»ýyoô¿ýìGüzc÷¡l%Þž‚r@Ä´ÕÝ^·[¸#þ _ØûWìžÙ;aíÌ“µR.ÏE™¥ç‹%öq"å8÷ ç4¹7 f>±hÝÚ²d -0¢vKXêÑXú8;“¬÷Yg(›Onæ ƒçWœº±•fÐt³€À}«!òøj[EÝ-TTqõª„M·"O$gÅÏ2^Zþš=r5ÕõsÍv¾¸¯2 ?OCsS›ÈºI~ù!¹Z˜÷Í®z‘ØQe«dØ–Ë=Ñøaó‡L–ñgxüW,ÉÖ·ùx<^=m$¹ZÚ0Þ~„;\OZ’çLÏïÆrã-iJè±£ü{dZùð;:m4ôàX¨Í×â(ÒŠÍú8xgƨ ïüLr§z_–^eWi18~övDÒŽ=ºÛ]w~Ç{pËÃõÃUÿž>°‚dIÔ¢ó\ˆT<9ÂçW†ft¼óESMË£¨fgXxHFGòø‰F¿ŠÆïx®À-®Ð®úçˆ>VA2¢’Õ"í8QR=%)uÕ››ft¼‡\TÓò@Õì ɸPS=]‡êu~Ç{pnY ᪎èc$#ºFÒ+ endstream endobj 191 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061130220413) /ModDate (D:20061130220413) /Title (data.fig) /Creator (fig2dev Version 3.2 Patchlevel 4) /Author (bdm@pbook \(Brendan McKay\)) >> endobj 192 0 obj << /Type /ExtGState /OPM 1 >> endobj 193 0 obj << /BaseFont /Times-Bold /Type /Font /Subtype /Type1 >> endobj 194 0 obj 741 endobj 185 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [141.299 104.174 149.144 116.794] /Subtype /Link /A << /S /GoTo /D (figure.2) >> >> endobj 189 0 obj << /D [187 0 R /XYZ 72 720 null] >> endobj 190 0 obj << /D [187 0 R /XYZ 207.237 149.67 null] >> endobj 186 0 obj << /Font << /F18 140 0 R /F38 159 0 R /F41 161 0 R /F14 141 0 R /F17 138 0 R >> /XObject << /Im2 184 0 R >> /ProcSet [ /PDF /Text ] >> endobj 197 0 obj << /Length 2664 /Filter /FlateDecode >> stream xÚ•YKÛȾûWè °¸ýäHNb’]`=ÉYç@I”Ę"’²1ÉŸO½š"5œçÄVuwuu=¾ªj©Õq¥Vz£äûû‡7?|ÐÙJë8÷Þ¬«,½ÏW©Êbåüêa¿ú5z8•ë=üù‡v¶ÔØØ%0¢Eà%sny쀙¬Ö&/ë |Ê~‰£U±MLXߗ÷¶Û/ñu6V‰ ß.ñJâ$Í&¬–ا76E³_¼¦‰u’†EÇ®¸œ–xY"]‰÷L£b7\‹µŽêú‘ ÃIfúâ\¾…a–D}+‹ùÃgÀ0‰ª†I—b‡Úû²6YTî™vh»3J²Ú°–ÏòÕF»Ø¹„E¨úõÆš$êÊ‚·°¿+/]Ù— ²·øK¼GoöÕ¹lúªmŠšIE×d@þÙxC]6ÇAâôLoY+œ›%­é46&½’x7í° Yó¢L†Õ},:É|œdtº#Óï`±6‘ø ¨>ס*°PÛð$p\¸MnÀÙÇËü}ñ.6Ö~ô^R?°{ªr nà ´æ‹mz1 /‹¡][5²¬S§zôjð `:”DzëQ¿Ú‘ .ðN’ةу«E'ó܆°;I.—ëùç±úZ5GËQ«õ6ö¹»sÑsq„h°Þ=s]—Æ™¶/Š”MèÚìËŽRœáੱÛ&^o¼ÎØxñšä£\âÀÑU¸hUö‹˜c¼‰³Ti.p¨¸$y Cågþ2•ñGÅ"Xnl¦@;‰¨Ôs/#‰­m»½=§¢çð©A‹5ñMbí^-›,•!ø&U?´]µ H€Ó·MˆC§y>BR»ýÏù/Üí¯Æ²mÛº,ué Ø“|ªKä_ð§lZŠ‚Ç3Pô…Ó2Û\ßgQ“pç“ b§X¡t#¾Zí«ÏJÛ²+9üx–•‡£ aˆNðÛ½ph™AÙìÚk‡ñÁp¦Áµ²»øyÄÍíu½q©¡ø´Ý BEpðužT_!óΖ—,éxüð32üÛ{þÕ õÃZ«&•QÀ–Ô¹Ôt¨8×þ{˜$6·ºnQ¬)­âlqØì©3ˆv׳Ôc5ù_¡¾îô¬8^Ú¾ä 2:ª³µwx4€®ƒ^ÅkÞàÖˆ}ªþƒqŸú¨®ÎPÄKb+<ªD;¢/c— ¦Alö ŽÊ |[S_!ž† +„¬]‹Át©Fqså±¶v 2k«!ç-Õ¥¨vÖFxtÂb`Aµ¨7r¬†Ô|8`bÞ•"!Êu7¸‰RMžÂYQ>”蜛}:·ƒôp ¨…ô3»ÐÄl§%Õ¥C#gÈÓ—{tbëQµ}:€G@f\jÛ.Øeˆ«—P™qdtU±­ÅÆÖ…e øŽ×~„¥ ?f+ݸ\Eå¬{½fK4Øâµ* 8q#SŠÌAL1`¡&¬aÊ–jT¡œ—´’4…K÷ÒâÀ \‚iQG쥸 Ì¾Û¾­¯ƒp"Çç…Á´‰‹ tõ3Ó¹u¾JãD,^ •+ÉE€2­¬ág!dõ–ŸvXZ W†!)Y¥‚WBGRâHŠßçÔøBˆÃpæQ:&rRž‘ïëÿ½a3cw¡ÖâëXQ¯ >+è»r ]Æ` !=N /IC±–‡âb SGâܦ}ôÓ·í0¢®]OÏ iUÞ4¶µÄ²m~3ððTL$%JÙ´×ã‰Çâ¿Pû-6—7_7É‚Ãø\L2ꡨêgu8aÀã}y(®õpÅP;ºD?…âíKÞd’\¼ GTq§jêMH.zùòl¨öªÐ2ËæÛ³=2+)CpK%¸ ‡ø!Î1ÈÑpœ?¤áç þ)€VM¢{\|ª{¨{Іüò*|)ìJp‹.<†—PŽ|½?ü Ñ¢mtÄºŽ¯+{*ù.;;ñ¢"‹zÞIæÕ ºtjx²¥ÎŒß‚'°µäT\„¨¯ÒD*}ç÷X‹MÏü8Ù_Šì£‚¾\$÷†ï^¦üe‡¸-Ö¿dŽï/@  ‹«¤rB¦ÜHÃ|µ,ýØ÷¢s_©ø|67½ã·PA‡'Õ]Å5¾ó‚ÈØ_$°¤ÿÝŠ%¼DÕâw’Åc]øÛçòµ—v*-Øí1泂$¾Ì Š÷°êÔèO?ÿñÓǾ˩nòÎE¢Ÿ/uUöáY˜*é}©ÇÌ@{öµ&VÙ]‰¹k›¾êéMÖjÖ)|ü­‚¤9.¿ËäYœçéÿýÿ‚Ë¢O-=íNä@„Á®«Ð½ñ,&tíu¨šR¬šåNÇÆg•D:é¦@Ow¾Pô‚Ë­1¸D*±½ ýüÕ ,7óW/ôÇ3wn.ÿÀ¿Ððå©ügΊa]J~ÚÉyitøô­gy±Åm“Wö·<먹%"WOÄ@¸ËÉý¸s)uI¸U.’†Ú'Ýä¤ /õÉ̯ïò”Á—0ÐàØÂðyÉlÍû‡7ÿkm“ endstream endobj 196 0 obj << /Type /Page /Contents 197 0 R /Resources 195 0 R /MediaBox [0 0 612 792] /Parent 146 0 R >> endobj 198 0 obj << /D [196 0 R /XYZ 72 720 null] >> endobj 22 0 obj << /D [196 0 R /XYZ 72 483.437 null] >> endobj 195 0 obj << /Font << /F18 140 0 R /F38 159 0 R /F41 161 0 R /F34 144 0 R /F39 168 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 203 0 obj << /Length 3352 /Filter /FlateDecode >> stream xÚÍZÝã¶Ï_±2pfH‰©)pmsEŠ»4¸lpEsyÐÚZ¯p¶äJòímþúÎp(êc©µÝ&@_l‘¢†äp>~3C~³»á7ûŠ»ÿ?ß~õõ›DÞÍb¡äÍíýŽo47ŒKus»½ù9R«µ±Š~X%"Ê›üPtEÓ²Õ/·ÿú07B°L©?å7ë„3ÉúòõjÄi´É÷{|ÒQWÓW8áð•4LÊ>¶Uù©Ã™žB$š©Ø}È[š¡{(h‚ûº9„¦XÅ2ØØZH;×µ3}䊻Qz²t†nÐ.DG±Äô^…Hh†|w#öù]ˆ¬:8tžÌ±«‚dR&¯YM¾éÊÏEˆRœ1e²Ë)ÕÍ]ÙµAJ†)™\A騕u$•¤L§ñå¤Ú._XSÂq~M~ÄcÝ|j+Åcød™â,¹fu–hùk–Œ™º‚û‡ 8ÁT^N#(P)SZ]NÃ2'¯êj·p| |>M1Óý#Ú¦•ˆ¬y¢®‡|¿ŸW±‰Ü C‘Weµsv£·Ûâ#²*¶4ènµ†ßb_ã‡ÎÒ%sK'@rSgévM~|nJ²t8õº ÑBíæ~ã-ì£-Æ'–L ày2p‰'!¶£µ3/Ú%0±¡?¬Ö™Î¢ÛÇÓ²:‚i´¼° a«µLTô¾È·ëºÚ?­LÙ²IÌ2™9îH"_V]h+qÌe.ÙŠ¾Ä>ê¹ N&KX¬ÄUl[2¢š%I<çÜ# Z lÒ UMcåî©¥v}Ot¤˜èŸb˜ÕKÄ,5~ª¢B¢]Sà|ׯ(<¯²¡9NmAÛâHÒ[mûé+üפ(Øñy¥d”ïO(KKï`‰öU[|ÆIŠ&ß“ò À žiŸ³Á° ¤Ñw÷!V¦1ãY<³Úl[Üç§}·ÀÚ,eFùcü–k¹}+úéÛWØtêŽýNF¥Up¥ì†ZjçM?fWÕM±ý£Û$|Û<–mñÊíM'«£½Á˜'üXx£€­¸ŸWÀ¼eW{lcSïëS…š–ãÁ¤Æö!D[8j# ££G´uÈ̘/03¬žssWtÞ¤ùÉ™jà'™S E¸];Œ7br"²Þ¦ò³Ô¬ƒ«\ZLÎé¨a&ó…gjŠîÔTD½lg³opcå™ýH˜Ø¶·w+š~3Ø«$ú¡)6pÜd¯úCÑ@Í`‰‚$L´/Ûe¨'ˆ}N!ºrcÅ z¸€:~Ùè£L¼*+¢ç¦ÊÀ=l‹†úúwåðà‡>ÑØª@oeûjúGæX?‡¦qk:2‹v%m*´ `a©šiÅÏ­Xœú#ó˜…¦)Zg‹GÒŒëÎ%Ì@€èI¢¯•q#™1#X(`N‰ºDìšqnÎÉjÆøàµ«:H `‰,Ü‚I‹€¯¸VÂt¤yµ³ˆ: ç¢ªO»’V€¡€igæ1Éôˆ µI23X%8ŠTkzÞ. ³óŽFºOt/zöñ~önªØóìE Û€¤¹÷¥…Õ$µ $b_I!_Æ,Ê[j'lñµ)»" . ê0à2'Ø¢-~+l±í`LkäÌå¿ÆýÃr½·Ç¦Xpö†3Ç3<þ >Ä&EÀ6þNom[Z…×´òþ‰Œ£qnEᆎL ­13=;ß¶r¯¼Þ2gtÀ±쫌e"›¦B¸Ýí?…–ÄivUþRÂO³!ýÔÛB mל`Ð"OÀÒ’cD§A÷ǘ'õ“LõZ¥Ñ±©­ÀnŠ-P¶ÞHE?nŽiXGRª&ø N;a²ö¾lF™)˜±Úµö$¼Y‡¾—!Š0³¹t°žqší‚#XN”bæJNþðzöCÝ/=Ý¡# YMa®L.¬˜qfÑx Çƒ rk§5Q[Š~=yç]nZj»ð¨¶‰.h;tOeG'ƒ ç™™ݶÜ:E¡S‡Cœ"_ˆ˜pêssE;ãº'œ„àá´šªŸ¦W¹ïß2\”¿†s6*”}Œ!LÍ·[[l¤ª¶Ô»/ª8fÛ‰êjGVÔvè¨Ø¡ß±/@ip=$8ØÅZùƒ ,¢ºHþ@ß'…ôZÇû‘ÅÑൺºÉwh0”FøJékM¾¿¨jjƒPNêhŠŸÊ¦°×X€ ~"+©·vA@“£CÇedtwêBÁ˜O:`–+Ý”Eµq™…CÏ6l´'xPV"³¨Õ&j›yã­tÈPdpÀ­p^Qg´hpe Ѱ ^/ä½R6à“™DÉYXoø(¿«…<±‚ÿ¾¤7s®‚iž¾X:»0J&»`6¦˜63ȇSàìˆNíã‘Ú[k¬¨\ñ¡ƒy>\&ÅØL Œ%t­Wð¾^Æû¿[­4Xp°å$~ 1%vÚ^–N/•å(V¶"Z…h¢/ÓÙˆæBSªtF¯?½IÚ0 ‰iGÏòŠ˜Û–" $ÌFŽ• –ÊYüýª"Ä6vªSk[²Ÿ“^Ñ¢àa“Û2 qr÷©“’ s‡â ôE F«‹é¹N %` F›Ç 5d? Kþñþ¯?~÷¯oª¥C±bjøUšKqÇ貂µvÈØúp,)Ï ÌÅô˜ËßD5jfÞ½þç÷ÁÈDØÑ‘þSpÉx¡åF¤6}ðsLÌåû¶¦'/ Ó|êÊ»à±hΤçX§âù?3¼\ûs±  5VÛÐÄ©bê½,€ÍDrõ¼ï˨€LgˆI‰çgô¹f¨lò DËQä±]¸÷1,oéÄA:øàß¾ Ó1¦ t0êƒ0tð]ÅÒºä8UY]7æà%t:u(ÿ×Uï—KÒ0>Hù!ؼ¯8¡gÆŽy“¤-%„¨.h©•/ƒb&2?¤,·§M?Ñ2P]ƒÃf XÌ+ÒKZéÑÁ+Îû4ªÌ( ¼§Q¥!lŠÿTFupõKa…Ò\]½ÉX–d£Š/Îðfsôúí¶)©†ÿãÌ54“dÓÈCj"6Ï9ò6—g|–Kµ±ô‚)ÑOoßRkcc xðF3Î¥iMÓbïàkKñ!‡H7ßÓKD¾ý59F9«P¨g_PÌu6(>ŽçôÖ<€Þ‹Ž;éÓ•ðl³c£»-¾Ø§”ä€ÿc¿º°Í‡i†äÒÂÝžŒl%ã ÒX…I9¯Wa¨¥¤—•¿,äsÕ NÕÏ$u›´Ï̤zØU”OD¹âLuËåÞzz×4Óì„ÅÃU“3F†C(!§qÂ33C,á']4€ õf1¨GWe,Ò–D‰iËüœéFqô¢sâÌ0 ¦s¢bǼ¥üˆV}¶´ø’Žû ®Æeµ3 Õ,Õâ˜ñ2@•î6SûPŸöÛ!mãuh“Óe9e±%üŸ°*èÇÄ8‰þ›ž Ã™Mü<Ó,[Úó×QÃÇ×Q\-Òþû: »Ž‚C­m7xËTæPÒÝ7hûJ´áÃwþÆP;&<0ºò ã3Íâ¡ ô¿\rÍÒs÷³Ñ€à³ÌŒM#%½ÉƇ\¨|¼º„Iø+o.éHGš—ÆK÷¢À~Œ¼þÅ÷¢äø]ÿøÊŽÉ†}mj§ºô×RïÂdÕ•/߆Ѓ“^°‹Àv}fæz—oEÄC0—ÓUNeƒn§šKÈ€÷¼>[ª® …b5ò†yôÆdûp]éêr×ËÕP•mé‚i_ÑEesÚšY Vö•ÿÈ‘öû# ˲Ï_À‡%s‹@Ï;¾éɘoo¿ú¬»^ endstream endobj 202 0 obj << /Type /Page /Contents 203 0 R /Resources 201 0 R /MediaBox [0 0 612 792] /Parent 205 0 R >> endobj 204 0 obj << /D [202 0 R /XYZ 72 720 null] >> endobj 26 0 obj << /D [202 0 R /XYZ 72 720 null] >> endobj 201 0 obj << /Font << /F34 144 0 R /F18 140 0 R /F17 138 0 R /F38 159 0 R /F14 141 0 R /F41 161 0 R >> /ProcSet [ /PDF /Text ] >> endobj 210 0 obj << /Length 3687 /Filter /FlateDecode >> stream xÚ½ZK“ܶ¾ëWLånEÃàÅ—§J‰%G)•íHëCJÖKbghqÈ1’׿>Ýè9¤¹ÒÊåʉ~~Ý Øvb÷Í#ÁÏ\?úë ™î¤ ³(R»ëÛ]¢v‰HCa¢Ýu¹{ íÕÞHó+•®TX¹¹ÚcÇ6Ôíí ‘Á8 ßÑàpäÉco»ðj§Qð²¡yñêée‘÷öñÕ»ë1É%1J‹06 Ðêh©óžµ Yfa–L“úc;Ö%/Ü6HõWLdNºê™Øö–_Ôõ%Åð†ŽÚ Ua{Üu·WP£Ìn/MhLLÛáÊNÕ·'K­¶+mǃcû©7óZ‹µÝÈÇj˜fñ:}N+8FÝŽ¼dÞñkw¶$ªÃØŽ=òVÊàÚl›òJ¼8Ò/'Ë#Ðòû¢Îûé1&¡m°Q5eUäƒ-©; Ú¿Ú®íý¬MñIB‹sšMéšѩŸçH²„tÖíÇ3iY·?w¶¨z¦j°Ý© í$ l'-®#½,¬&´Ž9ÓçO¾W*†Ó%nÛîĤ™ýI(ö¤Ýn1ºT½ûôÓ„zVâ·4ÅÈË):T‘ô3ª­Et˜eÆÏx÷Ù5žn«Œù¿û¹I®LC%²™Þ½Œ“à >bz$þ±y£Rò!‡‰?{˜IEÚZ$ #­8¿Ô“Ň­5²P§“"}¯ï·5²OZ_¦³#øû&*œ¥*À#‰žgk1pØ^ë$ø<„ÞÖ'­€'r"[¦«š‡xõìµ2>zã2ìp2)§Fø­Ë{Ä9 œ#º4k(ïzw¨8½G¨àUÂxÁ“êÞµ88òöyq%E<{õæ9õï+’MmÊ׬äg“¹Ä[äˆKéÃŽ^úqF¾ÇìlL=l©d0Ùƒô.ÎæÀù8-Í»f8 ^œ"?ömÃx©C©'vÒ5Xs½¿°äwÁéwäù/%°‚¼z]2»(»~N¹ô\ÏrR’Ò§„xƒÑÒÈ@táÈ‚û𠤌éó‘¿¥óH,c´§¶;ƒ½`z¸R‚þ%­f{hHÞøÂyÜ‘.8pÎ$|éM¯ˆðFƒxŒtU&á¸0Úea©`ûQ¢äjô úfæÔ¥/j#´3ùcÐö9þj9{eÂȨ‹€aÞaµ«Ú±§Ô[—ÜsWLðÄ4ÛÒÝX¸X±…i0L§j…”·NiÔeÕ‘2åý06¼ Ýekóž]‹B S·¥Ž°²žë_V©I åã$i@L*Š—6°ÌH0œÎÛaË‘°ï«Ç_.V–íŸÃÀÁ‰Žyµ¨ ùyL¢1Ðu}LÒàåò¹t¡WÐË?FK:Á×Ï_<ûáÕõwß_¿üîÛ7¡=¿~ôó#ÉÐMFi˜ÆÑN«4ÌvÅéÑÛwbWÂ+ðN•>º‰§÷õîÍ£ÿÐ…¬^URUq¥Dðöß¼~öý¿ÐCñÑÛ<Ýçñe¡`¿Ð{@4¹‹|ï]P)i #*J¿ÅàA&z…!Ì ü(2 ;°N±>½ùþÙë7ÏÌ *+2}Wú3&³\QÄxè“pÔ™l©׬|‘šjUØó^†{,ªÔö®±Ô¦éÇQ¹þCL›óÄ[Zßyú;†»[4t&érý›zóÊâ°Ž'»vÕ¯Ô#ÌêW§.ƒG8no›¾º©ítNæJaX€§Z§ŽáÆHFÜØ*ª®OÀ±6º’$ þyÌ›ÝKKW03®ÖßÒ]°\¸·F>ͱܚü¿Û-/¹5ö¶`“üÌé2]Z!'ãœÙ?^G_r,£=ÀsøÂG]5¶¶ÍQaö+|DâévéVñZç -¤•çƒ`áʱ¯"¹ñvpE|ìܹØïªQ0©pÈ2(ù›Û®=Ñ´€üï)Š©J„ϼÄ\ \BÛä¼øàÜ—ÑLT lb°k7¸2{¤OhøÞOýíÿÈùѧZèº*®ï÷šÛ j"—¡GP{쓾ê'ø´“#ëÓ9ò¥}Råo-Ð%ý÷*•TjÃ@Ä¿¨`ÛcÑ$h¬†>`¹0y®j;Ãù½T*”Z./#ž¹Ëœ%tñl–g–4³»}ÛxB7}}ž6[îtÓ¶µÍ7K1&³xòH;¸Ë¼i7 )& šüäjŸ©¿tPIù_ƒ¥¬FiWÉM©’‹]F6 ½mïƒðkÄ›ø²æRŒuås^†€ífÝBÚìr'¢÷x]›K쫃­íÙÏ¥Y˜©l©²åXØÒU+âûjOQv™0ÞWÅ9èÅ]J3Ÿ0fœ0¦—ÂÔ×%¡á9UÓ¬š¯Rlí)ãõJÛ]Å,ilUÛòõk|‡7+þ}kþTfUãwJF)í”÷ŽÃœh¸ÄöеîWŸ‹ßJK÷¸¶äbù›öd±FÒ;ŠuPV›®Ÿð«ƒm, ¸¶ë—?5Üs¹¤Dƒì™’ùúÆnÛÑå½ÐtµóHøª´È…ñ[ëmw¶Å`˧t¡Öòw¸adtâùÉoê¶w[”òÁìÒ÷Lðs+ö7_SIƧ"9Ðó|ÛÎU¦iú;í¼¬3™É¸–~4 ¥0+3¿æ{sü7Å%dÃfÌ8RxÈqV˜Ñ$3fÄË0¡— qUµUø³Q‹óŒÖ9!Ðá/Ѝçdlü¯xÆLU£ú4¸îH²êœ°©g˃å;UƒÿÒ³¦KÙöŒÀÆd2xé˲*µ\#ÚGùKF$u¾—W){zx=v _pmwèÆ¹Œu-;1]ÕLà5,ƒ™ªv—«TU%uçÀ²î¶pÎŽý}E޽‰2÷O‰ÅpùÓSÓA@˜03‡ÆéÿCxqî ’Ñ_œèûÁìÁ¶ð>ß!·hú4ž Gý˜3Ã:=ìÝŒ½öÅÙEe]f4äÀ•%w’å¿ ¢ÿcÑÝ÷ endstream endobj 209 0 obj << /Type /Page /Contents 210 0 R /Resources 208 0 R /MediaBox [0 0 612 792] /Parent 205 0 R /Annots [ 199 0 R 200 0 R 206 0 R 207 0 R ] >> endobj 199 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [480.442 646.276 488.287 660.224] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 200 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [343.357 618.049 351.203 630.668] /Subtype /Link /A << /S /GoTo /D (section.7) >> >> endobj 206 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [397.841 587.364 405.687 597.061] /Subtype /Link /A << /S /GoTo /D (cite.pgi) >> >> endobj 207 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [407.567 515.135 415.412 524.832] /Subtype /Link /A << /S /GoTo /D (cite.pgi) >> >> endobj 211 0 obj << /D [209 0 R /XYZ 72 720 null] >> endobj 208 0 obj << /Font << /F18 140 0 R /F17 138 0 R /F14 141 0 R /F41 161 0 R /F34 144 0 R /F38 159 0 R >> /ProcSet [ /PDF /Text ] >> endobj 221 0 obj << /Length 3066 /Filter /FlateDecode >> stream xÚÍZY“Û6~Ÿ_¡ÊU5bHıUyðn쬷»6žÔ>$y %h†µ©”Çóï·Ýáxä•}q4®Æ×'”¬nWÉ껫„¿¿¹úúUjViÛ<«›ý*MÒØ³Ò‰‰™¯nv«Ÿ¢»m‹[o2¡¢þÎtt\oà×µû¦=õ–»»ª¼½[CG_=¬ˆâõFfyô­Û§ª'šWë41Ñ‹7ï_Æë_nþõõ«l²‡°~›ÔĹ’´‡MS¹¢&úT饊­Rp"Oxß–½[çITœúæÐñ€ÉJÄ21aÀßÖ«môz›3ÎWvT ß›ðl+8,xIÔºc Z¤öîgÐ66ø_¿’éD÷ ‹áÆçùâ5ƒ•=#èÔ1-ÎŒF 8+GËü þ *AÕœ> ›3‚$éWèHÁ.—ù*k¥/ç7Hw6æ7®;F¢%$z.fÀE!äÌÉâ+Èòœ‡p­©ab»– 냜?ÇÈ4ÑÍ•Ç=LNà†Bç~=¡j¡H¼ŒÀ×_çé°tSËc‘á0"åM‰•Ž­NRÚ“Œ3«Wð œùì¾lœk£¥X˜Œ8Ê‹ÓM¹Ó‰Ét vR¥é£à³ÄXȈ±q]šœƒüL §`µÆ Ó$ÉòÅàâz{´Ä@ð­“üþå@’NübN $œU±˜;öƒì !…«LɨäÔ"é“­Ù%gñ«ßOfAUöOøÿY~¡ÿ/m¬RñȨ≔DŸUf•&hËâCÅ4‡MÛ½0×…Ü}(>•ß³ ÔA‹Éˆ]“¶ØöìÃ= Pγ«8£uâOã­¢û´­N;Ö¨bºM³ß 4Ó5<šT}0‚…s0‚óîЕ“5Ý5ŽqLµmDzB©Â­&Ó(ÞßÖÙ'ï7Ph§"m¨£Ä´÷eç.(^½~órÉt IG¦#[B_öA_-BQ›åˆŒ!}C6Qé çÔØPÛX…(hÕà­(=&ìùpV2£©?“AÊD«Aß_àõ£a‹E–OaõT6)‹¥¸8¡A3çjâ @=ÆDD¯{j> cN×… •¢jÑ‘*vToŽÔ‹*s><†vÜž™,´×eE’Φ¤ 86æ6å\¬ÞþøæÍ²àÍ•lùg/ 5HZ­ëw¨>–ln›t’…àKÁ 8YÑrhŠ& D9¡X¬¡•£yÜõ²à¤ÆÄRÉ©ä|lÊÝÒžf’|·©xM|·Ï‰×Œ§Îµ-‚ÑíþÛàÏvÑSŒvàã üNäNè< _ÌWi5¾aãoØ·¢ü‰r¿‘ÍX“AÛ±õ4ÑÖíNdòiÔ9,f#T¶`QÝŽ¥ò8?*"Yt!U÷åCÅi#2[* Yjmy‹0à0`'™lÀËÔ'…Pë6/ƒÍ,/佤 øÌ-ÏéßTö'&a¿ò©Ä±º Ïõìqe7öoÃÁIš_ÁXúàÊvKžòÓˆ_2àÏÊ÷9ÈkÞSù,æý;\31…hèéÊL`ïpê-¨:‡½8ç¹™$[†W#ͳ͞yLƒiše0H ¢M8ö–6rÅyNh>?9!Î’ü‚„&Lñ¸0 #à„oZ÷œi†Ò^ÍÑ÷@[î©…#ødñ,€œèAú[™ýeȬÜGW=‡JPebÈ >‰J™“¨ÊÜ+Y¬>²µ¾Õ¿ú DsHb×’H7‚$’„%i65{yÄD‰}’F2$M>†$4×´ªtz} _T©wÜV¹}hÈE‘ѱðYqhßQˆå…Üûv×Q×¾mDÞ‡YøxMMO‡a%Ž2úþ<¢YÂ]ï½ ¶£Ý¹Ö‡úyùÁäï R&XDç|ÛP+‹I„°4²}‚EKåž¾œíã¤ïç‰Xh°„æ ;ò­Ük/8;÷¬;s?#%ÅÀ/ R/I‘dÜKMD R$+v¤K‘d•ú<ÛTŠÀ‡±ùü1–¥( c(xÏü,H™šT½‹“O ­ó¯**»@íýcµ¤öÁaVIRû™:«} `µŸ_Õ ÂjJåhƒ œ^ˆ®AÙ ØÛÙÿ¢ô–:è‰ÔfÀ íßTÎìšê¸¨ÿ›Ë. endstream endobj 220 0 obj << /Type /Page /Contents 221 0 R /Resources 219 0 R /MediaBox [0 0 612 792] /Parent 205 0 R /Annots [ 212 0 R 213 0 R 214 0 R 215 0 R 216 0 R 217 0 R 218 0 R ] >> endobj 212 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [225.755 642.159 233.601 656.106] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 213 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [271.929 594.703 279.775 608.651] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 214 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [378.891 329.199 386.736 341.818] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 215 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [277.784 281.743 285.629 294.363] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 216 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [196.273 219.842 204.118 232.461] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 217 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [310.129 174.711 317.974 185.006] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 218 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [518.694 138.713 526.54 152.661] /Subtype /Link /A << /S /GoTo /D (section.9) >> >> endobj 222 0 obj << /D [220 0 R /XYZ 72 720 null] >> endobj 219 0 obj << /Font << /F18 140 0 R /F38 159 0 R /F17 138 0 R /F41 161 0 R /F42 169 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 227 0 obj << /Length 3293 /Filter /FlateDecode >> stream xÚíZK“Û6¾Ï¯Ð‘ªõ xd¶rp*¶×[NìõL6[›äÀ‘ ‰ŠTø°ãüúíFƒ/ çålí)@<Ý_Ý_íW|õꂇç××_¼ÉJ–#W×»•à‚%I²²MT¸ki#WPuU:ö7b}©¥Œžã-µl;A ºÖT1|Ù<ƒŠTG¸ÁÚƒËæ½ë®8[A׸íZDŒ¦z¹NDTÁ{è¿Íw?q¡7]Ñ®¾þ;ˆáRh¦uL;Ý×Ùé€+ãÄ ¦*²zï¨æÃÚàzDTtŽqVl©Ý¦:]¹u[œYœYFUMÝ\Ö䮦®³9`µÔƒ‡Ï¾q» ç[‡jXæ/Õì”@.þ”.EÂL¬iíyÙR_a§}¥dÊ$°Qß阗yù!«AÊp6Ô}6tœ2£tßýËõejÓèúàW™DÙMS]Þ@&Ê‚,’hŸÓÉ5ôÚÂÖpÎ#¶tGj™(¶g-U<ätÈ‹ÛHSBô ó›8ÕkÃátág³´#™PÃ'óÂïxu©¹ñG>;úÒ+<e§S‘û£´°EÐ\îE •Œê 5)ªZz­vôE{ŸÁmPƒ·,¡®øÁç1`õh#8çëÝ’”ÔL ‡YÚ¼*¶wí…•U¹$‡”3e9|„›7F!K¹<ž¿¹záO’ñɨtû¬ ÇK5d þìe{+·pxöæªi„ª‡9W¬˜¡„¢ò 7^Æá³¬k«#L¿ÉŠâõlÜ¢ùÞàhŸ‚Åè®á‰j]Âk%ú®si©˜=ȸÅãÖ&lBkXsÖ´T7]>´äå­®»öòXõÝOY{XìiæÀŠ ¬Pú]½Ü¢6ÉâѶgl">ize0Ì&gŒ €a¹í‘´tø‚•ãîê6G} @¶¬À"1 ‹éS58I˜äjÔ`0Õ$º~û~})¢ÏÎVÓäû’ªz„†ŠªF“ö–V1“Èù†ŸOQ>ÀZì-Ü#t5Ô_Ëj98¨ ÎYÒPãâ6¶{Àÿß"{öÛýÈn9³j ØešN€ß&Àޝ`—iv¬Ç)G{†ŠaÃaЖž;g:–OUb›è‡€Ýü ìƒjÏN=ŽÏ=ži?¾NÔ]ƶGõ8˜Vö§ŠÛ™"Àkvøj8 ¬>ö8þØÿvv}ÿuܺr›ÞP±z›7ÙMášÅ Çš)ežtFÚ2#¨[dü´,&š¬-ÙÓa¡!¡¦Ñ~|Ô€”©¸.‚Ì^Eb ’[QOp+~_þýï~q[’™ô¶kñY¬gÖ¯}õ)k0Tóå{ì[qÆEüX·sû†¡Né^b­ûíÌ”ÂP‰:CKVåÝ€6nÛ-§Gª”zÚÁƒš‹áàŸÛ”àù¸ž«ëè+ý©óý!¬n.‚ⱫêÞŒI„þåÔÕ&W}x™‡Nˆr®YR½'° À¼Íáƒëw;;3+˜©ÆOœ«%9–ާ…#z-ƒQ(X¢Å¢Š)-¢þ™ÑƒŽzÓzáÀ»·vxž.Õ‘ rR°(ªöi_BEòcj.ª¨LbŸ+y”ŠZf¹˜èh@iŤ™+B®ôó?° \’ª\S±E\ð%Ê&Àyk¢bÎah•L‡oKiP:da¸]‡NKMw R¨ÛÐVÕÓᩜ‡AO™×Ð_¼‡ß.¹kò)È™ÀyxVcQï`Sß}ÿæ uðÏiúôÎ1o[ðe:eô˜¦à±²+‹ü—@bð ¿Tßu@ɆZBd ‹ ]íÜö¨#å=´¦»©½èè›Kyõ%~ýöÝõë·ß]á/®/~½Àæ+±’h qêk™ârµ9^üø3_m¡&c*MV}×ã \—Gˆbuuñ¥Ôœ´†qJÀP~¯Þ?÷7Z"0§E?he„~´UŽªLªO‡Ìœ+Q}sÛ‹ibwKÀ‰\ÍN—r9Òv1èýl™s© À$Éã•æ’%&~@ª‰=“ê|QJ2›J?VllŸô“ŸE¤€h¥#pÖ„ŽLzÅ[QP/$S€øÄ–ý„b<ÖS‚ÀyÒä …8Ï“´‚¦âÇÊë~-ÔàdÀ홼®Þáž¿¿zA éOU)ÍÒt w))pŽ$•OPR«åLIѵ%-CvÝ^ß(dü †ÂZMz×:æR…áX Úª€Ã‚kú#J¨€äH%üPRˆ +šñs™ëŒ¼y¢„”¢XTB×N”ÀyYcËâ1²\f[¤¹vØznUBòl±Ù¨9àÍFW„×!¶ÆNèbCX”ÀÁ«ƒˆƒr]UGì˜râFð$ª’+¶¸ÐT' ÍKÐÂÇTÌ=rƒ A<>«÷ÝÑ Î&8f=My¸ìÁ›–Òß½ÀB†õm0–Äœ½YØwQäåžê€ç×"RXŸ9C¡m·ASÑFÞx€¹H•>ŽÔ)¦• v"$¢62m€9ÖŽfD»$IÎY"'„ø~'d=PLŠóSÆåeÄôOíbn#~ñ`Hµ­Û=˜SAhx‚\ŸP÷ Ê!=Ëd<|wÞ#5÷Ž .+‰2HÔéƒãÙ'å ãGUC([¦â ±!Î:5?-ú̶µS¸ÀÜÒ9\`—¬h*jÝö—Ñå6$ÐdÌîé^YÌáõ1™ 3QÑ»|†ÆÐÉFÞ[[KwÄðb%kûX ÌdH·Çœ|â†îG§„‰Iº"¬(Ä·6p$|º¦ %\ÞGü©&; Qàí“DÍBñ¢OîTǪ>?<¢·²š2!íãŸÇ!Ö/Êçi²¡ä¨ÐdÇP²waï´¨kºô®^ÌÄBKØ*”†eR;ÔKQ_Rc[Æô¾SN¢B­ô@ªº†*F׉ÙºAÐý ì§­»M{WZ)èhô¤M›µ‹~T¢MêÑöc»–f½Aú»ìÑÆígz4k¼Iå5M‚9—íÃ^‡ud½š€Ä¸¹¥&EQyåj¾\¢”|ž ÜVÝM±(,0ùd j÷õ©Éwâ.Ú!õ†Íg…xÚèÑ ʇ' ñ‡¼=ôPW]¹%ªbã|QU£©$éˆ U½íQÞî `ü½I°²@s$8ßó4ÿf:á&X½ŽÜ¯çMPE¹§[î Voî«>Ãqmã ¡_†±Dðå ‹Y 時cyŒxS ŽqÒÝ%G ¤‘˜ Ù¦¥"G¨B¯Œ!Aô‰û¿ú@Ã\xä 8´üL¥Kç¶n‹—jqê±Nš}&8DµÅ¦+2ŸÖÂÆ]]©D9jèRuí©k©²qª}ç@T}¯;¸¸âŠY1œÞÇ:oÝ1«Áœæò}°ÑjÎÜýå ˜";¶šI“Ì7ýÉû†owEØl*£Mu<…+dA¢€Jº±ÀÒ'¦ª«é` ¤ÎtwX´ù©v›œÒ—XØÚŽ®Í7ôQ×ÏáÀ’ ²ÔN¹žg7‘²ËþÃ9^¹ á:d˯\ˆ­®ð¦ˆî³.ˆüÖûÀ‚ß¿ºXý裱84Ó_íî ¢géõ§\Ì”@ÀM¾ì$Œ˜R¢ù¿¸bÊáu^è7ÿ馷baàY] :Ñÿ£k@áOm`.Ë;RÜ|Æ?`‡{W:b”mu‡ÇŒóÏß©Ÿ€÷õ;çå}¤ jñûˆGoÞ5wðáDž-ÿu/òÃpÏ9¤ Êß]]= Çàó±ôCt#ÔÇ·,|°umÊÜÅ $°DûxjœÝa¾ó€Ð49úëù}kX„/—ü4BpÈψ”]üÃÓ¨ß^¿}ûõëWaTÓæ‘#¡ã¢kŠGMïË/!*£[CÏ{š˜ïÿº¾Œ%Àsì^²„l·ñéØÉ¿°¢Dp °)ñ¶¿}ÿÍÕë¿ø‹Ýv!/cqÎþ€÷íó}÷G¡Æcp4WÄD€«7·ùÊœ%*œâï|ü$†ÿ:`•’7‚ÅÃu¬ ÊÆæÖÒ±S¾£Æeš~™#ÔáuÞÂ+ $-žºþ¡Ï‹ë‹ÿÉà± endstream endobj 226 0 obj << /Type /Page /Contents 227 0 R /Resources 225 0 R /MediaBox [0 0 612 792] /Parent 205 0 R /Annots [ 223 0 R ] >> endobj 223 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [206.571 156.546 214.416 166.841] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 228 0 obj << /D [226 0 R /XYZ 72 720 null] >> endobj 225 0 obj << /Font << /F18 140 0 R /F38 159 0 R /F17 138 0 R /F34 144 0 R /F14 141 0 R /F41 161 0 R >> /ProcSet [ /PDF /Text ] >> endobj 231 0 obj << /Length 2821 /Filter /FlateDecode >> stream xÚµZmoä¶þ~¿bÑ/‘/#¾H´@®½\\màâ Esý ïÒk!Zi!i}çüúÎ#JÚãÞ ’|ñŠ9äÌ<óÌrºÚ­ÒÕë)ý¾¼{ñݲXqÎL–‰ÕÝʧœE±ÒiÁR•­î¶«_’ª.þw÷Ïï~䋱B0™ É z,û‹µyRø«“Ú–ý໤ð¿÷ÕÐ_ú·e³%™j±¾Ð,å£ÌmlÙŒI.Çÿúá?7~âóAÄÀúk\N‘9ÿ¾€=ݾýÇO×ÿ}ÛW®˜Hóq´É3Lð0¢m÷¾ê-‹I[‹"uf^sÅ”Êýœw)×qÁE°òÍÝííËë×W1óŒñiMLˆ'¿üK¬nÞúak».¶ªé ™ ¬¡Ø“üMÙ[Ç£E–ø=)|ÝY?²¢­5´ÝΖ5õ|IZëá*RÃÀ½ ЀnÖá±"¸Ê®ÜÛØÀ½Ñ»o{bûòp¸àôMéݳÀ-à Z°,W~µcÓW»÷•q•Ô´–0”¬˜lÒ÷ €c nˆQ;?Ç]]¬6ÉÝ£%­ÚÁvÝ \Žû `¿{DPâÔIû@c;K³O’[KingÛ•ƒÝÆUåò”Îÿ]ï]ଲªk<Å×)KeTïÜ)[8eõ\Ùœ”ÍsÌØøò ÿ85¡Ï¿Óˆ/ßA®÷Õ‡>úïÝ´Ž†óxœq¡ ¯›%ÐÀ¦f6[ÇÞÖNÐ0©Cvºõñ¡·MoÇ>¬5p”wŽI ˜Û}Û·û™h$]ÒÙ{ìyö۪ߴ“κÆÉi¶Ó²¨@ºdͱë¬ϰ&[öÃzwtÛžŠ œÌï7Ècµï¯KšV× Àõ…­:d¶$áxp·ç¡‹ª©dÓçK¶}ù¡¶O¶Ž’<:B¹Á™ÕžbÇu€gÁÚ7j4’7bîÙ7$€$*\ψ%ãZB½´%¦•:ÿÂYfx8šŽf&¢ê)çL«¤µÄWómB³mìŸKTÃÆ“M,·@Ö1û*¥GŠÂǾú:Qwü-kz5„áeéÒ?oR½ÄØYŒëmÙmÐ#ôŒ×F»¥ù ,íNÌ·­ ÍÆ;°å€ÖôÑkÿ†r<=]dë#M™*þ…Á¸†B\_Lí3Såyè|ôVž–Ý*þâ±ÚÒ|Ëæa¯A¡|SBÏ”%”zú¤8€i‘:Fð<…Ÿ. $ËE¨~¿!r 7s®§ürèŽ PAZ³Põ»ñHp Z¸ÎÛ¸ˆbS*9åÌEÎÈ𠆇(wQ’Là«ßP?¸¬<™7Ž|Ç¥ ¬ê»€>×”I b1šŸtë} †|h»‰ra#uõŒuÿòåÓhÜþör,Ô7õqHz«ˆ¶«vU3J&I.™TÍTYPb«yâ.é— ¢SÁ'úí}¿O_é"ÅC“”ç˜.!†ºÁ~XWÏŸë]å ð£Þã³·.°þ!8Î]ŠÀZ_”Þäï2_tàþ@ªŽ£?LdñÌgŠ3£!ŠÁsSBÛ™Ò,«%32‘)ΙÐä­©5a l~´ Ï™P'G=<šº¼Ês •?Мj*Œ‚ï ø…Š~¨ÜÑ“*ùÎŽ#Êæë$ÇîmØc,¯êÆnãdÄ?¸HAÔw ûÙJ%Gcäqè«éJ-“¿"ì´#ÔI(²¢šŒd­(>Ô2>f¢¨œ\85ã èü˜Ló“ÃhPQBç7$1r¦1Þ™ë<“¡:8)ƒçaGDú›EyŽ<NôYÃ|LË ¹Xݶ oáÏÃOl ¸ã5ÞAFO<…@³¯’k ‰cüfá[ã§ªå’øùÑDWܗݯ'ã¯8˧ëà“å.}³j༼Çã%sèÛ´Íb‚NÂ@)Ngwr¿éo^ñÔB—¯Ø¹v=,kCÜô`Çz¢=)±8'2‘åLæüÔÀÞ‹9ËÛpÎÔôŠDÉS&d¶?OQb¥™Ñ)wêÂfñÃ#ÓF‚•¿­s—_n‡ˆZÒ\Œ‚°™ ú>& ˜Û}☆‰/’uuuäÉ™<4X k0„ iQDzŽ `v(Tüý…2øÔæDDòküï_ôCy_ÕÐì&„·~”bž,Ïôg5Làá±$ýH”bªä<}™™Ù2XÉ,ÜÍŠiÀøle˜H€¾I—çdŠˆÌOe¤§ˆç%þ3 _¬õ'Ø¢àóõ°ì”ÙôÉnªØôô&5Úºö®ÀKþó]Î!Ã]-?¡snXt²Æÿ8 s¾óêîÅÿÄõÈö endstream endobj 230 0 obj << /Type /Page /Contents 231 0 R /Resources 229 0 R /MediaBox [0 0 612 792] /Parent 205 0 R /Annots [ 224 0 R ] >> endobj 224 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [197.856 678.157 205.702 688.452] /Subtype /Link /A << /S /GoTo /D (section.4) >> >> endobj 232 0 obj << /D [230 0 R /XYZ 72 720 null] >> endobj 30 0 obj << /D [230 0 R /XYZ 72 207.173 null] >> endobj 229 0 obj << /Font << /F38 159 0 R /F18 140 0 R /F14 141 0 R /F41 161 0 R /F17 138 0 R /F34 144 0 R /F42 169 0 R /F40 233 0 R /F43 234 0 R /F39 168 0 R >> /ProcSet [ /PDF /Text ] >> endobj 239 0 obj << /Length 2472 /Filter /FlateDecode >> stream xÚå[_sÛ8ϧðôIž©Yþ'•ξÜÌvoïáæf/û´»ª-ÇêÚVN’ÓöÛ/@R²$ÓŽã:ÍÝÜKDQÄåÐÉý„N~º¡G®»»y÷A² c$UŠOî–F-IŸjÜõn1ù-ù25ýãîï>ˆtó†2¤ÕÄpkÉõd’÷Èá©yŽæÏI4ð¡†4“™%JëÉ,%T,ph<Ó„6™1AdÊÎTøå4V^ã`9^¶)¡©BrÃSOG:™)a#s¦7w`O0c–P°Ø«¹lĤ5‡%–õ›@&&NeíeQeAy"© -%L%^wtëü1_Ç "4ì]6ÖÀNÃfi nc<8,Ô$óÈú¡Â)nRqB ¹á“Ù<_¯ë÷1¡Œ¡e+´Š åF]"´¬>Í©)áLµR£RµJ/‘º,¾ä‹÷Ó™b2)¶‹üKL¾IAP'¿ˆîÇ4•OËW°¯Ó¾øw1q°ûU·w?E¤Ib¥ˆI…€ÍÈÜÞÅpH_ z¤:y”F…)«[¶Ç'RlPÇ!•H})j€ÆœÇkDè§¹kO/¬{…%£îòéâ]Wào;[À¸äñˉ<4Vð°¶ie§ÛQ=¬Tb°«!{ Ä`¯‚ìõƒ}WÄ`±zt&8l.q@4èçHÿžWùÛhL]œ6´Ž‰9l¼H°0Ó&ÊËszø!Oáy‹í/¦½¼÷“±:N@zÏCËA`ÖëQõð7M2©óÿìòí<÷wårŠ <ä6É«¦˜ç.,ÙÁΚO¹IV~²YeMlÌÜ é}ú+0„«¡Á#Ð# ã"=£Ò û¶Ñû/h}|ÙÞ‘ñ³xÝÞÞvüú} ´‹ÖªX#8v‚Ñ"‹¥éÐ MU<ÙšLgRÐä̻ʣa y2íumW;vøE—'Ž1 ±Ü8À7r&Õƒ…S·Ž,«rŸG¥vB¹"@Ê`¾l×”›²zXõ¦vfQɇ©å«Säðˆ Ö®{öá2º-;:TXÇBͳ¸DÝ ÛÌvʼE½5„Jî°,×ëÃës±½÷ShOTírÒžß(¢´Z=šõ<2ì·9Ø€Ÿsü¬˜“ÿ;1·Ž¾pxÌ.8|®µÆ žºÏ·y•5ùÂ{ð#:ô«Oëá^Žî$+ ;?¬¿s\«Óq­8ëÇõ²¬â© /õ:A÷)ÆÐç°aéÉàÅo)i'*Û.¼3£¸9ì9ºq &Ÿ§{ "޾ë÷§Ø %vPÕÈ‘êSšBÎÇ£Ýãÿiþ;BÎ*‹‚‡Àèç}[ÇÏz)| ¶ WV‹<àV“ýŠŽ5â‚ZûYÇã#nÃUŸxƒùŠºi?Š#V*øóŽ£†ÆÂŒKíð ÌæGà 6é¾o<ï$}/L—ãf€[ås·2Ùbu¿ÛL]N›Á_pº£Àί®§ö´Åvð²J •(šìã:ðzÈ hŠ2A«È¡Ì odÐyÔMY )Ö¹ï?Ž|á€FkŸ4li¦:(Á²K?|œºùfB“è±'dÕ}Þø1z6°YŽÈêlFÛm˜,rào½!|7g~¸Ø!a©PÎ"É{w&ÄÞ ù|•zˆÐ¸º\5–è’;¬‹áÆkª®`“ôâ D8î"Ð:çZï\Ñzå 7‡÷ä`U~îóªè:v¸õ­P`¬>NÝ:w"›¶ï0‡}GSÆ C}ÊÓúrœ„€²æ&=˜4£Ž4Õü\2ú¿":…2jR•êÕx õOWèG²‡2 «°ˆð|IŠ¢þƒÃŠ¥5§ë¸!š©ùððhå­Á¾2ÙÆx¥PLÄÎkÆ(³ö %Ç¡ÇgÐM$w+°)C“l’ÏíDUnp$(áT6oü(ì{¥ö£y ¸XÁk[äôæÂÛ2¹¯ÊÝCˆŠÕäpö›?#±ù3®ù3Mk?éyáL¯ „(¯ýì²Ü¹Ê †\î 8¸Ï¶_™lÊM¦Žh‘Ï«<« m`›gsD‡•¿ÛæŸÛÝÏnf’Q‡CxuZ3´ÕÉÏ[?ç²ø|·Îª·xÃL)«öMžmÃÐ{Áò0(›lí‡Q‡à4>^ƒQ˪è¬Ûîr×vb¾7®ZÀûMYG!­!úäž×PG˜§~ á!¡-ØÃ‰Ô¯õýÏ¥ÞzeŠf¨œÃï]‡¼ðd×u@6(™÷ßrTÛ>ß¹ýbÁ¢Yõ§ÏZµŸø ;7 P¤[¡ûÎB‰6|ƒŸ²½`KuÈÀ¿Ü®¿úÑçªhš|ëoŠe`e†'mÜ9¥­­°¾« ¾™£æyUG›jx kÞ;ˆ»_p¡¿þHüíÏAr—ß…†ÞÄŽrѼÜlJ—ÆY2/ªùnS7™?ÀÆÍ¹Ê¦,‰JK@þý׈o+£Å ½øáZª}¿~E´Ä-'xo_ =5—u b¼õÿDs¤âàgGoPAác|Rnp[!®H(.ÿ]l “}ô –2úÎÅAé}æºÖ¯.βò¯üharÿ¬m‘ãzôTÂCmsÎ>3нH¿:“V$ÿ,W3ŠSÁ¥ñ$ð).[òLP•0_¢û‚Y$.…”u]¸n-Ýx©-L- h4䮯ßßWÙêËú0µ,ÙU6UཛÌ7¬®ð‰ªÜµ¥1…€MG,ºÓÞ^þr`Ž¶Ú¶ÇÃ.ãyÂ.•ߎÀ€?(½ñ7€”2œ¹„v†¿¡ 7,Ì&þŸ~ùé4HÃ#ÿß 0ñÎp3–¼ JjmÛàªïnþžæa- endstream endobj 238 0 obj << /Type /Page /Contents 239 0 R /Resources 237 0 R /MediaBox [0 0 612 792] /Parent 205 0 R /Annots [ 235 0 R ] >> endobj 235 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [322.422 160.828 330.268 170.525] /Subtype /Link /A << /S /GoTo /D (cite.pgi) >> >> endobj 240 0 obj << /D [238 0 R /XYZ 72 720 null] >> endobj 237 0 obj << /Font << /F41 161 0 R /F39 168 0 R /F42 169 0 R /F38 159 0 R /F43 234 0 R /F45 160 0 R /F46 241 0 R /F40 233 0 R /F14 141 0 R /F18 140 0 R /F47 242 0 R /F17 138 0 R >> /ProcSet [ /PDF /Text ] >> endobj 245 0 obj << /Length 1621 /Filter /FlateDecode >> stream xÚíYÝoÛ6Ï_¡G°¿Ù¢Ö‚[ݧ¶J­8ÆlÉ“å$Ø_¿£HË’B¹N`Ø0ˆDмïûñx¡É2¡ÉO4<˜_\¾ç"MH‘ÌoÍM ¡B&óEòi¢§)““wÙf»ÎwdúeþËå{0 ±R2·‰&)§DPî÷¼]¯§)gjRÞ¸§žÔ·¹Ÿ¸)×ërŠ3÷«bé§ò@ØîÝǼ Ë«}á ܯêÛr_ûÙ–Ú~—ûÏžšdþqç‰ÔùCº*ÜûÝTÊIV­²fT7:8¡Á©„:(è)À+¯¦€®š %aF%©dD ã÷-cN˜4È¢YòÆ-¹x7¿œ¡ $L*b4$R["Á&_7¶ÝߨÄåÏžüX^ü†¿Ã§ô@)íj¼ º+zUJC¬b^¢r[¯Êbk¢åAòOaE˜ÓV,óúëTÒIV”EŒœ°ÄZq´DÊ ›¼Ÿµ“·WÞÍb PRnÚ=‹Õ²j8lo£ QžÁ Uò¾ZÕyÃa_—›¨Q”"Vµ˜ÿî¢éã ;xÅ&«þÈ«(}Í•ª/I*„ ‚[ S| å¿d*(Q\·†Ëo²ýºÞÖQÇ`,sª»*aÜŸV‰%Z#x¯c’í\ZÅ 0ÇH œcÌ Çè®0²Bâ“s‹rc8£q4(Ðd1¥ ·&¹o–n0N¥q ®“˜2‘¬à;Ƙ†–„`àu~—¯cú0IiúÐ/LRf ¡ÑYŠP€!k»¯–ð~šYb$æ­ŸòË?SIÙ4• 'r nnŠû)áÆ-ru¶y‰q˜ðWרÎDù=eu½ªw¯ÃG?w³zÈajU,ò?Íb¤{ðßyG"é§ô±ƒD""œ”ˆIDýwèHÌÆãÀMƸT ­ ¡¡#tž”ÙÄ¢:míΛCl4†ˆ"°Ø¢x½g½ŸS$šEŠ’µØ³«³8&ÐWÛÝꯢ¬0öå@bUÄ(J > ËFéŠÝ8Q&‰2-rû͸}ù”Òª0NUv¨.ó"¯RŸòÜZ¬êãsV—qˆwR_„犢õ(Ø.ò1u…aˆ[‰1ªk¥ëż ÜÅÙhN,gCø—¿uð&{ÅTŒ0CÙÅS¡“7m¶]gEæê—iÊ´mŠ¿æÀ6U–N®ò:ZÁ¹Sã˜[Ÿ)ÈÎ6Ñx`£ÝiÎ+Ñ6$k<ê‰FƒtVÍb,Ñ”=™a40¡”é2ÌŠEŒ%c¬z2O>ÆÓvy^;kOroó¦÷/U^›*ª¬¶·«SÍÔM¹/3|7ÁÒ=)î@LÎý{Y-Ü  n†–ý¼rTdš .ÇÜ‹eš8›Ÿ)ž±âɃ®ÕÇ_T¼P‡ÌeUî·A‚ùm^ÄDÀê_RL—”9zÐ ºvV ÖY%ã­F¯#d2ls žK¡Ð± @Iß„Ub`WÁÚ°»‰b25Gÿ`qq8ÃúY¶ ½Œ™:u×1”+Åë«àâ›ÆæÞØâ;ÍÆ3•8ÛT·1í’öü}™D¨ÂªÕHZÙjïnÜ>êU¸cûóÔß³wü¿Z`Ö6ßÙ˜‹¾ÞEòyùðý±øîŸCRƒ“ CPzŒ*îä ¢xÿÈo=UÇýÆûM<Éoóa¡ Œî iô@ ås ˆ¤ÆâLk ›X<8l§ŒÄ#ÍÀÚÞ­ø?âçÇdùw‘å§Óþ9áðwŠkJ=-xL/x„‰Ù /Fœ¶Õø«Ñ”+Àê^&)Þ2„HoÑÛ³ßêíéoöö‹W+ôKôö:¤â½=Ð6(»Î®£bbÍ ÒnnÎx•„Ÿ‰™œ©™>u©4ÇÊy¤©Ä {‚v¸8Ç=“Köµ^ÝåÑÛ”èvð£_?^]E©bLáÉM¡_Rþß}FT>¹ ÊþmMÐsz”úimPñü>ë©&(8¿cV¿DÔÑÖþãMPyhîùö¡)? ]=Úëgês;/Ô¥‡îdW@è ¨ýHz¹gvŸÙ"mÿ÷ò¡é4g¡ Çô÷`\ý ¿Ày8 endstream endobj 244 0 obj << /Type /Page /Contents 245 0 R /Resources 243 0 R /MediaBox [0 0 612 792] /Parent 247 0 R >> endobj 236 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./fig2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 248 0 R /BBox [0 0 56 60] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 249 0 R >>/Font << /R8 250 0 R>> >> /Length 251 0 R /Filter /FlateDecode >> stream xœÝW»ŽÜ0 ìõ*÷ +’EëÑH—[wAªM²Hp.îRä÷CJ$åuþÀ06Çäp¸’(ùÍz¬§‹ï·Í|xÉöþÇD—ì_ì/ãí³ )¹âƒ É»X‹3àÏ;ð³}ÿa®êÅ·ûf–‚¾X˜û›Wô‚êh6ËÜŸòºã^µ÷®‘Q¸ö‘ÿ ·wkv¡.ê´)R‹¨³˜,C²ôˆYrÍôx31ƒ+PžJ Ö¶… à"Ip@=Ä(Ìbc§U* á7óÓ´á´/Ïgª ‡©„†ÑhSÌ6<÷|˜—X!õ(šEä)öÍš è©ËÜîÊ v¥)]±0Ô¥+”lc„¨ÕÍ ‡:hÄÎ[®?¿jS„•A-µÑº~¬ ÊüPäôP›Úšw Ì- ¬\shmª‚‘¡»ãÇ:hÜÎ[ÛÕäHPÜ5A¤Ðô€¨IàÌÉ5ÕÞ<lÇ[' XбÇÂV„—¾KkæÑ<$­ *”ŽÂi NTÌXQ»ÝQ\Ñ(Mg]hcÞ™éy̶ö&NÑ¢ÄfÞ1Óuxšae×Ú cn¶ÇLdh-ü> endobj 249 0 obj << /Type /ExtGState /OPM 1 >> endobj 250 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 251 0 obj 735 endobj 246 0 obj << /D [244 0 R /XYZ 72 720 null] >> endobj 34 0 obj << /D [244 0 R /XYZ 72 720 null] >> endobj 243 0 obj << /Font << /F34 144 0 R /F18 140 0 R /F41 161 0 R /F17 138 0 R /F38 159 0 R /F39 168 0 R /F42 169 0 R /F14 141 0 R >> /XObject << /Im3 236 0 R >> /ProcSet [ /PDF /Text ] >> endobj 257 0 obj << /Length 1654 /Filter /FlateDecode >> stream xÚÍYKoã6¾çW=É€Íð1|í¢‡Ý-¶( ´ëž²9(±ìµ%W–“´¿¾CQ’-…r”MZFV"9~’3ßÌÒhÑèÇ Z?¿Ÿ_\~d:bŒX)y4_FšGšBAFóEtçÅͺÜO®ç?¡¤9•‚p+PO%÷íd&˜Œ¿PIé”M9þÁ„ÅS× ØË¦µŽÎlÖim£c_&á©8AY#vÒ„`d+±*vûõß) éE˜Ñ=ØŠÐ >Ä(ÕSËG« +å’hÕbÍÛaKe=¥0Né*ÍÒb"iœÌœ|4VËT4c@”,óbÈâ :Ëá*æá™ÑxLœÌœånÚE:´" ¬§XS|S-g1™ác“Vûð,—*xo:b–mò¸IïÓMp‹ nqº¸&Þ¼\q4Cóâ™Và…>e(&.ïÖ{ÿ–>&Û‚¯®ãúý.qû 7M~ÁðÅe7M„l·h“Ü„03I¨6PКÀQbWfÁãÀXh„’l´¤ ”·öÉwå:Ïöd‘.“æPleu&7æJJÿv_Y¨(ÓGßæþÑXó eð˜.ê-\KE÷„ÏïМ\ê89”9^µnÅvï»*kµÀC±.Ë4óuý,›Ï¿0· "Ù¯“ìßW¤»"Ýã'}®wŠšÆwë[×y×Σãü°Yøæ®Èo’›Í_jZÃmüm†ý3¡M|ãTUgAëø°O—‡X/}B«Eý9*jÙU¾ÎV~ Ì}—Óe]ËtÑM²u¾Á­ŠdKð–ã­çºï'RÆÉæP7óeèÕ„Áñ ÇÀÓn{žùý`•íì_‘–‡"ó—m-Ö· nk¢ðnø“ÂërBõ¬þ}Ù\ùaç_´—‡]Ïg‰<úŽeЉ{¼2ÔKà²;F¶Nå}X‡öFÉ7СC«éèX=»–iHî©„gíÑz"öko CýOìÁ¿‡%ÆÓÇsÊ#?XM µî(^]ÓhƒÈp‰&z¨D·x„d•ol¢Ïxš– ‰ŽÊTºêò4qˆÜ"uâÒösCn™¥˜‹ÌÈ–µ¨oÀ¡ÜÊúš‹î @ïå®”ïòâ.54È*0…a¸™K ]Ÿ­ûª,±¥D'zÌ(±z‡œX ´ÿÊû÷~´Ö¾\#%¬»18êèºyH· ý¸AP}Ll&Ù`2Hú,$9 ü¸ª!uÄÔÐ ÐðuF~NŒ"kP#l"Dõì·éfÓ’â,H¸´C0Y³Œ€¡žÂâ ,ñ`±ØNAÑã)еgúªk–&z“¸d<äzfítÙ©ÁÏ;Mu7µ÷õO»Ÿ«òàc°ÆÃ0Z6®Èó‚ y®Ä£ ^¡z0t Èƒ„4Œ*ò„” QJŒ+òhÌ›uO«j h膴Nµg¨¢£M޳pf† /§4]ÑÂzjaÀ&˜Yqùu¤f¢? þlAGpìZ§¾ªYÏ[0Ðöõy_ŠW¦j*ñ¢˜)cS;e´*rwmHˆ)ϸ¢8§Â=G²öõT™#¿E/>š*Ëaª|¢Ê3ÞfEœâ†É@ZϦò-Ò†DÊó§QKUÃK=j 'ŒQ"ü×I kO]‘0üö ˜Çñ±In_·òŒê]R`Ï$†#_’à¥ÒðêIΧTª1iÁ3Óâ'Tþ«yœÏ p󌈬"]ÖëÒ¼bÚi¢Æ¼2)ÄðžÉëÊ[•øê[SXe¾zÐþ÷SÄ9­¨†5¶Fà#„vøp*@U endstream endobj 256 0 obj << /Type /Page /Contents 257 0 R /Resources 255 0 R /MediaBox [0 0 612 792] /Parent 247 0 R >> endobj 252 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./fig3.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 259 0 R /BBox [0 0 157 51] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 260 0 R >>/Font << /R8 261 0 R>> >> /Length 262 0 R /Filter /FlateDecode >> stream xœÝX;’ä6 Íy †ë`´?™ºÊåØÓ}Ù»öÖt°ëÀ×÷HÒŽœLWþM$ô݇|ßx÷ùu÷_ÿvicÿ#ÿ—S¹ýÕ%®[ ä[ÝR«Ù?\¤ì… Ò¿¹Ò6j-Nù›ûÓÝàâ«#ªì[†u¨0£©‘oŽr†ck"V‘CÐX`PÌ*-ÑøòÿºŒ«'PqOʵç?í?„7×b’¤}Úikfr8n¡4ߨl”vŸJRJ—úpµ•-rœœZ÷‹‡I°0N'e?=Ôv1èÃM¦a(‡‡÷yHüys»¹}¿ÖêcrjÝ2‡æÕœx÷5t «n£—€ÑÒÈtõ`´Å€ÅàP+±7D¬{Èb}8CaCiÞç!ëö¼¹Ý\j H¶ûÞ¸!7ãTlëÒÐjìÖÜ5Ò»÷ANj/3-’¯m1`18ÀJÙ›4¨ì3†Ñ°(¦Æ@9=¼ËCÖíys»¹˜°ƒ9«þ£SE!ùˆÝÙRõ)³JõLðd÷aÿš¥¾Ÿ‡Sjï¦UËg5ü3¢IYžpÊš|LÜ8u6QÖs¯C YÅ IË;EÎÁpp‚Á'ÔÁɾ“æ_ô;ƒ‚â1óLõìßÈÀ©0›ý¿,ÅÓ¥„U"”GÖËHiz•Œ·Ù`©ŠÃȻʱáă‘ˆˆ›@Z ÎæÞU]8QK*Þ¬SHg÷FŠ~¿:ºiA¯kô\ a…2nz«!+i½”RÆ̳×ê=tµb’½ø$F Ë–ùÔ •´þi†Ö_Õïj¿vŠÓ´=ãÕùØ È ì½ú˜ñ˜ ®ýœÊ8°´¦Æ)”KÜyÈ<{M™BÊûNÿ¢ßµßB¦yã‹ÿÆS˜ ß´¿àïkòd)a•ptËLÈY*„ýu.3ßNeFx?—q=Ùòù"¡ä,•a8ëHüžÊl„bÁ4mÏxuM>vk¥ð~Zk2jÉÄ<椪£ÍIÊè5­Çf1ó`´ÅXÓZïeZöË´fôšÖ¦†á¦ë´¶b|yâÜnޱפ&ÔœÒÒ®÷=›ÁäCÄšÐgܧ”²Äûšš„²™Ê¬læÒk"§4ó²<á”5ù˜¸åÿnzºÛw«Çâ”Þ>£¬\RéÝ• ¹õ_Ž$÷‘©@éêÀh¶99û5T¾F¨3#Ã`†Ñ¼Ë¢¯ÈsfvŸ |ußõ÷ñ8þç»ûüŠÛ8û;úx£!lM¾Ò!b¸Oå§û7@,Ý4‡þ¼ÿî>í"½Cò/¸ ‘PÑKD#YPfS.“ÛŽ:Û‚~x*'ì}1Á_ˆÐ…U»ê2\C‹4 q6ºØ$•¤­Ê’ÒvîVo8Ô‹äøwÕrÉ"Êø;pØ¢q«rqÊËWP H†R¯ñ¹»ßðûK Lc endstream endobj 259 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061128150846) /ModDate (D:20061128150846) /Title (/tmp/xfig-fig028607) /Creator (fig2dev Version 2.1.8 Patchlevel 0) /Author (bdm@tyl \(Brendan McKay\)) >> endobj 260 0 obj << /Type /ExtGState /OPM 1 >> endobj 261 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 262 0 obj 1117 endobj 253 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./fig4.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 263 0 R /BBox [0 0 153 53] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 264 0 R >>/Font << /R8 265 0 R>> >> /Length 266 0 R /Filter /FlateDecode >> stream xœÝX»Žc7 íõ*g ßõV .;î‚TNv6Á¸ØM‘ßÏ!%JºS¤J3†aøò}h‰”x¿Ywuü¿·»ùô¹Ø×¿M8²ýÇýÓˆÜ~þÉ„Têȶz„V£½ï¢ YHûfb;¨5?åoæ«y‹WCT²m֮ŒB‰“|3[_=¾dÑ9‰Qi:²c/ÿ¯;Ƙ©ZåK®þ~ÿÑþCøbNÚ†BGkh&'ûÃ¥f›KÚ‚hÔ–º|Ð7SÅg¿4J9y˜ôˆ åTpB´ÓCm烾™‰bp&Êáá}7$þ¸¹aÅËy¯Þ'§Ö#f×lÂn¹Øêº†în¥o&4£¥èìAi‹Á!VÈV=e©!¡ôÍ( å(Jõð>^·ÇÍíÅ„ˆË½´Ü›r*Ê:5 -^¬Q÷¢Á;åJiòH‚–FŒgƒÖ°r`aG©"•2c( ‹bj ”Óû«âŸUÊh†åŽ“×äcâÆ©ëQ5Qν}0BsƒÇCXÞÉcÑö`88ÁÈ›öÁn/¤úgýÎ ×3æ‘êî_IÖï–B<íOøy).%¬úX|IM®2ƒQp;‘«ìУ&)AbJ""·J@Z ÎíæÞE]8ASHV­ƒ »{%Y¿Ç_ Ý´?¡—5z¬„°B Ù…Ô^J¡¢ ãìµr]­˜¸]ÞÄ)o¶)o RHíŸj¨ýUü®ö«a—XÎLµÝðÊŠ|ì¸FZÜ`r‚ ,Õž[”ó)Ju³Mû%ä1 'Bö»%0Â.1ÓvÃÛkâC'€ˆ™K°y÷AÂ,ÁRÄ¡0¥qÎÅÈ=SÉOc(Ѳ)xÇó×´ïäðÎúÁ­ÔÌ0Ωo~d½¸ Ñ´ØÐÊÿÿ‘ᯠ“Üû)¬ñ…ÛƒÎ?UF,š’Òk ›cÆRJkŒ5…¡…ž¦0lŽÓ¦ôšÂ”3qÓy [1¾cƒè‡Wtñ.¶Ø ŽßäÁ[à·p×»y"÷|ýË”€ÆKø^7Ož9Ī®Ú ”³°³¹Cs/¿¨’_ŸÊóÅGÌÂ.>Õçß®?› öž¼À&,\Ýì ±ƒDrrð”YG•Y8^ØQظαˆ ¾8Îpsº„zÿ;,#‘Q9<'ê:¯3Uí¹±èÇ«ùŸ r?| endstream endobj 263 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061128150847) /ModDate (D:20061128150847) /Title (/tmp/xfig-fig028607) /Creator (fig2dev Version 2.1.8 Patchlevel 0) /Author (bdm@tyl \(Brendan McKay\)) >> endobj 264 0 obj << /Type /ExtGState /OPM 1 >> endobj 265 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 266 0 obj 1119 endobj 254 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./fig5.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 267 0 R /BBox [0 0 155 52] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 268 0 R >>/Font << /R8 269 0 R>> >> /Length 270 0 R /Filter /FlateDecode >> stream xœÝX½²c' îy ÊMá³8ÚÌdRçÚoàd7Ù¹.vSäõóI ÇEª4×ãÂÖÿ'ƒâ»ù Ÿñ}¸ÏoÅýÛ¥ý?Žü_NåþíW—¸n5§P·Ôª¸HÙ§Ò©w··Z‹SþîþtW¸øêˆ*ƒÕüá(Õ<ÉwG9ñ0+ƒÈLJ1«tß8ˆÆ—ÿ×`äX=>–¤\ûþñ¢ý‡ðêZL’´O•¶Öh&§Ä-ìÍ7Ú7JÅ'NªÑÂÞ僾» ,‘ãäÔZN&=bÀÂ8 œ”ýôÐÚ9Æ ïn¢0 C9<<çqG⯛ÛÕ•rÞ«ÉiuËšgìæÄñD!{ÛÝFß]nF‡F¦³£-,ŒCà$öæ"«Æ¬ Aß¡0ÎÄ=<<ç!ëöº¹]]ꀴÜK+ÈÍ8 e½7ô£Õu_÷&r£ïècIС±ç³‡A[ X‡ÀÁŽ2£jX £a1PL Ãmžòu{ÝÜ®.&Tp±¼”b…ä#ª³¥ d¬R=SÆï»‹ð¤ú‡P¿f©¿‹ÅPªvÓªÅÃg3ü3¢IY.8eM>&nœº E“õÜëÐBÇð#Þ)bÑÖ`88ÁàEû`±äð/úƒâ1óëêßÈ»3Saà3û3~YŠ—K «D™Á’ËȮڷn6â0¢îZ`Q<‰ˆÒ*éP °šwjxWuýGp‚îi÷f(­îýÿPPt‡ý ½®Ñk%„Ê!. YI륔 2Ï^«÷У“ÔcàEŒ[æ¥AvrôO3´þÚï·³ýZØ)Vˆf»âÕùØ `Ðׄœ Kµ& ƒÁ’>%@\[^¨Nˆa8êÀq$0ÂN±B4Û¯®ÀÇN@j H Úe²“ðŸKÂráPÃÙyœsy—žiä]¦1”hYRùkÚw²Úo0´•FÙÝ> endobj 268 0 obj << /Type /ExtGState /OPM 1 >> endobj 269 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 270 0 obj 1115 endobj 258 0 obj << /D [256 0 R /XYZ 72 720 null] >> endobj 255 0 obj << /Font << /F17 138 0 R /F18 140 0 R /F14 141 0 R /F41 161 0 R /F38 159 0 R >> /XObject << /Im4 252 0 R /Im5 253 0 R /Im6 254 0 R >> /ProcSet [ /PDF /Text ] >> endobj 276 0 obj << /Length 3598 /Filter /FlateDecode >> stream xÚå[ë·ÿ~…O:ôÄðÍ¥ÝHÑ$pM}þ8÷aOZI›J»—]Éçë_ß’û<êq¶Ú"-ðR$w8äÌüæÁ5¬&tòý Ï¿Ü^}ý3ƈUŠOn—Ã'†&„J5¹]L>LËê>ßÕ×w·?À̤?SH¢:nÞŸ®g’«é/TQzÓü©ðg¯ÙôÆÞXe7Ö`U& ±Ì6Äê]_“K"šIb„áÐ3VÕCÿ3c1JÒEåˆ{™PB£ JK¤‘#ÂülÂq¢¿æfºö§‘×á¹È ìÞåótã»v%>¡kùŽ*«÷›]^¬¢øb¡ºÕì¹S¢¢,¢‡$Á|:,Ê OÿÛOéöa“ùUEƒ@fƒµ¡ô¡Ax’€ $YyÉõŒ1°Ö÷uVÍÙ/`6EÚ,Œš>T¸ 6g‹=l€ÄØ¡ UÌGxrƒW€ƒy—ÀšÒ>·é"ó­eYùÆþÁ?ñ¸¤0°#nižàҀθºï¯\w6Ï‘Sd{ﯡï)ÐZ‡Uö°£>yœ6ÞÂ0ÈjÓ¼Ÿîüó㵂Õ 7Š;ë›I^î‘nAÎÛ,4á\P¦¾Û- Ï»ÞëFÉõÌH9½]ÃFüYÐéc¾ÙøÉOH®,B+_Zn¸Ì½‚eUÃBÙ®¹õ­´jVOëÚí ©± £1Ì¡ÄðÙðôgË÷t:§&R´E Éú¤Šïwåöq^(iA3-_ƒòÄpÙ• ¸o ÿÔ Ø—âeì;8>IØÃZ–œ¾nˆFNËeÔ£”Z·U>ìÀˆ¢®Dr0ë¤#­h9¡¢7£“¡Èßes¤åÕc`µ `ø÷ï¯&†¨0ì£/O(ªé›ÂCKº 7O묾ñíÔõ(˜°([t£oßÿø£oy­Ç1‡>„ÕYQç÷ †-²eÚNI÷Ñ”²°½„(Pçö€F ¢:‡‹rÛ9lOê¼õIÐØ¼ß™5¢!Ÿ.ò:}ð6š.|/îŸÑhÁfb'Ï“Óé¤\×r_¸Í¥›|‡ÓŸ|÷< ¯´ø€?*PæÒ£ÓŒAÌǾ|±Ÿ;ð¾ÌÅŸföiè“e‹lBõûÚa—óWñdZeÚØ¥îÀVÙ𣘀`ÂFºï׊«¾;·j¤úÎ÷ÁÇ„óul™„n[ó +Å“ "²U‘OÑð‘ QFL×)ú/1?m›@ð¥´J·™G`œŸÃy¾9/·Û²x ?, {‚×wlAà9¯òN–ð–sn²ÞùV¾ p_52nt½Þž-´ £½‘hàö°kUh áô}±ä»}(Só]jþ1_ì]¸]cÕÆùžåAnV}ž/ŸÂê@´zÌë qîèiàqBšV¯Ë}#þö\|Teé®ÑØ´nb¥t1+‹ÍÓu¦M(3:ú²]UéC£rœjÞi!1ÕSÄš6êŒÆ\à!xr½ŽqH¡d”í¢pÄ!èlÚF#`¥”=ዘ겲¨Ë$² &_]Ϭ±ú«&RP ìN#|Ïj¿Åújß…z5˜Sƒöû®"´ºPÃM,»˜³Ÿ-)Â:³.Àå_C@ùÍØ„f`ËcrkŽ“Ç£TÁ„º¨fÝèXQî¼Îq×ë´Xe‹6dß§÷. Ñûg¹OGÍ…ºaóÐÜfiÈ[GU{NG29Tðc ÕFSDpƒ=½ëÂs¯9ÈÚ ½v›¹Ì÷U•µãŽÎYð"s§¤§·€&ë`ÏGÊ] õÃ4¨/ÙO¡ÀþÃHŒiùª KE?*© ÀRÃP ;*yø¨ÎB‚Cy1äj晉ʃ&zl­–¡‡]Ô’ÿEÀÉ}SU©sLx`€îá¹ÉŠÕnKÀ•È裠MÕ…ž+p.6ºàùvyãà7}ðyÀnè|ÌwkßÊÒVÀ=æ¼@£Õž:¸8e‰û¸tSºÕ‡1pñí‡Ô-­eUn±Õ†®¾êÁO·p<¨v• éÐ1Tqª8mЇz»È š2†pAP§øôoÑO±U´­OÝÄ(ž2à ër­à)zh&¦÷û]Œ.‡X²“þ)@]ýÁ›-ð» GÖæåa·ô 9/C ëá­4h7ÌíkÌöƒ¦^ôéÿ¦DØ~ ãæv™ïö!./ä¬òš„™>þhÂ4ae)tÎ÷0£U…Í“ïõ¯ÈPFLŒƒ‰Ýž`‡ðË]„»ôT½BÀ2hÄÐWP?-ìôÇl5kv-z@ÃM­²†23&AwBŒ ÉbÄ€}@šÞ,ˆg™6‡¨Â›Ô…ØÝ ü%d_áCû‡i¯}g·¤ä½%'”ªÁ’›xø“Ý_²‹84y2„JŒòä€0:d¥ºñƒºuUÐ àÓìÀ'&'M!·1Ÿ+§áî,į¿;‡f}^†h¦{;î¤PÉsægÿœ¹èÑ p3}Þ0 Q2Ä(Y&dëN|W˜WÄ—½Ì€¾¼(æ¦ù*/ÒCG7Üø,sÈg%‚ðäs]ìx“ÏsÄcŸÞÛÔL ×U”Á¡dŸÚÉlÜx÷íª®Œ‚=øHÛ#UÄw]˜Q¯Š‰‹ˆñ'ý*Yd5¸Ò*ô†’sÌ$xõ¨ž+ÍÀÜ{JŒ…F }cüD—(_M[™—Xúße~ýMÁ`‘ÕQPšq h2¿#ÌÆx}Žõ"êB¢DáÍäK<ÓqµTp!‰æç¸ÊK6W=ëPÅ2¡´þ,¨§ð;•AôoÖ°DOíLW¹8pF¸h1pÃõ^… (áXÅ«hê €±%%8Nsïí×¥/hw5àP"ª¶Ž—] Z°Ãç–‘l‰áÅCwýºŒ–ûÉRTùIºœëuœF/ÄegÐ8©eE´æhGû™&»qn툙!3«C‡bFµO.9@¨|.ö{_÷MŒœ~‡ÐèêðƒF×6ÄHÛs02î•ÝÝi£~1Bà>ûUà#tøÑÐY® íjm=SwàŒ_šó¸nf¿Ó¼ùÜ8hžól³©ýÕiº õ £:Nël×]ÿ¸g;´,«mÔ8Mx÷Æòd%áÝJ"º@æC쨧 ±ZVîNÒxg¶g…ÿ1fÿÀ¢ì2¼B°‹E% ¶É‡ô*¯Ü¢žQCz᛿ꢌ»( >7: !`XŠÙé#^ @ðÐ8g‹®¾œœüõÀ>êiŒ#ê¢1¬#ùdzòOùï"ðw½¿oo»Ã¢@›qLÑx’eÁ·›zq‡n“ŸƒÐ­U±À;°Î¦X%h2uéj[i´Ž ¬¾û«ýˆžAÀ¥•:~W‚ÀÞÿ6‘Š5_юࢠ©Žj-d›fDLDiá÷Å–ŸQX8]W€XV ‚Ù°pܹB¢©;?»âÈÐäh¨ ÐРa.@#ù|­úÙ“‰æ¯j„ü%‰ó)6Ä]T½™¯Î¾´nÆ.¤ß¿?õÖŸ/NvI1Љä|Ø œ»ô{ž@óy%WWsQÛ@ÍW‡ÔœÚÝ‘üéyòû·•‹ê¹¸„­Üa-N³.Å>vjõÒxE¼HÑåAEøè/÷‹ôÈÿ»z~5Wÿ›jŽ÷ØCÜ®3¼ÉPMÝ‘ÏZÔ¡¯û1d†Ÿª Z"?QÜÀÿ­Bt"GWÙç\mCê3øwðå"³h+ÿ{À]ùC~Þ é¿Ýš½ endstream endobj 275 0 obj << /Type /Page /Contents 276 0 R /Resources 274 0 R /MediaBox [0 0 612 792] /Parent 247 0 R /Annots [ 272 0 R 273 0 R ] >> endobj 271 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./fig6.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 278 0 R /BBox [0 0 154 53] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 279 0 R >>/Font << /R8 280 0 R>> >> /Length 281 0 R /Filter /FlateDecode >> stream xœÝX;#7 îõ+Tîž%m€ @ºœÝ©&¹½ëâ.Eþ~>R¢¤q‘*Í.føþh‰”8߬ÛÈ:þõçq7Ÿ>gûö· [²ÿ²‘ÛÏ?™ÊVYre µØ»ñmÈz7{ݨV?äïæ«¹ÂÅ›!* ì(æwC¡ÄA¾ŠŽ­‡)_ˆHN¥ä£H÷-9ÖøòÿºcŒÉ õ9WŸßÿ@´ÿ^Mõ“¶¡ÐVkšÁÉ~s{µ•öB¶!ѨnoòN¦‹O~pJÉ'ƒî1`¡œ Nˆvx¨õ£Ó‡(TCQvyHüys»šœÏ{õ>8µl1¹jvsHñX!ZÝÝJ&V£©éìAi å8!Yõ@>‰Æ¨ NFQ(gàîóàu{ÞÜ®&4@Rî¹fä¦œŠ²Þ+úQñbºÏ5µÆr¥ô1$hjìñì¡ÓÊ!p°£Ôy/CiXtCCq«‡‡v\™KP/“„ÿ˜– ‡ÎŸú9wî™J<¡Dó¢Ï_þ‘E¯x!­ÔóvhæœúæWÖk› ÇÅbAÛ*àß&šÛÃFî<…U±hLHJÏ)L9:c©‡AÓãFþ<…áÐ;MaJÏ)lh(JžÂfŒ/OœÛÕ¤˜– Œ©1}…,÷8­øܼÎ0¾)vȰäÝ2¦!¡ú¬¤V:KÉG‹9iõˆCÊØÔrÁÉkò1qóÿ]åÔÖïQ÷ÉIE&š„•ùÚ|’u¹ÓxXÏ”¦B¿& Jç™J甪;¨é¡ŽŒƒj(FuðE[‘çÌìÚ?-~3ß µ÷þ8îö‡›ùô£í–¢½¡‹71ª-²9.ÑÉÑžìín^ȽÞþ2\Œüa)î5ìíwóë‹{½Bç þÅ¿þvûAÑ“—+ä/Ä–33.õÍ YYrAopAÝR3‹ eC° n”…?-²¬²¨ 70‡«}´ˆ!I,‰acÌ À{ag‰Àß)å2¶¤E\íMp‰8OT²³äÇ›ù¿ì–>ê endstream endobj 278 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061128150848) /ModDate (D:20061128150848) /Title (/tmp/xfig-fig028607) /Creator (fig2dev Version 2.1.8 Patchlevel 0) /Author (bdm@tyl \(Brendan McKay\)) >> endobj 279 0 obj << /Type /ExtGState /OPM 1 >> endobj 280 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 281 0 obj 1118 endobj 272 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [111.975 469.042 119.82 482.99] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 273 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [321.551 356.232 329.397 368.851] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 277 0 obj << /D [275 0 R /XYZ 72 720 null] >> endobj 38 0 obj << /D [275 0 R /XYZ 72 570.479 null] >> endobj 274 0 obj << /Font << /F17 138 0 R /F18 140 0 R /F41 161 0 R /F34 144 0 R /F38 159 0 R /F14 141 0 R /F39 168 0 R /F42 169 0 R >> /XObject << /Im7 271 0 R >> /ProcSet [ /PDF /Text ] >> endobj 286 0 obj << /Length 3100 /Filter /FlateDecode >> stream xÚ½ZKÛF¾Ï¯rY °:ý`ó`YÀ¼ÏbØ9p¤žŠTHÊcÿûTuUó5ÔŒÆö"²¬®®®ÇWÕ’«‡•\ýr#/<ÿu{óã;•¬”™µzu{¿Ri"ŒNV‰ÌDš¦«ÛýêÓºÌï~Úü~ûïß™t<ÙDÂÊHùYÑf«tdÖ±êµæ¶„§”rr;g”ÚµåvÆã†ŸŠ–šòµ5VX­àSE1­xê*æKE¾´ˆ­ |©%Öµ™ 3Ì• %“ë‰(f_/r ­ì|ê"Ñ(©3eO”ž’‰O¾Øê,iÃK"eèÓÛƒÛlŽ×u³w ¾&ëúžºº0öe½®éŠk©ç±èEEÓûi;W–<$< ‘šHB[‘dý?KÃ{‹ô*Y"ΊE ŸmLe&Ë¥ý$Bj½Í*xí¼¹+º&o¾mRµø)lY+Ø{TSacþà›T¯mâ±(Kú¼q÷$@=Ûá)!tE]ñJ—$”®]¹´i•õra+±í5$çm|V&â…“õîÜ4®ÂExÉž“Âagq O°6' ØÊ~mEk‘Ľ [×4+×îþäŸ5þì–¸¥0F‡håy`c0®‡%:V˜$ 3Þ,ÑH„c–½{Y¢–nÀÒ¯&Þ`‘L,"ó27ýŽàÈÝâY‚X•J¯'T;/wP?x€-À…˜WlÒS¬ÏU·Èa"¢,¹žÃ|×_Ü"¥LØWÈl×ëÕ~™œV_Oî¸D8Ší+¤¿lŽƒ½ëÐñÂètêBnèut¢ÖôÔ뜧¦Æð‰ûsãhJWÓXãNe¾Q0Fmoå8aïîósÙ1…`áÛÆ}–*ªÜÑÁGúâni‘7ð-¯ö48Ûåeéö´ •€YfÓøx_7øe´vù‰¨Uí½£&|³˜»Ùqb³´¦8‚ã#‰Í¼m™Ç"ïÜž:1zL¨=YÍóŽ‹„qô†sÒ=½÷Mzï;=m9Ýëe³5ÂØþÔxÃaîP‘`“" rI²ç0pçy¯q&±Â>£]P˜hoa3ùÑu®aš'& "ø座޼áé9O»¯!N)Z뱋 ¨?äѺ—<ðóžÊ=XäE{‹^¤¡žµ·XØ$¾žï2Ï‚WHåJúi³Í’lý3#8À™Ê¤Þެ´ hT4i¤" \( hѼ(• ˜í¥‚¾a !Mò‚`Ð;÷çxÌ‘óoÀg”­i/Ìt^ÃÞ2üÈ0«ó®Òï«A Þ2nIµqÂfj9R°×42%†Ïw¸¯ ^Û®Âó˜ÿQT³É8Ü&öQ4É–ïÈ26Ðñ¬–Ú9}(‘ù§Î…#¸#¶ÎmG­ªfè6ˆ íšÄ%–0> vŸ]M ¹èƒz4ƒƦCÔ’fé -€ìäuÈ#™ŽfZL2J Iõ|DÆ]ÁÙ r†ØãÏ&„”^}ºÏ.|¼;ù¬¥£¾^èhIÄñGFÂ„Ö ChœO;(ÀøµîI¹7™DMO©ó=óý‘4}òB {ÈgBnQT»Æåíkìäšã¹Ë½¾-\f•˜k.½ÝA`ž˜ß@di#QÈí #ßï×ò¨ß9Œæ6Í`èaØ‚¢WÁýÔ.ôåm·˜ôÅ©H¥}6À«R½—G] ¼ Ü„C'8†îO¥S¿YÌ~/Û]“w;TÐwœò-Ʈ߳iÒ sÓ$òê¡§Éüz éâõ*к¿Ëf/cq#E”.ª‰=ðÂGOOhÛ5>w‡]•-J&6AaŒW¿Šñ%‘È!¬×Ý…¡†Ò©l!ªÑª9/Ò>û7å¶÷ŸrF ©ÍÔ¶+¢¬1v¶¬ #ÔDúwìH-ós·1 4}I¶Á›QÆT5èŠZŸ½F(Ð’–—:ðú¼G;:Äú…&h{|îY<7ä¸ê–Ò°B"d÷!Ë¿tRNt’½ý€|"Ä×õ™•;‡øfwõ°$†L‚¾F׉p¥î­”ù:xñ¥¨Ï [ÕGÇôW%¯w#á3µj°¢ˆ/¿þr³úäÉò0ÕWŸ¸dóÄ®”M…Îfé×ß _ÌMµˆÔ²[Õ±E'ëáÈpÈ›öv·ûל†J†gàt¶Eµw¤ÞúD&~ÙXÈwÊ3“9HlÚ{mß®VZtàE>&䳸˜RN2#8þx!Çø(±äö\ê]¾É›€<ÒÑ̺¡Ôâ{2æ k!¥B†xÈW±€ôök~<•ÄjM|„NŸFh¨‘0½ú -ú4}ɼAYÊ'ñ ‘Ž[ä%uu‡œ'¹?ÏKz¨µ+>¸tƒé°Ö{)2ü–ßíBN‹;U){c˜2:Nl‚«*(›„V¯J Ûù¬:¶m(Ôæ\‘üð3~ýßÛß¼U½½½ùóF±Éi%E ^ü)(¾YíŽ7Ÿ~—«= Â:€m=ú©GHp¬ÂÄ¢\}¼ù×ÿgŽ= €ÒJŽrï?¼{ÿáýíoœü*pбÒKéo‘½ÉYÑ2RNcE! ý]ø(TA .ÂÈXSa<(>œJ]Rtki$¬FÂíž’ž•¸aõ²N¼Y¨œ0Ü`^šÂy ”}Ù{V …L¾˜¨Y!“tRvò$C¥ßsz Êc±€.{bxp’…œ *%BØ_tü$Vkjµç;.y„‹]!UC}”éÉPY8šúÔ`1‡äGB§S-ˆe|0ó¿R$:¸œuêΆH>Ë„!ó.˜ž¯ÌöŸµÃ_¦k46Øi±)2 Ö¶ßÍ NH¡"}u®yt; ‰Êo4ܾا¦‚Õ#îŸ{$˜c§à5x9Ÿü–ßBö²`H»Á5 ðÉ9¢=F>swôBñ*¥xtA9"+ŸÎ{hòÓœ^*1ƒ# ¥’3³'ðM6J¿ç2BArÑ+ºyd€KžþÝò’$RfÏÞPÀk4@ÄKÅ0£^°n³ÀËpä£È\$Qô3@»««¶hC½ÏQ§[}š…òhÆAGg’Ã>Ä––F–mO¥JÄÑK—"zb¡—ö`k¸ðx!A1#­³$¸­ñV¼ïÇàŒ>R>¿mE<œåÿc7Û¯uçWÍ-ÀîÏÆŒA`€4Ø‹…{·œ`_?8l>é’šy–8–)@Óì¥ð’ˆt¨^Ç'c"/Ak=ð§â«ù† ;“mŒ“4HÒ;š¨Ë¡¬ 3ë#m°pô(ôd(‚Ñ-õ‘—¤7¯÷ýý5öy›ÙYLÇž>˜fqøÒöA^÷ó\[ýƒéó,†c_¤šP^<hyé¯;ÀóWVmñš2pŒ¶ÔöÜħðbÅÑGcœ}ÑÇø$¨1C®÷¡”–5>i¿ _È@¾ÇšÆ”x€çbi›·8R/ÔLÚüÞ½¡þÆ=äM¨œT}üŒ'ðè`þ?‚;Ç£«º iÇѯØ|BÛS ãKw!>)P\ ƒ'pR4ù]騉êè•TµUæ§3œ.Ö®¿<ÃnŽ×*Ô(àe J¡Ù¸îܺ­‰üv¸¦OšÕúý=¯‡j³½|Yç5 „ÿ&S=ÁØp +—F¡±¯+ºùü\ŸpRƒøÆ¹áö“dð6ôÎn5—îF"+Ôp»LQœH]¸AVãÛ_<×ÿ`Q*®0§TûKñ™™[ !P‹HØ,!€zã¼”±+H¿({d‡Ý CÞø>Kf.µg¤öÈ¢DÃÿýÇ&ÌŸG·¼™!X’L iÕP•¨OþnAì‹/$@LKJ±<Ó­2Tˆ"ÿo…©MþêS¿·—õžïh%â«ûsYùüQ'—¢*@cý=ÿ±ä„=jò§‡‹îÝ”Î{X²-ªsÜ´ûº]¬\ð÷>Ùnø#ÎgX÷çÝ-Ko½­cEQqòôÿ`W”¥âu6+K­)L:5 Š "ï2©Y U<™)ø_izÂæ endstream endobj 285 0 obj << /Type /Page /Contents 286 0 R /Resources 284 0 R /MediaBox [0 0 612 792] /Parent 247 0 R /Annots [ 282 0 R 283 0 R ] >> endobj 282 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [349.938 394.354 357.784 406.974] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 283 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [111.975 84.184 119.82 98.132] /Subtype /Link /A << /S /GoTo /D (section.9) >> >> endobj 287 0 obj << /D [285 0 R /XYZ 72 720 null] >> endobj 284 0 obj << /Font << /F17 138 0 R /F38 159 0 R /F14 141 0 R /F18 140 0 R /F41 161 0 R /F42 169 0 R /F59 288 0 R /F34 144 0 R >> /ProcSet [ /PDF /Text ] >> endobj 299 0 obj << /Length 3112 /Filter /FlateDecode >> stream xÚÝZKs㸾ϯPåDU‚Hb69$UÙ­Ée«v}›Ù-Â63©"){&¿>Ýh€/C¶äÌVÆ«û믊7÷›xóÓ»Ø=ÿzóî?ò|Ã9ÓJ%››»M–l²8g±T››ró)ú«ø~øö·›¿CãlÞ8LòDÙ¦§ÞtM»UqTšc‡Oû²w=—ÃÄLÀñ4HH¾dXpîCr¹oð>$"c\Iߢ.nCB¸„ɤ—‹9MPLÊäU³1¦ JÆ¡ßÅ‚šÓa; Òvð¨ûP)˜¯/RøCðÜ4KÒ+„ìG-(Mp¥œMüúBá)©T^>¥àÑeLf3e´Ê¾Ù%9O7;žÛ1ì盇ªßîD’FôÌ¢}Qצ¤º¶Ù*ݵ}6Û$L÷^ÁBvð(]³öŽª‡W1tƼ§bq7˜ÎÕÒç,:ÝP UÛPýCá&s Ra”-LC-;ó9æ²1%³«‰×ËpãÀâ`` ·š#ˆ(zxáVZIµEçš®Ù][×ð¹ÝBù©gÛ*ºÙæÆ-ך¬y˜‹I±q¹k›úöd¡ÃÛñ P@»Ù‹ K&m{£.¡ þ¢.¥Leéåóx;&-ļ“–³9‹I‚ 5ÚȇíNg:ú‹S†âÖêt‹ŠþˆaÜQŠ…Œ†r²Ôꂞ%áòëN‚p±šá¨æ NëtÀ_š¬qæÙ‚;õÜ›ºö¶Ý¬Ìrê:c… £Ý!†—šf,ÉùÖzwõƒnmïÜÈr!-gI<TSœ†­àÑ·PM…öM Jò  ÐàP5ÓrÄkÐPÚãúªºì,Èäβm›Êõžã¾šQLKO·ýôb¾ë¶3eX3ìÌÌáCQ鸈ª'è–\±,Gè–L‚‘˜USš¯tÀU9Uó#9g¢9Óùˆ„qiôô`:³Æô¢»7NoPɨd1v@¸íBÐ4úútOPWõä`†ÃènhËã–œåÓT?Çq|Æoëq“xXe®:—K¤½Hg_uó ðÄç¦iUFr¤Bºý‚ŠýL‡àõع÷ÓÞ*TÝ¢&~£òØÍ{¼Ãd¨P[4®!S7˜¯»Ê6xÜ*›_óæ4Xç„ÞïÔ§Q Hy.– õ¶`¼#³cWͽ;{èýàÂ+€Xh•ÃtW&ÞŸ%ÚÈùœhãfƒm·‡W™¶d ——0ík;'Ÿ¯ð%ò ²l» ºÛ$e\êËeµÝm5ÁvT ~e>/LAQ^Á¿û¡¸}´ŠuFZ¦óß…  PÆD-,Öٕ⑎ʎ ªÄT¨2Å÷Uß›ÆtÅ€n±£‹lÐŽì VïÚî¨æ¾kOGÄ+•‘뜚'QüÒ Þ• ¹dNžÕÍÌÉ: Ôô7*í„ÂSW ƒu:ð‚JÜ÷åW³G[CF ‚!´7|Óa|‹…_~z·ùdÛ¥î3E¾nu•TÑÇdUnˆˆUi· §ÔÒó®ØWu5ƒ½?{‡­Šþ‹á×ÒmG @ ¹ølÝ~Ë-W¹? އ(žÈ¤©Ý ’ÕŽQC'Úvõ-ívˆóô§¢¦O‡¢œ?ƾuXhƒ”3’ÐÚÐÔ‹¦Eå1ðpéÀ·˜‚\÷I¤.]?ÌÓg#¦ô}T1ÓëèîŽÿä4#@^3±²˜qWÚz›_O'Ö›3Y}ÀF!2çö¬±§É¸ûÀL}çöòGL`x§ ›‡Ö›‚%M±öç8‘çð‚O î}ý‰Í™ugIö(™b‰óŸBó[¤@‚¸!@ÆÑ~£™‡¡B¨‰UA¼Ó€w 8ùl vv>kx&ÈÉ 0”ê\`.ÏÛåKê™]ÈPdzÿ!4¹ ¼41r)]˜Cœù™Ú2…HPÛ|ìÀdÕ‹êÀ{?`Ö‘Ê–ÒggoƉ¾E˜ýæp;ÖLŠlE%l\¬|¨ÄŠIàE';QøÔ·®ª >Ã~íëSéè‹ô¨MÛÆ Íã¸#C_÷KÐO­ü’›BGRÝ$mÍÁº (·w¡#ó”I½ª" ’rT€3( O¼%¯tM²†N”%œÏÉ„l8Å;ßó1`Š¥–éÃbÁ[Vù;& ¾žµz¿ô×¥ÏgÏ3t—p èà¡Íó>‘¿%Cy&hKõ• É)YîÓÕÞôï—YsËég¹är6—0ãŽåå—v6éûZ!Ç ó«nìþO¯Û.5à‹g &¸¸â²îñ;\ÖQV4Ì/®HÒ ËT}õÏ`JPèùÐßóŽS].t¹ìù6ࢌŸä„3Îtðvâ zÎ’7Pç’7PK~ªlò&³ xk앦/K×Іdð…üjs‡ù’Ckù>T‹Áõ.)²Èô´µ·~¥›Í]×Hà(È%eÛÁI+—IgvÜýÐ0X)ÚåS4L«=R…M Ÿ†è†Ò1ÓÀ]gzÅ7v*Ø•Öh‹v.P8Ý ø€€»vŸ¹!”Orð1“Ç"X~ À)ðˆ± »LG5ø¬XÆÓ¿ãækŸ¬‚E•¦ßw•CõÒ¥êDÆb-—Ûb}XÊ/ða@pžù0Ü÷,¶kþº7Çd¹Û( 1£¢,mò¹¨-UÂèÞé úï‰x!…ê©ã¡°Ú“z5ƒO´ÓP3…ŠðR›â޾[§•ò©^c³EÆHÍ.žÔ»S7KÐ$9¥ßðËкSŽ*€ìºRÕï²)Ûç¡hœØžŠ£Lå£a¥#¢¶<øÉŒ Ô¡¯M4·gƒ_ ßsg¡Ø\ r™¦¸­ÕÁ˜înàIêÏî¾àSƒþŠ^i¯¡à³~P¤¬ŸŒUd†=CóH0GÁ£'cq{oßûÞ8Eçx9–{?H]wöÅ,ò‹ {kåéX(ùñœ÷Πíìe¹ú¯º,×—_ÿ_Yžh=»,ÏÆËòÄsuq6·í”Ÿ‰,¸Œ._0pàÉ_Ož%ŽRš=£5?ÃߩᚨÒj%ÖLŽ«4?@3;€±QÒ8g"^Ý•Y‰‹?ÆŒÙ\Ëë §_(ÙQ[;Yýóc•ÖMÆëé¹À)^ñŒ:´yB±8Ö¯o^g¾º`~–Ç—’MçΉLŠ~&úÐàedþŸNM,•N!¿r±‰òY(øx_©E¼¯Òé†Vyð˜÷›_!õÔŒîSݧÝû(ÃÉ© pž‹ Ü'…óPIºÈ}ÎjÀ­Ø¤^}lV_ginx³»qéø÷ δЯŸ™$šþft_’ô4¡q¾ãÙÑl¡ûˆð_#0MPÕUoº3±~ÆÓç6XÄû™…Úy¼ï³1idJ‘"O1gîo YÐ ðvÖè‡,Àí,]ÈJ.’õáÇQž˜ÉãŠå9îÿtaÓ°_S³„ÉÀVÌ'¦ÀèGäá¬G*ñ†…ký"6(<¬Úðñ¶þ%æAíE©õóÑ(¸×˜‡ðA Ž·+à·èŸøŽ,§èéÝëfCÕUCÕ¯ 6VÎ+s„Ûþ[щ.ŽÇº2nH½°Òß½î`gTœ¯n` Æ’|‘¶Ä׉-fcXp´1[ÃV9Ãbߺ*›¤L F¢¹bÝÈRýÍê³,;¸'™© lM­É—mMüØšzÑÖ&|ÁÚÒk­ ¨WýŒ> endobj 289 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [239.268 506.235 247.114 520.183] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 290 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [402.286 457.077 410.131 474.222] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 291 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [427.97 373.234 435.815 385.853] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 292 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [340.936 339.206 348.781 352.843] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 293 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [126.453 249.664 134.298 262.283] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 294 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [162.359 121.743 170.204 134.363] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 295 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [387.36 121.743 395.206 134.363] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 296 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [360.296 88.734 368.141 101.353] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 300 0 obj << /D [298 0 R /XYZ 72 720 null] >> endobj 297 0 obj << /Font << /F18 140 0 R /F17 138 0 R /F38 159 0 R /F34 144 0 R /F14 141 0 R /F41 161 0 R /F39 168 0 R /F42 169 0 R /F40 233 0 R /F43 234 0 R /F46 241 0 R >> /ProcSet [ /PDF /Text ] >> endobj 306 0 obj << /Length 3824 /Filter /FlateDecode >> stream xÚí[YsÛÈ~÷¯PÞÀ*‹91Ø”6)ÛåTR©ÚUœªìæ&A kdвòëÓ==384äoyæâ=Ý__£ìæx“ݼ•¹ïïn_}÷Ž™ÆÒB)~s{¸aK17yfÒLª›ÛýÍÏÉpWm¶‚ë䗌ɪÙ÷XË“û»z·á&¹£jWªŽÆ g÷¥æÉ±;_/Ô¶+[*|Úl¡Ç (ûþzªönȹëªÝnþ~û‡ïÞ‰Ù·¼°Ü2“*-iƒu;ÐX–OÇrž eà¨tŠ/nÌâÀ)–ܘױiò”)éGÔí¾ú›ˆ›Tõò‰†ÝFeIÕl¶ðiúúŸUlV™Á5ä/Ÿµ½žæóF'•iÁÃO¾ßl‹¼H>Àµp­èθÖI{Ê¡>»æó¾?ÁÅ`#L |”ݰ›™ ?¾uó³¤]7±™Ý8ܵÁ¹ûŠæ)»j±Þ—‚ææZõaE»wÉfdÎEjDؼ»SÉ Ež1¢R­ `4/jbT)ã0õ8êul½­äY*3 óÉTJí¸ ²¬H ˜é¿´¬Î ×þkd5™ù‚Õtšq=]­l÷Q²Â­ý‚»(U3a^v¼ùéà23‡þBòìóeƒ…æacx’n¶2Ë“wÃ’3À—±oº~ Ê®lœM8 vckdà¨_A!s+3ÿuý+ç/€­ò ¾mœ–…1£(>w®x ddÊ¡—øôÚÝÕÍÞŠöùÆÏ&W×ýrßδºªŠª²{{‘Vî†+ðÞÕŽU[uåPíSZÁ5ñb®ný »s»¯=^>n•JQ|rç)Wtobœ û‘\?ÉÈ óŒ ϲIÜί½×ƤÌó¤†[fÈ5y2Ô‡jœ™ö:HÇ7yÃ`Ó¨¢P˜@& —„¯röE±Ù2ÆUòqSH ûP}ÝÖíF0n]—¶6ôiì4\:B´“¦Ï <ÙïºÚiOmuKßç• â%&²Ìq ìôì$¿ój²Aiá±§¢œ¥¼xÞ–×ôPÐç#Û×þ4C—–Öþ„Üú@å’†\:Æ]µ¿Z„6âëù«ånW]†ž—«8Å8IqWq)»Á2¬…Sná D{¨Nø[ÛŒ<ßSùyCFŽÊœ¨½ºz7 È` y£µè•ûz¸;_úE_Á‚@¾öHÕ?®5!:°ZS³Qv·«ˆðâ§BþaUˆ„ýùTaI'‡òT75ª¬!‚áw_æôîÚ T?vå宇–ŠÑ ã,Ÿ®u3 /Ú1]E9U:³$;ެÝjuÛ_í:µ;JóÛ9ñaòpEU&*ؤ%€­á^„B}2ôµƒÙjlÊîXѸ¾*;óXG¨²mˬ¥‡m§Ònêj»²¯z»(Úixl…Ó}jðViˆ[ݛì»òº³Âì<˜|ò+Âç wÜÓÉÂá˜þÜ9ÁÛ²Ðc7J¢Eb‹):Q{ø  4»±ð“ù/F)µ@qÇP'{0O;„¶ôêw&ãy–æ&ˆøû(îr0²‚éüÉœZ“LÀÅ T°œÊжi¨¡)Ý/š©‰}ĵÔýK¦2ËýPÞ×ÔmŒF¢ÔQŸ—#ðb‚5"ÀŸ1,àÐÇèydª˜Yh£9U¶œ Ôr3”9Dí05ÃdYlO*5Jø¿ÏÁe 0{Á r´•8 ßOj9õé @g§"åYØë/Y–Å6Sæ‹ÍÌç™mæ¸F”‰ûüë0Yp6áÄ™]!ÑpÒ“Ý©•Ë“™~ÄŒ8¯“FÌ(xæ‘ÍÔÖã>ÜŽ'Y§ÕlUô„°š'-‹‚¥… IÓ=»=…XØ•ëË@¢›Æk7NˆZØöG‰ŸpªZ̃o_[TñÞ*~Ô  õ2ö‚Åâ¯jìô+C`»¨æl7'‡Tl¡xRR0ŒãÌL*Y௿Eïø”?¿ K( ®Ÿ¶®äÔ¿¥WǪëS‚½b¬¦3ð9ÂMñ¶Û‹ÒQ/Å€G:2§%9ªcÔ{gUžc!"j;•— *˜òso¹°k8öz…4£ƒý}ŒÀEj 1â9r _ñÕ€ƒ#"']Ç6xTzlq)=r©Hd âo(¸å°òtʧD鯣m€¬PFU8”¢ãvㄯxz&En9 ²½D+Ád–©‡ÙÍÄT¿ÎÛÉ@‡á°=™½3öM‹0ÁÏ„àñY—ø-À˜ßÎF¢NF³ˆZÿˆ>¥ÓVh¯ß¢AQÁS3¡Dr@ûÂZŸÎˆxˆÒ¤ì‘´”ƒlô?9Q#n1€MË ê|90Üä”^QE ï$âa(šQ%­jM¼œ½|C_âÈRH±ØÌ# ˜læã €ivB6Ü‘÷IO6ºã"¸‘Š,ù±âì«Óœ‹QM“ÂPèÌ.4ë‡ö,eN†JîÝ4é2÷öy9,Óà/ÖW‚¿FëÍsÒñ°ëÒ‡q0r逸Ñ!@Ï‹%‡EøKïÍ-®šÖp p›ÒGÍS1ÒÖVÞ0Õ +œvĨ\‚ ©Ncúdþ£D?LØE"jb̋ļ'9õ Ï 0ÄÒàªò i1t|ªŠÈ•Ð{Ž tþÒÈ{0¹ $¨Ÿ«›úøA%Ü\…²Œ73Ò‘DNq3Ž‘¯i\ ghbdÙ20Ò0`¸pÍÁ»¾t6ˆv+y"ÅŸ~ÕVúèBœêÖλšŒÓl>ùì„ánNå×§'Ää›™¯1Æ'}´qí„xdú{\á%'–ÖVÃmßÒ³Q0‡€ A¬²†¶1S”ÛL‘ƒFÛ÷SµÛ:½ Ö…Òù7žÎ" ž¨eÉ&¼å( ó ±[2 'þ €+3fêϧåh„ÝtD´LGC–åÞJAì’á„cÄòTºX=Nt3VH‡5ý7Ø—ýP1©"‚yaóPP ©(AJ¿dX ´úHg9“±Ði¦(½)3ÃEgS^)+ö‰eç»â¬Òè¨Ùç7Þ‹Yòö«÷ À¦³¸ ¿éïÈ”ë}zÄjPè¨j©]O º›²1ù"ŒƒgGT2:!šš@ˆ×dqU²Õ ˆÍÌÑÏ~½ú‰Ì©l0ÉtVîM Ê{£¹ ¦Â’TÞTšNÒS¹e­r„§ßºÃ¸ÐÜc£Ã)šÙØ0´©?Ù+LÇÀŒõ¾|z/¦@þŠÞ¥µq¾=°æµ­Ìd˜šœA%žGb6³ª„·¥(¯Š?ª÷päŠ"”_ªlÐÉ'@¥rå½h*ä#Â,,R9jš¬hªØŒ,|ï;tР¨l^ZÚêžêÏц?J#Ã/mâ;G€ ¨F‹<0 vý$͆ž4Q„¦ZLi¸žFµ˜R©ÐSIÎ= ¸Ø5€a±Àäûº±2¯Ý£B,«Õ §òâÉ ËR>föHÔµµ~%ŽÑ;¡Z<Ö’óék®µhŽõÖ›µ¨ÙÃú íßN¡iáÃez=ö­ÓQ'QÅ%cL^„½A3«ÑX„³\/˜@“¨²N —³v+aÝ\ˆé;w±)O3=µÇ¾eΧ®õcì ¤°¯†§ë}Žß cÅt=dÖùr"®Á^„K¦‰;¹öR­õmIÈ‚¹s8«_„âc¤-²@iT4PÁ˜MX©äÚ6šˆ™³•Š::‹ì{žæj™Êçï,ùÜÇ|¿5Œ/w+F±ó±oÈe¼ýAÿ/oݹÿÜVSbÞ ˜¤y.cj\ç.Ój‹+ÔÏRaÔ³¾¸ îè«ó }µAÝ^јÄWwÑXv³ÈÅUNÓKø&³0E%§|M1ªf°ì>hgK=‰m–u´±ïß|0H›'b É”¿8öOG½Ç4Ð’SªŒ>BuZ…H3s¯…';2½ëw"..5íŸÅ¥$½žD±}Mƒ(L‹/«ðí>°á½OìMœp<úÓŽ‰H -组YÍw}XÓäÅÂušÁå+`Û^Ò§)hG‹™;·-„}¤ëÿ+Ö̽½}õ/W* endstream endobj 305 0 obj << /Type /Page /Contents 306 0 R /Resources 304 0 R /MediaBox [0 0 612 792] /Parent 247 0 R /Annots [ 301 0 R 302 0 R 303 0 R ] >> endobj 301 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [385.904 686.16 393.749 698.78] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 302 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [193.115 546.184 200.961 558.803] /Subtype /Link /A << /S /GoTo /D (section.2) >> >> endobj 303 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [93.939 198.841 101.784 211.46] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 307 0 obj << /D [305 0 R /XYZ 72 720 null] >> endobj 42 0 obj << /D [305 0 R /XYZ 72 603.618 null] >> endobj 304 0 obj << /Font << /F18 140 0 R /F38 159 0 R /F17 138 0 R /F41 161 0 R /F42 169 0 R /F34 144 0 R /F14 141 0 R /F39 168 0 R /F45 160 0 R >> /ProcSet [ /PDF /Text ] >> endobj 310 0 obj << /Length 3693 /Filter /FlateDecode >> stream xÚí\KsÛȾï¯à‘®²°ó R¹¤j7U9+É!Þ,BÖ©àÊίO÷t€’òÊöî&˜̳_?Fbµ]‰Õ_¿üüËíwßÿ(ó•”Ya­ZÝÞ¯¼Zy‘gÂØÕífõ¯õ;!MÓvon´Óë»j·{óÓíß¾ÿÑÈø#c³\Bá‹P ]¬|Vx!±ËreV72ó…¦V‚ZM7™×zµúŒ›Ëõ¡{¨šçº­Þ¦Fw:s…› ó‡/2£ô®uÞ¯JèÔŠLøÕMÔ𹆇µ¿s£üº¢˜ýhëývWu‡=¾*Ú Ú*(‚ö]Yï¡Éä+µþ«ª¦«>RnòÇjC/õžž‡7rÝlªç [§‹ÌÚ~˜ÌG³ëÐT¹õ]S•ö#>Ô-•îaÊ›Š^ï›Ã#5©;nñT6M3 £HÏcä™u†Æøû~WµÐÞ˜èèµ}¢=¹«qÕæ-{Ëì[ÀZT˵f]6uIcqg06÷ºß}⢱u½+ßï¸Áý¡¡Û¦|zh‡®Ãó©¼Ã¯>„-ÝðfùÓ½‚N3øDÛõí›\­›Ot.8#ÞÆcË[+à­z®»*ka³úz쫯ŽgPŸ—T·©Û²íª&cJó1¥ Þe&ôîùðôÆŠuÙ=´YŠ2e®{"ÿí×05£9åLN)ö@æ+ú/Iu?¥V}¤ìv[î鵤ÇÝHUøº©˜ö›°ŸX†”Ë’Ÿgp¿¸Ýø|~¨ãU0ƒí}7ø-§Q™6fzž=ÕwR³ök`˜º$âÁÒ@ö‰m‘JeÂêóû"2)ÉRÒÔ°Ó’Oe#>ÐËážž»j¿í¸L%Ïö$–ö{ÿKل÷IÉè2§d|BØýþÐÑ ½ ·sëÛ‡¾¶òdic*˜pùDûªa“ÏöµL Lh#–…£)ìº=Öm¬* q%÷\‰…Ñ™bUàq,oªíqWòï•FòËJšä,6" j€÷à û̺íšã]wlˆ@Ätï„arÈ‹ÕÇòñiWA™<ˇ,íÊÍÏ®z›dB 2XûS&T¶ˆezŠ UV–ØŠLTNæñµ¤Gă8ôœ± j$¬ ˆá ø—9­¡H·ÔéãcÿÕ¾ª·cÓñi{5$3ço8cî¯ÃžÃ6™!ìºå”ÀS¬^¹™¬<ÏÌ(~îSûgA—Ï·o‚0læ >I™*0Ô*jC:Ÿì˜¿zÒ§JÍ~-Üj» Jñ pÏqGRû*É]ÈóÌy–Š\&òAØ£BVÀ…û õK\x%™œ§PYnò ÛìÉ~ÏiÚú"ÞœJb@¥3/ÜËTW 8Õ*°èî%TdBËWX2€’а„– å± ›¾;­M„%áDNyW ÄÕ  S K¸˜M.LQŸÙ$ "ec˜]ß'Õ’¬|¡–n ¾?';U™(K,€[ Mí⦰®Kí×ÒôQ»_rþI𙣣R¶ù ”ͺ–ô¸‘è—Ô±+@É»©2c­ *;¨³íŒUs#ú¼+÷T~¸ï*þù ÒƺO½¹À ub“ Þ­ÈJ``ƒ%]\´ût3(s,%ínÅ š8 oÁ‚´ÊjV-ô%ͪ³¢°4«Q\8è5B·ZÐykV,kVll=Ñ[sÐvŠkî©à9¨l–ì]RÂ*„´b@ŸÏi6u#ù"¨Ik4ƒX "Òi.­Ól–œHˆE=97įѓç¤Î¨{õ°$ùw,Ú­Ë͕놓FÎl¹%ˆ¿L:^ÀW®Ý$×nÎö¹]P^#6B«€ª…çÚ Ç°®pD|¡Í==K4Hñ¢­vZ7µ™°lÔ®ÞßQÀÝ,™KÊY~ À:5´h£€Ó-¹ÿþ¹ †HÛO~_ 3MQØ)`´ 켆 ^Àæ*~x]ܨ.âÆ"+F¿«ÉÖ ÞÄ45ÈÂܾŠ'Œf»ÂP•TeM~r¨‰S¢HƘK2î*§Gê—T}SÀ\FŸ'}¢ˆ£ÝŠ4I8B²Ð°¦ë7t°ÐòÈBà ò,Ș}y˜8äéV7JÉ,·yÂUhý: @$¬ç6Tš4±"Í£!|ÅöÛ:µÏ`DèMY9…¥–}‡°ŸtŠPÀŽ®P‡R/‰äQ–º‹v\>Úq‰^gÊױј^WÙhò¢ùá®1Ñ„°‹&ZØK îCQZgõRHŸ»ü’9?ó|‘…áUïM³^ôÀ —7TõÛ³P<4ø#ö„âÏzö£G[Œä2]´v`ùaçUÒC%³ˆ/Ëz×Odÿ–W.Ñ¥¦+¹`^0ä<4Uï?ëåVË€ù¨ÿïc¹iŽ‹hßù OOýhÞ]FûÚ¨ 0DGV_K½Fh_KzÄ~4x=ñ£yG~4Ïvàò ªà9Õƒi´¯èuþÅ4¡»(S_ð&Áþ«úÄÀÐ(&d½hUh“©ÑøúX¯z`ú¼S_P‚ÎÎM^d Ý Ð¡è5bÎö1{šñL¬ae¬Ëçaôn“‰ÒQý¢}’ç™”öR8Gjw´PH—<Ë’a”.D6stïª`± ,yj§Û "; ×ýîÒ«zÍõç{ÍÁ¤-b¶~`ó­@]—¬{­õ£O¬Õ[?äãñ£'©ªrWþ¡­Ÿ/B&ùY2a‹jê›k™Ù—7xæÒf rï}U!wä\d(Àq‘™ )kÀ’EÏÈ¢‚·àŸ>Z-É Y-È©¤ß”«ïU•žþ5.´ÜÍŒ´è¨ØÙm#-”-i0Ç y×iRŸ#.`ŸÏÍ]rrZ²UæGÿÎu«ÓWÄÌtÒ.ôcèîÔ(T/7 Í$"`ûl ;dSX5n,gSP(Ù¤ƒŸ§¶7]0¡*ÒØ>H?ÚÃcÕÕÖ)æ.@z*¤ú  'ùõñ0˜”âô%J¡Œ/N¤Àœ+,™s†¼ŠkŒ¼;Üß  'ü·¡·…Qü"ø“ô¥ý¦àï›Ó“¹ŽžÔ¯§§ÏHS™¸Œ“# ´áºý¯‘æVÚVš™+Nr(QÒ."@k=žìëú0#4êñ¤ñ¤ìñdtýnu“ÌÝI„'–Ô±s㌃Nøh5¦èÁ¥¶‚þËÅàË\b¥ä—XËÐvÏågÁ%:_ˆ-½WÓàœàà΃s®ÿ‰.§Šê?ìCÒ3£I#3YS0Ö‡Ìö\ÛÃÊ€C–ÂiãÿS`2ùD Lš3 !LJ(O®)£ÒO>réˆa|­Ë„øâ€¯Á}˜Uî ý-¤[êÌ ȧ}~ òÙÀi\inv»Êñ½e|-é»Ò`ìÈ•VcTuK­ü±‘Ï´g õ'Ic¾ 0 5Ãd˜ùðoOV9Þ&Áü´Á$‹ÚbÒæ‡Ûïþ $?Ž endstream endobj 309 0 obj << /Type /Page /Contents 310 0 R /Resources 308 0 R /MediaBox [0 0 612 792] /Parent 312 0 R >> endobj 311 0 obj << /D [309 0 R /XYZ 72 720 null] >> endobj 308 0 obj << /Font << /F18 140 0 R /F41 161 0 R /F39 168 0 R /F45 160 0 R /F17 138 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 316 0 obj << /Length 2987 /Filter /FlateDecode >> stream xÚÅZI“ã¶¾÷¯Ð-ì*‹ÆÆí8©ò¸&•KâöiâG¢$ÚlRCRw~}Þ.j¨—8U¹ˆÀÃöððð½R›ãFm~¼SòýëÃÝ÷u¾Ñ:.’Äl›Ìl2•ÇÊ%›‡ýæs´¯‡±lwÕýÖ¦Itè»Çû_þöýG§W£\¬SsҘ߹Ëzâ4Vyá{|ÓeIT¶{œ7¾Ê‘WØUM30q¸GÉtÍ„Z&9t^$ùx‘4ÎM=ÂDÛIÏK+öÈûf›«Ø$v³Õ.v.e¦…5Sبì+.Œ}]ícÙo¶ICAö[·¿—ý}¢"þ=†ä@BÅ$ÃáÌ{ÞÕÿRÚU~Ý–¿—³4÷\gñV±ÞI¿o§{Õ»{h<1e>Ob¿ãoÝޛΠ§ÆúXŽJG©è[=ÒH)–Œ6&Nµ[‹¦n÷õ®k:m¢–í¸ØÔõ§å¬ŠNt,@õ_<7­£CY÷Í“˜Ûª¿úo´)né«ã¥){n:öåù4ЦÔz7<“Aµô² p¢c›¥þ¼ÆoÝ™xä9ŸnêùÞûŽohÿ2ÊR¸N×ÿF’J¢ŸdH ’Üax,›‡k,æ"Ý!Ä¡QI¬µ~§º"™6Å7fÁÞÔõ­a$ª1Â6S»‚\«"™Üýðp÷õùQ„œDžÂšÖÙÍîñîó/j³‡F8‘Øùæu}ÜØ8ÉQvÍæ§»j­@¥TÖÒ\Ú9¹BÇ8´E“@qB"QIàÑ'• l4Uq®òé¯7x½T¢âBM ðå2ò “0¹Êê…á\ötîL|äR_,QyÄûŒ €•sIÊÉÜîça±\Ô<‹3X}¥ÚŸä©¢M#{·kËÅÚLªÑ–f7Þ…vž>dÖwž¶@+ÿéS;kÓO °áÙS½ÀÖ°Fš `*…tJ Õ8Ä7ŽJ§ÓÉþPzÌ´N .öcõGÈö¥nyÈAÛ§qòIåHö0í±æ‰[®":€?††}ÅÔ}%HKè ]:P‚–‹|nëÐéòˆ¿_&Ó€ Ý¿°ùyªŠº<È&dù$6¶XkÏPÿ;x- @¡±ï™$NÝ„L3ÎnM¶»Ý5—}t4L¬Uò.Gä;85É Þ˜c±ci”uK"¦~ ßµcåŢׄzWÉ`/OÜ ÒŸulëÀà<œ*'lX'ùZœKëqgã4{¯#‘¸t¥mV£F_`$¤€:š~üj *d×å º#!¦FRP ‘×ÄTV;KW#—«Á}`ï\B%=qìÁskž¶Þþ’H p±´—ˆx›b“ÁÓÞ94Ñ—€fd晲¯†úØr7B¾òÕ]Ž'n ^q¸8RÝc%3Wø‹0È”Á@ÛfÜ{O Ðnu0=ìüX¡ßêTôeFÔ"½­lÛéë±ñ`?cÍ{Âê;ÝÕr³ƒ ¨Öp¸kꯗ* ‡.‹]ªŸÃ¡IíkphÁç/ÞÐ%[Jg] !VKü¸%"õ ±K'#øjC!…Ø@w'寉7±­01ô{ÏñãÕ‹â < gµ}äÀßQ¯GSù2šÒ©\-’°ÚMÁЮAnÕOik„C ét‚»ÅfB³;mg—•±N¦˜õ—LJ tVÄIa®Ãˆ7Ý­Lek[ê8Ê hƒ A|5áZ>á× àq Š×p$›S·ÔqîøF…r jDõhD·[X]!Ü„Pè„|¥¯ Z‚…#‚²Ôà9mÞíç¯mLï #Ìf2Q¶£Ùü/ÀhkTŽS~…IäLC Ž8ê×-tÊ\B'³´H!t2t1_A'¯ÑɬÑI3:™5:™:A'ãÑIßB'#@„ñ/kP3ý%€RÖýO ñe/̪ôíÏîÌÙÔ£-¦êkàæì Ã>Çù‚VÀY‡H/y;H’Gæ¥ØŠM(%f ”Ä$Îòw:¶™³×Æm‚'Ü%]€ˆðÄ^@–ĪÈÖ§ÁŒfvòT3'i§LÒNL#)ft\}U¬x@ïú=iV&&.c‡qîäD2/|h<ƒÚõÈY+·cwök{ë<éõ‚\rUŽûQŽ-åWŽM§¼ÓœÜ¡¨Äþ”g˜€6 ýJ!6_Æ«†[ Ô± ŠŸ¸i¸ìp[‡‹ ídȾ&¨º4ãjÀÇvìK€ß±fDáîŒïÁ]}¸•™!„´\eûsí¾e˜È1%ÀµŠ—lsýçǬ8ºåïÙ¶B8ßÈS¥yˆƒaÐ+Ž&›ìkq°É’•ÕÁ{´ˆƒñrñg'8ºt­ÏŠHÒ$'ŠOs<á s/lൈ€]¬2÷ÆØÄîÝéÞ, EÀÖ/b¯‹í+©vsš¬À'%ð¥ü“€/Åã)|êœ$/®"†\7ñùÐÙ»ðœZñI™fÇ"¹üfhèÍŸ7m‚%ë Ÿ(÷/žb’(aß! ŸŠHx±£/½0´LZ/Òx±©“× ^›9ÕzWÏ=k:£.6 êÒÂÁõƒmªƒéËÿ¢& Þ&]>ÓYRêr Šui¾‘¿ ÔŪ‘eJY~B]¬ˆûõ$ ,Pëžãê¶÷#¾ñÊý¯%£^ Îh8ÒÍ ºŸµTLS¡ÙtFž\n¾C`JàbŸ}í7âDLPâ«Gšñ‰+óõƒìî[ ‡•›è-I «+x¦±*ÖÊnLª düs¯4Ö‚sQÐT¦xù‘Üôê&/"ÿ}ñÆ@7 ìï™™²±šŸæø•ÖX¾Ò@•_i 0½ÒÓ+ P§'޼à'*]=ÑÐ6:Yd>’éÉñQ”ã•'šì…'­Š¥Qþ¿¿ÑèâåG«\œƒ_q;p(Û.ü^ƒ Êk YÂt²¶mÃsLÿ [¹g"/5aô¯ºãœ~Á¶¦l¥8eª¡Ì*Sø¬9R¦; ¶©¸×áž“"ÈVÁ ?­]û…ZÌùß•à £7e€¯Emâ[G©®eÚ[Ñ5É‹’ô"q³¬Â²NÍRÖ =¼ S»xÀ¿9€“Äý°K÷Ã.ý3 Zø_]¸IÐF AkK‚F"ÇîzáјçoÐòG¾¤8NÀyŽEɃd6ÿ‚Š!àBêùÊ<;œ`aâ´˜¼¶¸¸!v.u+ °¤Ý$é‰3–4§!´s}•†Xx%Eô E®r"•EM9Ž@Ü•9¹Zž^ˆ$æ3¢Ñ”•ÿqÜdø’‹Ãº [d6‘ó‚yôíZIÙÚpùBüË8 Xv`¬÷³\Ûc2°¹7"§`+Ÿ³ä¹ó9Êí„#h£¶)ìùCëÓå9¦ÀËAÆÒ.rLã ŸO~Fò¢©ÄÖËÞüKKîóÓP8UÍ™{ó?pVƒéé~º)6÷¢ž{&Ð?·¨Ûßñ:’QøzJ†”,¾ñ'T•Ž4õŽ]þ(>Á?¼Û|¦AÚH;ÿ¡lóY3ÔÏcT\€Vo‹<¶þ¯F­:ÃñìØ™ endstream endobj 315 0 obj << /Type /Page /Contents 316 0 R /Resources 314 0 R /MediaBox [0 0 612 792] /Parent 312 0 R /Annots [ 313 0 R ] >> endobj 313 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [339.361 133.167 353.06 145.786] /Subtype /Link /A << /S /GoTo /D (section.12) >> >> endobj 317 0 obj << /D [315 0 R /XYZ 72 720 null] >> endobj 314 0 obj << /Font << /F18 140 0 R /F41 161 0 R /F17 138 0 R /F38 159 0 R >> /ProcSet [ /PDF /Text ] >> endobj 321 0 obj << /Length 3029 /Filter /FlateDecode >> stream xÚÍZKsÜ6¾ëWLåÄqi`âÁ’“ãØ©l%R6VU6åø@Í`f¸æ’cEùõéF|‰’å•ÚAh4Ý_?Àp±[„‹ïÏB÷üöêìùk©_/%öôºÎŠbùîê_Ï_Çá¼Hc¦«[êevjoiܘ •2©b?ŒÑž.8g:ŠYI©X*à2JùsÇ”Š1%Rd _{¦p±žì%\ ™Â­Üέ*5ã 7´ÙW§bCÔór]œ6_xÐî õþrU·êˆÚ|$ ¶Ÿ[SIƲÆ*U­Ã{FØÈêÝé`hÓv#Âoz6ÀaÏ4t4ÕÁ̓5¶§ÂË® ÓXEE=Ž" ü¤,ŠbþlˆX:a«1ÀKe»ý)Ò‡›O[['†“›âG3+‰÷vÒ†¾Ú—Öþð­6G`Øí)ÃuΑT&þV – 8ÃÆt³ð<ú‰+Ò˜nCï2„3¯èùÆm¦Â€Ù/j„lüòýÙâ­ĹûNDú¬„~Æ3k®Ý¾pîkOM:ShБOÍX„Iò83N˜ ;|©Í§œ÷³wËÜo»©`RÈÁJ–K¶ž[*æ,ãÅÍþ°¥2z\Ÿò¢]女OÄHÅÛ @]ó¬³PÔp§˜ žÍùDµ‚mQ` ­¼ü0¿…Hƒ`ýHZ®3jX؉oü¶ÀŽ˜­þ+šõæt$ ©¼a¶û¬¥Å.³EÒÍaŽ WLÑTgè¼&q¿¿Y:!Kµ±'Ãp†ˆLºóûõb&·¬ð›æ@zbôW{C(y¸R„§ÖÜ+ú²3ҦΠ7òðG¾'ì‹ÈÄ`rÓVu¶s$Y m \ ´¨YRà’4O¾nÚs‡â{7©ÉGª–Þò- Îî·ócW5žœŠü·Ô´ Ï÷ee÷SÒkåžv9l8ëÅf“ÿe„Ò~v[ÑÓy+7ç§ÿ¹¿Æiñ´³ö?×䟶U=«ì NZ¥pµ+7rl{x Zz¿asKÄ1@Âc–PÉP/ ì‘z/|!ütNÍ õcCmlÙ ¸ðß7Ó®uæF9¹Ð „#+¯¸Š…éäЛ&ŧ°@‡<¨Y¼^¦"@½@‹0ft…ùzN2ši0ˆ4Æ™>OF&3uÙÌBKzÐz‹Rz÷ÍrG2xþÌÙ)=p ËݳçsLÁ'J·kë’²Îð%ɦݪ»Y”ÈÖC¾.žÝË\+!vX¿v?‡J1­ÅÔ òÃ7PZX„²ZR¸¦…× 5Ø¢˜ÖÉ|<Šß;×|Q/öÜì­¯ó”©åÉJ )AçàÃæ¶Ì9¦*·Ô-¢¤Ø\°{¹¥¸p]\,‡a•…û•Ôk%wûêÇÁ¼ÂQ95Îh¤$\] p@ÎÖ¿‡¦ˆ1FüŸ5YŤì:ò,m§Écà3f\w¾3ÎnŒÛä6¡Àl­çÂt¨es»BÓÈSblüy;ÎŒ€R÷aA™›av$|Êã¼ãun†™õòÎ.=tæuÓva¬Og·0\_S›`؆ïÍc¡õ»ß.^üøã›«Wx2€‚ç.GZ@5EÚ‰C†a³Dà$úÈÖÒ8{uuöÇwQ?×’ÅZCÎ,zôb}8{û.\là#¨0“:]ÜØ¡‡…Ÿˆ‹‹7gÿ¦ºÄx-®¦âhAÖÌݒͶŠÅ=£R~ã¬ð‹ËIÞ;—ƒÙ½òPAP;õO’Øî®ÄD³Ü’LRÃÉ>Eb"Ô0D[Zªs¼Ÿ(2%èìC"ô ó.išƒ°¨—ÇÇ%FTîŠLÀ+&À+>Idü…7H ŸŸ.²;ñ$pÏb•Œmô[ TWRb¶‰Ñ?µG‘vy\i—Ý©aã–:Ý×ÄE;Ò%ãÒ'±ð¥Îw{I8Ðz""H•á`ç|ñãqy}çx"ïl? š._ò‡ ’_Þû˜/…L)DæKާ£žˆLœI.-­N0÷( 껜p®îçü0K$dBvšwþ¹á¯F@—2¡ÕœÕ^¾ãœ°ü Ãך¥Ø.¬ÆAÖOƒ9p2`÷„gó‹ÿ£DÊyê4}ðcظLç?„»cûù’¸ Þt!Rà>õS‚´ð|>ã þ/¿ á*œä<6ùÅL: Ú콯i债]õ…z‡°N=¶–Ã(M +1‰.°B¢¸è a¢hšSÑÒkµuËî%‹ÀÔçK j˜õGƒ:Û8gT!l©/b6÷ÈT/«}Öv*³(»Œ—#¡WËo¤±ê•v·³UHÐß«tõñE €S÷N7”÷0 1W`\C®™»j?uZ§ \ÚãˆÒQþÛm" SîÚ½Úú¾¬içËCHõp8UƒÒp$9•†ðwÈ€7xZ²Ê_”bàÁ&à0/P‰¸M)Q™¨îƒ=Ù.Ãü›67êT {šì`¨k˜Ë¢BJiÓ£ž&L¯ ”Yê£LÕ}ìW¬Êâv.{µEHík”:JsC=˜ï›†êº‹] E¹8€ìhgj?¬i@èX›yujúé äXÅÁ%f^7ycF'Û:fkG%o渮 ŠÕ– xpEétÝ“ª²¦ÜØ š”j¸øìŒ_¨ "Ru'´S¨Ô _ñfÆÖ@ñz®õ$OeiÖ¦i²ú–:°lÐÐŒ¶š-„B /eô©)üÊω +¼ORy ŠßyHT”/‹G¦F¶#•†]ÙƒŠBJÒñI5xlBâwôb fࢮÇ-tU wÐêÿ¼rtd¦ ‹}ש¨=²A ¾œºmÅÁ‹¨Î$cØŠš”Gô¹sÐ,Ô—Çþú—W¯¬˜f|1 <þâ!±¶Õ=ébÄŸƒ'—‰¥%yôÑ<*æQóÕU>¾C“Qw¹ÒÝ€õWRqðòò vpád[¨nŠU …jѺûÔ­-5]¢e+¢¦Ïˆ%Ÿ`ïu¾#¢UƤ]îŠG®¾cQèÎ5±ê¯‰•pˆ¤°þdu»ü¥çä¶,aq‡uOizà‡Î#{ßl/T”»7¤Å¦>¥Qþfî;:BìÙGbúAàŒ£›Â§ž÷W<äL¤“’¶Ãöõôm¾"·®ú \ÝL.8 «¦É¯ó"o½ñZÎß/r`Á8{3( éÓ{¯_áÓ1ë|œBUuWAŸË…#ò.ÒêkøéýÁSò_—)÷בkú×d|÷Šwâó× ‹?@üŸä€œÇ¿ÉÏ’"-Åå?œ>³å ŒMî&I ŒäÜd¬ùx“·šHð‘b¼É¶G̉–Lõõ³äAbZV°÷?J‡` ˜î`ëˆ1Šû/ˆz,nèpÓb—¿Üœ~Ôe±‡Ñ£ik„g¬[á«C.WväìÓÔµsÍÓŠ†K»É¿AšÕ» `dò¿… ©/ŒdyAÿÿô?·2ÍâÁƒËÄÕÅøЗ¿d]¬, endstream endobj 320 0 obj << /Type /Page /Contents 321 0 R /Resources 319 0 R /MediaBox [0 0 612 792] /Parent 312 0 R /Annots [ 318 0 R ] >> endobj 318 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [149.685 612.088 163.383 625.039] /Subtype /Link /A << /S /GoTo /D (section.11) >> >> endobj 322 0 obj << /D [320 0 R /XYZ 72 720 null] >> endobj 46 0 obj << /D [320 0 R /XYZ 72 720 null] >> endobj 319 0 obj << /Font << /F34 144 0 R /F60 323 0 R /F18 140 0 R /F38 159 0 R /F41 161 0 R /F17 138 0 R /F61 324 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 328 0 obj << /Length 2626 /Filter /FlateDecode >> stream xÚÍZ[s·~÷¯à#55\w±NÓŽRË5v쉘é´qV$$mËå*»ËÊê¯ï9ö‚%xñؙɋ pîç;¢³ûýõõŸß/_|óFèc$SŠÏ–w3¥²YJ5¡RÍ–ëÙ/óm¾kŸÉÃÅ¿–ûæ ¶Ë”¤JÁavc¾iª‹…Èø|m>R&·¦Á¯bž»ÙíOç»ÿÞ^,௩ÝBuçö•ùª®7×>ä­åµqË»ÆÜí6nò®ò¿}¬«û:/Ëb{ïv=íCw„qD 9&z‘("˜œ-˜$R&“‚ÍŸclŠ”(žtl®óâɼiëݪÝÕ¦! )Ôü¦*‘V`Ͳ[;(«Ú/õlàlÇ1ŒŸ8hÜÆ»j³©PZOp>Õ+n¶ð-#Šy=]¾~}õöêÝÕËTQÏG:æ#£D¤¬ã£‰j”¤šw;^Æ„«~Gqè ÑíZ˜cëUÈÃ/ ™Ñy¾^»U³1¥±ÒÆnÕ‚¨D½V“D÷¶ØV^E&zœàDéÏÄTþÐm(#’§nŠÿ¸tJ2¡¾‚ØWSÀßš³tI’py¾îêª<ª©HÆÄhAI-¼y{ýá´h•þ®ü S—¬Wƒ> °Ýô¸+¤$Ix¨<øÑIvT ×^­Å;­hýgƒŸ"±i¼õ¼„¥ç£íŽmcêvò«;÷«ð6Ïo»Cöµ)„×¶vÄ\ßœÐuŠAžÿ®tÝš¦uË „ÈmŠÆ’óý¬èÈÖå±ýÄ“ÑC`\@Ú?îIR>b”vRr,$2æGÊ¥Û%YxIX6eT†–,˜ú¼s¶±s’i=œÓS=ágý&†ZÜË»’1 ûWï>,ÿqsuØ*;iâü _ÆÎ`”H¥Ï4Á2ÿú˜9Ï.tbQá)³è90¿îrp\N‡+LùØâÕÏýS3¸Žj ùÃûyÿó7d°“O1 ¢Yr®‡vÔÆ!+,8—Jçlq[´ÞÿŠí N‡;C%¼kH;¦}ªêu4 ƒµ&ǹ«ƒ´ñ1ïÍDˆkn¢´pNd–ŽÝØíJX(26„½O±s4˜v¿ãÏûJšœ‡h5;ÿ@ÔÒ+ju×d„ƒ¼ìWE½Ú•M›oWÆÃ觇 È©µ‰G<ðçL58VÊô4Ø–UÓG×ÖøÛÿgêj/meX$é H¹þéfùýõAsSÉ”üÊöL!G[#®š¢-ª­›r1Ü­³ÂçßÑÞßÿôúæúŸWÑèž"pã§Â) ÅηÎCGdaµX[yz‚6&oÚEÄûÌz8Æúž[ï\‘tâÜ‘S2Èï”3&ç«â¥µ³'K°@/N;Y ¹+ú o­Ûjkö""…ðOÓЄ–šÏ/¸:bEJ-Ž#E(«tz>öùbK¼FΕ:¤Jañ¦|™Úþ„ßf”~ o+4•Ì)**CÎ /À&ä'@À’õϘ=êj°Ö¹šJúí§] r¯P']–ñÐÕ¬CH@bzê<˜Žüf#þ§­ÿé±ÿÁÆÎÿ\ê‹á2(´(OOO¢øÄwòíÚÑU›²ÂÛÿÛƒDàL¹½=¶È‰‘ Ls~> ûaÃà{—oß‚Ûݱó˘u§)‘:r¦m5­û<¹ª¶˜Ï\Y¾´kqI*qª× ÎFe—HÁ54wÿ EÛ‡ÂOwŸ» ÛæÙm‘³¢ •ûaÕògǰ28LŠsڻ˛ޤ½„«¯VhE•°!ò-(¨¢U\ œ¥^ œi' œê´3DpÑ,'‚q6`‘?0wømöŽÚÃ/»­Õ­“à¥þv(·1¸¹Sa…S>n a%$z!è¯BÍñKhìX˜R}ª@Õ)6fy·ä±µ²­ *õ_˜:Px¦cŒy°b„ršh`CtþÇ(Êô'{sË•\,ÍæËKMžŒ‚\úØrùãklSÇl @F64Ò£åÄRu^ðàIÏš5R— (¢ïÔ«RýÆþèúYM¥=jŽZ ÉQo÷Õ«âPy;T,û5#¨Iè°7Qú(sP.%ì· 6à><9Kkh2ld@ÿªÁ³.îfǃ `“S-ÂlÐl§ Ì¥¼ÐçàÌ&;ðá‡Ý~Ð3µžéP¸ä¶˜ZÔ]3ÂRù•ÚD‘sö¢ÏÐ =Ù’­„ë/B‘‡í6÷¢Ãµ¶ ‰k/à:†ÜÃ>eqa ªæg·bŸ¦p°60»Ú䡪µ$4@ƒCœ•ŽpèUS ®îžÖÌÿùqSíꕇ!«Êò²6ÝãY=in=æu^BPòó›¢+ཀྵc3ªôNW¬š°Ï§4&ôûiÕEk:õDóX49ÊìS}O†&úÙêÁ@µ1'H÷T¤ d§ª<`PZ':xßKvB¸ícxÚÓ½W¼–‘ˆª~„ÐRž¶3$+àbg…o ¥sÛ> endobj 329 0 obj << /D [327 0 R /XYZ 72 720 null] >> endobj 326 0 obj << /Font << /F38 159 0 R /F18 140 0 R /F34 144 0 R /F17 138 0 R /F14 141 0 R /F41 161 0 R /F61 324 0 R >> /ProcSet [ /PDF /Text ] >> endobj 335 0 obj << /Length 2065 /Filter /FlateDecode >> stream xÚ¥YKs㸾ûWð(U°Ä‹ '§Míì–·*»ÉØI*™™MÂk(Rác¼Î¯O7>Içd ¯»¿~: ž‚0øå&tÿ|óÃÏ4(%‰”,¸ â„H™*ŒI(dpŸŸ6÷{½Ýqm>‡T”zûåþ×~æ‹Ï# p¨ù Jû®ïŠ’dvïòŠHÁذ7««-S›.-ªÖÞrlêí–2÷6‹jó¼/²-‹7{û3m¤¾Õ¹]zÀ×/ö¹Û(ÅüfÆB’ÄÉpuÞè4G¬^”œ(¦†­€é©I¸1Ø ’ˆÑ`G"²;>‡2l5¢JèæNg]‚ÁvPvРAãÃÇ_n‚O°)ÜPéÞ[cØ3(Ùî"–lþ’µ <°µ~´ç‚\­»Âjʶ¶»@}évÖö¯ÞÚV‹Êh^fiYúôÄ• 4ŒçæÜr `êÉ 7·ï ^V÷Ó[¨ˆR-ô6hv°f;Zð°¥›wöWQeeŸ{™G…$TžRo–ztØ Œë€öjP±çt)>ÍñŸ,8 #>©ÁÌ G¢ÄDF¾»«z¼rd«Y8Ô3Z[SÂëcŠ@—ˆç.!Þ/˜ÔÓŽ*ãÌ;&¹½¾Õ][üW{M©X~áýŠ;ÂP9ei“UZÝÌó¬L^C.ƒs·íhBÀÏlEÕéæŒ‚e"ßκѨð oBŽnZç§Ks 8φ¹£,ía:#L”8f÷|éU´$ŒEeynŠÎq!Q8|õbÝåkʶ7Ε ðžš­ 7éÑÏhàlÌ®‚nj“-ðæãÞ>Z¤ê»ºkך¬›‡¢k½8!c)~ 'Àì–8G}¬pW¼¹²Òñ±«Þèk^íÓ¦+&ξçÜñ "hÆü"+$^Æ 1 ²R~ŽM}ø~ÐîÞ³ Ï¨êFß w¥å·AvwÏù`5[ ðæàE‘„Ç?é 17éŠÑMZåµË¤G“/ðøÓw) s ¯½ùTÅiu9P$„³äÿFl(rÝÅðª¹Ji·¯ÏÙ^ÉËT=šBS7usXÕ¼îÊ¢zrbØgÔøÎít¡"×&ï ehá8óélñ·‰×uß—ëLBI–ÉÐ"õáXꃮº3Å¥—3f—‚U¾bªÓ«R$Ž6™r™>S»÷5sæ³À«o˜}½fSP£‹+°¿"­O1´ßŒ8ÑýZ”\Ž\úÌÃMš ˜«¡ ËûL»Ò îÓ…ZÚm% ¼ŽåXÞBí»êúNd ƒ€žÎYY[Åáúù–†”ˆDÍký´ÿÃßÂʘÄShY¶° {2{Ù£~¶'--nš5c¸çVű/MˆÄ×FÒÖ¾«]E°qÕx޹ªué¡ï†ž´=5|󶹪Og}Ó8'/_δԾN».Á_×!B2U»uã;â¡zUc.™Ó¨ÁQsà©Í0a ]Ë'cázÊFCTƒ–Lëöi7Ά6ÙxÜBkþN™AkÅ…x½ÆxÜ·záœ{êÆW¾È¤‚³¥ÙM/j|ìÃýÍn¨Ë0”%DÈ8`ÐÂË(È7Ÿ¾„Aï~ *øç³Ùy  ŠQãepwó77 ZÜKѯ@6<ŠGÔq}o ®ì«OB–ƉÈ?Q¿üéîößÞÙOÀJ³O#áØ{ " Í+Ë ï!ÚÛ©I÷æBâchz÷Ûëï÷ÿúLJw·¿ÿvûN^þä|,¦DÑd©í#€ EéªK6ÅãË’Rc<ÆD eÃC©—̺N/¯ x\^é_E;EzH‘fWÆ c“é6EN Ã" ÷±éccP”9‰RHŸ”ÉÍ_­sl=¤$ˆßííS ÑÇž}„ØÁ€Î Î5ÜÐÌ#DÈgÃEIÙæ!mAÇðÈ7y …‰Yl»¦Ïº¾ÑöÔinÝÝ‹‹ã½&c‚1ÊÅW¨ ü‹}ÔÞmŸŽô$ È)£2í56yDQœ¨d'ê›sE.×óAW$ )L‘(¤¼>'ÄÍ|].’í.¦É`–ÖÙ·Æí³b“s2Óp xiå·bù«½Ý’×Üì…Ø©BÎdbÈ®Ñ)ÿ0Y‘HÑU6ˆb’˜âÇnŽg?b*U¬4†Ö›ÂùIŽo¹1 îºÃÆûŠmp߉m°Þˆ…«7àÀ¨¸y"jìÄ®c‰ƒ{SûÓ?¸b硸˜ºã&ÀŸöK±±C.×¥øT:Žç¸Æn:¬8ŸŸ'¬Çº,k3,;%4ª.óö½„;q1-ÆæE-Gõÿ&N~ófˆûbV_ï•L%²‰ýakêÛ¾-ç|.wVÚ>¸\’è-`so_ƒ¬žþ¡ðÝhóÊ—n¨\tþ4´˜fK[^ÖGWédu?o܆V•bšóŠ*(8¨\zÌ$¬8/ìç0ä>•HðÀQØoþ”EkuX×ã|v5䪆Á7´në©®Ú”è³ÕS7ÔºÝÐ¥­ßj¡"4‰–›wDK1 P‚Cý)E²¥ÿC%ö?{˽– endstream endobj 334 0 obj << /Type /Page /Contents 335 0 R /Resources 333 0 R /MediaBox [0 0 612 792] /Parent 312 0 R /Annots [ 325 0 R 330 0 R 331 0 R 332 0 R ] >> endobj 325 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [136.992 689.614 150.69 703.562] /Subtype /Link /A << /S /GoTo /D (section.15) >> >> endobj 330 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [352.169 436.645 360.015 446.342] /Subtype /Link /A << /S /GoTo /D (cite.mathon) >> >> endobj 331 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [158.837 167.525 166.683 180.477] /Subtype /Link /A << /S /GoTo /D (section.3) >> >> endobj 332 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [209.722 134.848 217.568 147.467] /Subtype /Link /A << /S /GoTo /D (section.3) >> >> endobj 336 0 obj << /D [334 0 R /XYZ 72 720 null] >> endobj 50 0 obj << /D [334 0 R /XYZ 72 239.738 null] >> endobj 333 0 obj << /Font << /F18 140 0 R /F38 159 0 R /F34 144 0 R /F17 138 0 R /F41 161 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 341 0 obj << /Length 2787 /Filter /FlateDecode >> stream xÚÅZ[sÛ¸~÷¯ÐìCGšµ°Ä·Ó‡lš¤ÙqÓéÆ}HòÀ°Ä-EzIÊnúë{’" ÉNä>‘!\Îåû¾*ZlÑâÍEä¯?]_üðšë¥$‘’-®oŠ-T¤I$äâ:_|XU·útýó¯©8ìÆáRà ¶ÓÇ(â¾—:ì%I¢Tß)÷=¦ÓF‡a~\­•,oWk¦–uQ­àÒ™fµæ,^v5^Õ2­ÜsÚ4)vøâëw-Mµé¶¾k×·¥mZ‹¡IÜÏ_ݹNS‹¬™`D‰d±¦šÈX<·]LÈ.1aJ<Ÿ]Ô²\Ñå9¦ÉÍÛP¢#9µÍû7Ø÷âÕõÅïFˆt¡%Ä[ÄŠ 3e»‹Ÿ¢Eï~^D„'zqo{îœÄ þª\¼¿øg(Dµ&Šs*" e§üõÕÛ7»yDDDSñU¹y$!‘œGjU{3»ÛÒìŒ÷Lî+gën[´®åß›¦-êêÒµ´Ûz_úþŸÁ¿ÂÁ>¼û×ÕUÐ⊩™78wËi‹ÿš‡&Oá"^Ä~!ùY&§%Wv,.½›ƒqC#°Ó`î;HÇ1Ìφ^—¡ üÆqÀB2ZŒI“§fÎ[ÃäÔ¢šÅK·EïÆr™fÝ>-ݽC,ŒØ§+4Ž=ûtnÝ,‚N¬­‰ôhî0”DZÏv5EA>É“0cðGÇ'!-!*a}´ÊC£0N‹O框Xí;ð€dËëÞXûª°A¹€'M„‚,D@8ÈF îm+BŸ³þµ´ÃY㚬C ¯ÿŸà+<Ú$Ç±Ò [·®5K[?ÇÇHFmDX qË裩"£òÁìò÷» ‡ÇfXx>t¹2Ì9’Ø4ÛÁvrðB;Ý(ÎìL¬ +›Úx´NÀ»<ÈŠ¿&X-š.#`Fê¦c"H€yàJ]Ç×+Í–uãà67#* LeZ¼÷+ïQ¼/ÊÒSeÛîw¦éžÛýàIìã^o`[tyëÙ³ÇóÜdeÚôxÜŠ¾h ži Æcµ·iÓÇ•T,ÛÍŸCFY?> ÙŸÌMÝø-í[3§š9±øíÃÚÁ2EZ­É½}oj/%î·ÅáÖÁÓ™n8u—]š5õ“·’”rÂÁÓ’ ŽåyäDDJÄ^¶¾}÷öÚ¦Þ#'lU!ñg“¥ö–HKÐWUÚޱK/¦¾àS½wYZõg£Àÿ²Ø¿·³7¡¯>Ìê*3›P>Á„ 9•âÏbBJ*`}õòê©&<ˆËk›‹«µˆ€¼Ê²¶±—¥Á¦>æ`¨9ü44ê“ä vk‰ Q`Kù€‚f°ŒÆ:ÍdpKGn?`h»C›Nx“:#l8\ŠãÓ}0brjmæêÈ´ú€/œ–ìŠÌø‰p*fÓÓŠ“«æEc2«bqT“o …`ÂÂLH’rÉÓ“^ ©øY"‡BïÅÕÕ?^º j !«™ùŒ’GÄR ͬÉg*Øe—ß퀅ÒùîxQ ÅÅœIï{ô=Ùƒ»ýP`Úüs17=zi¥†Gù´(Û˾VÌ‹GxÙ˜‡ r›füò `/b¨Å{¿ÃP1 åèÿ—W¯C*H/[Ùð÷´òJNPm•ž ÉˆP|RGÆ ‰ùàø*Ýw+N{3ŒƒFUìmãaò}cs&ÛZȸó²[R7;H‚tglu?.JÏ”iÀª==Š+'*å0h0ªa=¯†U˜tù6lW8 ®«2'p…u¯¼#ˆ:ŠÛ•Ó n“%Qà,_b8âÕOá[Lr¿óbÉ6wÍʨÆD'>¾Ëk×£ùo‘®Û®o4®×‰EvkÌïûUî/šnlâ— ƒÁuBG‹Ëè¸o}(}è~Ü9ð8æŸ\ì£GecÉd½”pB9Ÿž"¼À]hŒ@ •=H÷Ü›\)'y°m8ªÀÖ¶«­Æ…ïÐÏOXåbC^€*çi–*k´²Ü“'ºIË*óã:@7Q]ën1ðZ™bcå¶Ó¶+­ÛÀƒ”3.êk8Ÿn@ÇùkÂ@±e”=ÉÁжÄò¯Fõ Yí‚¥Øì!¨+Žn;$%(ž¡ TÐnH˜}BÙ¤è°A+EVˆÖ ®êW)«lë¦Ãó¾SŒÚ§†ý±åܹ  "„3lëŸz ƒ¦õ|`C¢õ\Ò³T‘ûZºÈÒòrVBôt¥úbŠŠAë)€ªD2k%£¥i2 Ö¢˜:\&@à( ©Õ”a¦óS‘(;–Ò¢÷]Ðs’·Õt˜Ò¤:à gH’Ë_¬Fg¹ÊÐ-jvþlÏ<˜d˜“u…&/]x`[™úp(K›˜ÐÔg1Üö¦Ï÷Yÿö3&å— ðHFÒ^˜ò öŠ&§vÒ=°™KxÓOeá®iÙ˜4÷ ÞÂÚ'ŒˆÅua¹Œ°h£“dÄð’Prä¿l©²/îÑB1º|‹).Qµµ{»Mû_¹Kë óʼn£>¦ŽÂ'žlÄ/úé{ê+DÅû0ÀSЂ¬ñ|Œ&^G×»^|wEYt…iGƒÚö-X¡,ªÍCx†.»áØÊõp^1ûÎpSïÇ‹ ~ÅLG5ûUfÑðµqî.(/ iÏ·$SOÀy ÑFAÌ0ɉ8ç±’ˆ¡lű˜æOÇùé®ÖÔ¢¥XÓZˆa>²¨Y1­wSÉ­»w,jA—[6@ì¢ÌêÆwu=î«4œÉ_€Á‘Ð˒‹zW7·Ðqç3–B壦 ÛÁŠ=Uÿ¶·‹zF"ï»NY½ƒ­À$Õp6{ÜÑ 2!F¬H 4ÐÞÒ€îNØ¼Ì ÷Á3Ð?¦g:ärÛ¡ú²ï›}ü¾¶Ú¿5¨þ HÑ­ãWϲ®×°Õ+„zI•މD@­ˆ±jÍ„Ë!süá Ä6HHø32ÑÑÿcQßmÍ,ÞüAq‚¤×Ô[Éךµ{J[*9´ÑåÆ')¤J¦IZ7¹iÈ×gØí¾ |‡×Dƒ¥ZÅÕY¹•0X£°CI®Í-v2·~EülŠÎL>»<(:¦_Ö·¯û]Z­QK¦ŸKˆuL»G¬ÆaåÈ?Öj“̌ƈNãÏhϱª¦8¶#QGîàäÁ§ûHÄÏ1!"C¥8ãqÏ ò¤Ÿ^¢i«Qª7Ý\¨AŒç‹·îëè¿íOòQ¥<âŸ˜Ú³Ž‰†ÅÏ8#Â?–ÀUÄDkv¦Í(mÇŠ{er² ÈÒ癪; )<™ô›©ê˜›Ž9bú_¢¹˜ü7åÀwi•9-²œ¶u~öÀ2â,Ë1F" q‹ÉøL˽¨Œ±ÖÃê°)ÜIq¯•Úþ´ü½Éì »7Ölü±#bïd6ÍrjNX”´ðÖ:±0iׯĤï`yb endstream endobj 340 0 obj << /Type /Page /Contents 341 0 R /Resources 339 0 R /MediaBox [0 0 612 792] /Parent 312 0 R /Annots [ 338 0 R ] >> endobj 338 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [276.682 123.935 284.528 136.554] /Subtype /Link /A << /S /GoTo /D (section.9) >> >> endobj 342 0 obj << /D [340 0 R /XYZ 72 720 null] >> endobj 339 0 obj << /Font << /F38 159 0 R /F14 141 0 R /F17 138 0 R /F18 140 0 R /F41 161 0 R /F34 144 0 R >> /ProcSet [ /PDF /Text ] >> endobj 349 0 obj << /Length 2596 /Filter /FlateDecode >> stream xÚ­ɒܺí>_¡£¦jZ7-Î%~/¶kR•J%™ÊÅï4-u·Êj©ÝR{fòõÁF-mí,¥AA@(öA|¼‰¥ýåáæÍc•FZ9<ì‚TiœE±uÁC| •¾Ý(¥]øÏÛ܆Ź.†ºkûèö÷‡?¿ù ²@©(wNãÚ8ؘ8²±á¥ïúÛÖIx¬Ú[†¸®*ïx¡Y,L]¤s ëi][\†—5úÆD6ѶEËôE[6Ãûsq:ȾOõp`hÛ5Ýå\•ÜûŠÜTç¡ÞVpŽux/¤†C-‹ûj‹ ßAÏ)ZÂ3eÕoÏõ#tpØ 6 $–º Y›0‡=ÝnŒ5@Nv-è†CuFІμœ˜`/Ó;ž«ûîØOÀÖ‘'Nç¤C"@4Ï ïÕ5¼Yé'u¾0|,N§ºÝ3"°päá®Eœ¡ã^A§Š—Ç™6ì:äöøŠë@–Õóf²!f‚&¶4T¸fÂ÷‹#Íg‡¶*÷Õœ* -¨.Cƒu8“xëXPÕYNT±cÒgÇL'aUlqêÀSbA±€Ai¬p¿ÙBBs»vd‹|'†Ž"cþ@°¡IQÁŒQV¿ÅʶtPÀª[nAE tHýkÝ]„Ξ£ Ó¹ÍT†ìl¾“uÕsq<5~íŽÛþâGÌqCÇ_S8X [UqîY§ÅÀJg¦` ©vC´L}¨÷p8$N&TpFOƒÀß?ÞŸ×È4û Ø)Z ¼ù`Ó¹bU’DyfÉ·8Ð91{޵_¥xð?˜F*5ߌ%N,îkö£Às%*ÐIdÐ3·›Ì˜PacaKêÅk²çÓ|S/0e^`º5L5£y-!gà6åÓQšÊÕš|~]‘ϯ+òyGúxÿp£DwJgQ’›Àf°“sÁöxóå&Ž2šö- ú2ðæþ˜ênþŸ×¯GÙxª›YŠHW;ÖÀ® ¬Ë¢Ì‹QìŒíé-8qãÂâûÑùæš…ïÇ_Ĺ¹vˆa.J”™e‘ÉE>¬ÎÙæØJ4Cï}´üÞcf{>r \—ûÙz÷rM•¸ìe 1¿˜¯eÓ}å‘”X‚ZDÈ"yb¼üÚ¡ƒëµcÕkT\”¹ÿ€†ß“B8yG,NŒ“§´±Šp´¸çzd“‹óȽ_I„Øó"D¯À©p ®°Ž¢ :ï/—úë­×Öˆ y^3¬ºŠS0GîXGºF:œàì¶è+?V1?°;¸ë›=0GX¬Öa#Þ™"$@Dñš6a=ô<Äk¹Ã¼¢|¡óžƒ!íxÏó˜â¦`ËÓá¹:«Þ[k)³B  ð>íê¡H%ŽUrîßqqÓ´êQ<·8õD# α®]2rްæ†8G€8m‘²˜Î@x½´-·|$^ËÈÈ5dq][®2¶ñUMü*áWÍøUèß±~YÒÀåBØ„Ð_‘Ó¡šåÔy;¥“cHóð~`œZ¨µ£é#é¢aˆ’7hûJ¸¯_W)°w晌ìÏÝå´<÷ˆÝâ Ÿ<æ ¢)€¶¶u_5”ˆ Ê]ÊöL»P-DÛ+¢hU@W ëJÞ¦¦£{¯r)—±Vûƒ HWÅjq¥8Þ§n1gL¾ÿi¦Ã¿t犄ûu´^›ªùÊ’¼¾e=bût¨Çû Ý‚ÈË»¶ÞÂ+òo ÉÖ›†2q›HI¼¿ EQ# ¢FpZØÏ±ÓxÌÂ9ó\%8Þ_Äo@æ ‹#zM 0¾&ˆBñ™dÍl‰ôV “8W¼:6FiΓ)¡œtƒÓ{4 R’‡Gªs9ì‘E^´j pá–ì«¶"ôf2CzÚñ4ïgÞYij‹Ã…§3Z²Ëqƒà⣅Ð6†ÁÝz ÌÓÌc¨ÿC°ý™€½QI¾Å&á&õÍ*}HyµV×è Þc5Ñ·‘19#•kòH£κ™¡ýÇñj®­"§õ•X–ÄGÚÿP´¢î1U¥ÑÈÙvWe|ºq}¹¶CùôÈꋾ“$²l¥kÑDeb{<Â2°îó w«çSÑöì¡K—‡1CÈ蕽1îL¦y9â,Þ¥Œn®Qh® úĹH;sLØEî3Ï}ïI³­”TÊq +"ðÐxXwµÓ/©†»?ÎUQbÕ$åh0{BÃô¶;Cr"v1£öŒŒ®Û®­˜Š 2±ÄCÅÄ&÷€Ãä9H`—ëA€5º&íÚ¶ÚbH^qQ—^j!qXÕ¾ ‡§b w„ŹÝ6õ— 'MÂû²fíœ1ìùðà¡è׌Og:ÊŒ+^¯\’xºWÅ öµB:q‘Õ#åϯ^ÆÂXÍ‘;mU•Bq „¾[ •bÃûçí­QXÐÞWÅ#–ï¬B;‚1q‹v ëUP4(kS/§_>\<ç…H©&~nÇw'V#½µ.¹U¼Öä8°N¬­×ê1{5Ê‚„}ʺ@—º?lD©wW=þ­?ýÜñé\‹£ k!×#hrùÐ9Ž•ËÒ㑾:î}KâL.Oúâ(ÐøÇ'2ý%ȱÀ޹EÅâð©€H?FV–þˆ7§1¨#Ü}_‰Í°GÁR+.Gz)_=slE)_O‹ùw†TàB-B}]ÊÚ•lÇ^•li•P! ú?/–²ÙoÎ;7ŽzmPÌ×v2n¬…·™¦:=Ì WE­‚Úzùíâ¾xÝúŠúôÃ:ÄÑŠIçId´ù9‹7¡Rù~–pÂð özM´¯Ü›o~ ~ªC;…]Usµ­P¶1¹™u[¢© ÊXfS:r{õCb–.a #Ìì;¢-L)0?+k4d¿êê¶`®³dnè¥:ÑÇÿ(ðü/SKí3%=åFDÈÏÁ¦~z¬ FkÙç½øYR1Þ ®~È寖«˜>UöËrÁÀú FØâó exR6ÏCÕ–\0ÎF ž9Ep‚>¹ÑöÁ+õô„ÿGÂs–?F­ã(W`ðr<ÿ'D»ÄóÓ…P endstream endobj 348 0 obj << /Type /Page /Contents 349 0 R /Resources 347 0 R /MediaBox [0 0 612 792] /Parent 354 0 R /Annots [ 343 0 R 346 0 R ] >> endobj 344 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./bdm-matr.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 355 0 R /BBox [0 0 402 109] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 356 0 R >>/Font << /R8 357 0 R>> >> /Length 358 0 R /Filter /FlateDecode >> stream xœÝZM· ¾¿¿bŽiOõ-êZ èÙñ==m8ÁN´‡þýò[ÒØ‹zŸ²/9$ÅGâ—fòÇÎxú§Ÿ¯ÇŸêǯÿyüñG #׃¼Î×.g«éÈeœ¡ô#vޔނÆ~~”>ÅæœÚÐ×h!-÷³$|V_(ýéñ‘½pîn__ƒöüOß¼µ)"˜RP,ŽvÄ^tKsªG,²ÒË#¥q¤u½Œ|’J1)Ç·²„ùá,Ç?²±¸ÊèÈB;;ŠáìŽéì½¹Æ3yÎz”ÏÑ¢R´‰7QèÚQ¶dÔ-¸~=®:.quôK¶ñîåuG±!üöË·««â%$ >±“Kޏ £&bô»D÷¥uó2E„‰‘Ý\-A´i^¯Úž«¿V¦óIëò©OXu°2jdF†›Dø,c—Û¢¥µj^¯ÛîV‚VzÖ´PFÊ3rJ»Œ26™ 7al2£Üd„±Ê¤ãwt!í>¦¡aFrÆ 1*KTM3dP–@L`¹Aq7‹IBë@³X~ú%›v‡Aϱ1‘™þãmcf™vOÊPû½õŒ›8f,ÔÀ? ›ÂÿÚ³ÂVªëfF†±iŒ4n¾ãæ£ Œ+&C .Žé ©ÙFõÈ®¦ä`bÀ¸žë‡Na.?1,s¡@ÑÁ·±ãŸ>¬[¤6ȳ>²éèÐm冂 D½¯ú‰ÃÁ¤CìÍWÀI¥ù¹£G¯0j¤PóŠ®—‰W(e>HÎÍâ­ì¹¯› ÙãŠ~£Ì äRÎB´…¨ù&Šaб)rĈÖDñ,KñˆL\“ÚŒÙL*UˆÈâµ­zÄ É‚u&$ìFÝš|¢Ä™ Îl­à*¨ûÚ¦ ³Âò-ì¼ÕÅ®9æ&C=r˜ñÚ’uæ ÁÈ¡kžá¨[µ CˆÀÄLŽ"Æ$^3¶; ÕÌ4.€“Ø–Ìc&hpXr¤2¼%K"a‚™%äîØ’'è€% c†6eBjUãÇŒ1ó€ÑÜ¡¦z• L]ŠÁ4‹Q£Ig©ÚÎÈÓ«$3G®¦Å~#ñ8ö®‰ŽØ øŽçÂnôƒO®_g|.˜‚‰"ŸÞŠá ‹Œ³w¯ 9e4êä3F VÄR§@À޵©íSfs –\}C½ûæÑõ¥Ï_ zC;Bó›ÝéúñA÷Èè‘ßùŽ;Çm PâK¯m]õ‘o/ÆòH˜êœz¹“íŒaI{8ÐV¤kXjpCbÀv˜3.ŒÍƒ Ú,lþö(àD˜I;½Î \‰Þ„–t¯nn\_sôå /ŠbGgF·w!DÎ+EF/øJáŒXÓö®D%Ì‚ï‘:m‚d¹µíËÇ»îõªõ¹þ€µ\\ñrz™{‘ñÞçýei‘˜KÛásÓ]µ’ïÀvÝëUësý7a¾,¸„¿Sd®n+ .¯»\b¾n0`jøú^ F]ôئ{½j}®ÿ +(ýÃ+L¢T§÷A’_F ›ð"Ì/‰²äb gË‹5ºKÍí—¿§µÏ4Éaû®l*4*P‹zÄL™h¶ôŠ]ég™Í¦D d¬Ó‚Ñ™¥â‡i§!—Ù75Ô㸇jaõÿ™÷ç]¢#êuEä”úÓóŽˆÞ7ìˆZÛµ²#ršWtJý1mó×ìODæqÜCµ°úÏGô¾­G¤÷u£ÊŽˆ^¯ˆŒžˆ\B}6 N÷‘T›‰òŽÈè‰È8æ¡YXýߎè}úÌßQZæøŠ|0ñº™½µ×º™é ]Z*'/y¯ÂßÑ;×Òb®•›¹ ‹¹šoæj½;÷ý¬±s¦¹ÂÍÜ(‹9š6stÝû~Ö¸Ñô]xÄ ÏJ—3pà”å@oNé#lãϬú…ÍÈgìŠ8`âÚSoÐiÑR퓼0‰‹:Îûò¡V¿à)Iò†¨¦¿û/-ì½a’üƒ”1Ô©œêJ?sNP˜6(œ¬WPFú¢ÆP§LÝ|¶Ï¨Ê˜°‚ºùÿ,Uàa’ZTn ”aNñ‹À”|k^@Õºƒ¢ÿµc¥ä¥ sJÕÝgý–=A©. þ™þî¿Ô{ÃD…Åse sjô”|ð_@¸ƒ¢ öJÉ J攪»Ïú?LPê€qÌ?Õ¿ùÏõî0­w,¦œ*û•ÄF%»2ÌaÊ..öaÊé¾^Il2m•Ìþ¦Ì㘇faõ»c½@ŸùŽÿ?â±ÆÑ endstream endobj 355 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061119154437) /ModDate (D:20061119154437) /Title (matr.fig) /Creator (fig2dev Version 3.2 Patchlevel 4) /Author (bdm@pbook \(Brendan McKay\)) >> endobj 356 0 obj << /Type /ExtGState /OPM 1 >> endobj 357 0 obj << /BaseFont /Times-Bold /Type /Font /Subtype /Type1 >> endobj 358 0 obj 2560 endobj 343 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [219.505 581.245 227.351 593.865] /Subtype /Link /A << /S /GoTo /D (figure.3) >> >> endobj 346 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [210.211 138.024 218.057 150.643] /Subtype /Link /A << /S /GoTo /D (figure.4) >> >> endobj 350 0 obj << /D [348 0 R /XYZ 72 720 null] >> endobj 54 0 obj << /D [348 0 R /XYZ 72 720 null] >> endobj 351 0 obj << /D [348 0 R /XYZ 72 629.697 null] >> endobj 352 0 obj << /D [348 0 R /XYZ 253.386 473.292 null] >> endobj 353 0 obj << /D [348 0 R /XYZ 72 205.04 null] >> endobj 347 0 obj << /Font << /F34 144 0 R /F18 140 0 R /F38 159 0 R /F47 242 0 R /F41 161 0 R /F14 141 0 R /F42 169 0 R >> /XObject << /Im8 344 0 R >> /ProcSet [ /PDF /Text ] >> endobj 367 0 obj << /Length 2288 /Filter /FlateDecode >> stream xÚ½YK“㸠¾÷¯ÐÑ®¬9|I¤vj«2›df7—T²}ÛÉAm˶¦lÉ+ÙÝÓùõR/³_5µS]Õ| |™'»„'Ÿnø¬ðŸ'"Z2›eIšK¦µHÖÇ›?n8³n9´n2ìðï~=æÉß››Ãßœé*p]Øþ|{ó‰,OS™Ün‘e,Íò$Í,ãJ%·›ä÷ÅÇjwiËåJÉl¡\®´JŸÚâ´ïpÎ,ªóžV˯ë%Lì‹zWw¿ççÊö\~¥ñº94—¶cËÿÞþóJ ï>*=–h•k'ìdÒ ôk×›ö´¯ºãr%s±h¶Ôî—J,OpŒ€w^F\)ê u6%̈Eµ«I€¹d*™ÈRÅõÁÓ˜‰–³\’=˜r8ÿïÜ87Æ;µL‰<ì«P´T-ºêXŠzqnh²¨©½Ô›ª-×çrƒ Q  kР`ÆŒ8¹‹Â¥sé,w?ixÞ}­ (7;Tέñœ»ƒÃìÂLÌT]yîhÕŒ3° Hi²«þWþ àvQ7þ°/—Î÷h QÑŒdËUöùíBX¡u`‰÷ãÓ‹uçö²>÷à«<àŠC×x(‡¨Æõ‹¨©$ê\ƒõÁò1Û(Á2ÛÓM±ùÛÁ;_–«DYÍlnÞä‚÷ÜÒ³[ø9·Ôf Êœi)I $#“‚!Îý5v5Á™ÎPtpé”èÄre•¢F'7ꛈ%ødƒxfC:ÙÀ'úÆI9½c–3!2P,S& R^ßðÃÄ2ó«®$7ÎÞ+›1•Šë–úö † ½ à3ûwbÕ8Ä8tuÔ_hp/’Å¢Y²‚¸+$„/i·!~á!FxŸ„Ρܢ¿ï/0ãE&ž•vç1óàú»£I'GúÉç½Ä¤+KâZÐxïÜïmBx¤ÁOׄP­Ëœ[Y 8å¸7D‰ñÎñ^3Òï¸ë—0,Mó)¨š©1v‚ 3h=3/„Œ”§‹Õ4&½I[íÜÎ4ïâ†_OWþq©î—U‹CY膷¢·È…Xp*ñ‡ÝîË)5êÂK VN* ­ùvóÅÀHÍ2Wtsœ"OÝ–§¶ìPT‹¢"aÏ4j;\pfð öÕÁÓû*è¶ Ë¯íŠæËÍH~eU€ ô j6Õg.TÙö"ãd%d0\É„u²tâp„…±Æñµè­kuРZŸ0©ûÊç/"&˜2OM ÙŸäÀõ”Ä\¥å9ãCåUŒ•ÓfUbƒZF Ÿ£w…>D¨¾ŽÚzMÖ>Xð™ÉÄÔc(®áB\sƒæ£9¾o8ÚB,ž‡¿#€^6R¸ÃþÌqSá|¿/8(†í<{™ÞynÈCÖ4óÚ}8W§Ã£IàͱœúAï!C” _ÛLw¿#vx1hõýä1†È5˜Q6Xà)Pæ {LÒ«ˆE8ÓÆNßÅß.'RQÓ•1ìꔥ¨>DQåMÞ{ÀOÈͺg;ÆOd,7½ü¾r7Ç5\¸r„ €ÎJ0“û@P}‰k˜ÌÒdDF)Ì-øÐºàjú'§^ôzÕKöý¼^¿Âëí ^Ÿ€ ï1pÍvî7³§bRô‡£gBá4 4 £†L’E+{0µ5Caá![ü-¼cdš‚Ä¥ô/v ¨Ÿž»Rƒ¸qÜiH£Ô³0¶Ì˜tÄFø˜¦-Ës1ôÄi©§5Jä\xR=Pîý³—ðž2ü:8±ˆËo@ #ª÷Ë•ÈÌâGl2jLhÞÓä}Ä»”`ÖNŽ;FÅÓå‘ãËtÄRà%H¨à^Ã’Ù5Wœi,ÇÁmsýâE%Žß|ѱTJ2©ÀµTuD¤:Fý]1iøH,W/Hzü\§¯¾1Ṇ3õ÷^óÑ“e*³bxǰùä¼:Í2€ñõy1@(ðYý @@žý:@¨7"&ÜÜøe<Ì…ªŸø²g¸‰á¡¨)s¡àöæROƒÅ•×êÒ¢‡ÿÐsUjËQ7{,©ÿjº›,7fy&—½Š> endobj 345 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./mix.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 372 0 R /BBox [0 0 365 154] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 373 0 R >>>> /Length 374 0 R /Filter /FlateDecode >> stream xœÝX9ŽT1Íÿ)|\Þ}bfŽÐb“¦ àú¼ÚìîHÐꑺŸ]Ë+—í*Ï×O ‘?ö}¹oŸzøôý˜áÇAáË!³áéÝ‘Zg c:K¸)Ï\[;iÎð²rÈTÓ%–;QŸU[/Ççã™íÕ³A(±qš3c²Bãµa–2«?oóE,^\»•­³¥[wÏÌ­³z$±>ædT:m2sŽ%ž©œ#äK>Y£%à8B‹]4lºGù~9W#ù§)¬iµ§âóíDZdÂÙ¢¡Ôe¤åxæ9 Ð&ÿ(¡u2–”CKCÄÀ¨*?^½—ã㛿oSRÔ9pNçâêxörö1CjÈ¢œØs6àÚya ^…Tár TÉÃÒWhæ!î8³Ppm„Æ©6ë†Ø¸z÷içjÊwÔ/¼D ''§8uLϧá‰mXgÈ„ó!Ñ€ÝìÁ7½Á ötŠ ÄY$UWdÆ!í0Qpe°anüf»êX§œ£©ÝQ–¤<@·ÉØ÷“ %x HoàÕW w KÀ©š¾A³¿CÁÇgv…2I.ÆàM@.`ü\ÿžÿ]j&&IT‘±jÅu @JH\›°Uãi±ÚbN3nX°Ú™+ÍÒ7höY^Pm„”©·”•³Úwy#°ŒŸëßó×D=ZLR{JÍRÔ¥€@)C²Cb{…*RÚ¼•0ˆÛ”õy#ÇÖÐäÖ•Ÿ“Yá7¥FS*¢Yuis»Œ•ëoÆZoþïVpÛvù€aT-©O~­kÛWª_Ì[Eqk XÇS¡^Wô³íýà:üîz 3׿g¾€ÇˆF’3 ´ÈCôYz Ê©åz¤É³eDÁÿ)ˆ‹„þÃÒBŒiWnx"ë?SR®àA²¥Ñw­ùk€ª”íŠ]k˜h‰¤¨§,ߎ±\X¦9ÆIruÔeacqÁëë}r wDðãöà¶2÷:·¸©â+òzÿ>T@’¢†JÀ¥“ƒi9Ë®)þ˜«àªÕßj¼¤À.‘ùÕ'× f„§]´E«R”øM¥‹V­lõÑlÑt¤7òE#í;‹ (¬^¥s1X~»¹ƒ—Ã)øüb¨ê¯B½ðˆaÉã5b¯x…ž‘ÿ¾}Їç¯&žÞµÖónå9Î}™V$JêÛ¨GAq²*%«…Å^´©îK¨Û«;UÛyÒý ü$ïŸ Wá endstream endobj 372 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061129235456) /ModDate (D:20061129235456) /Title (mix.fig) /Creator (fig2dev Version 3.2 Patchlevel 4) /Author (bdm@pbook \(Brendan McKay\)) >> endobj 373 0 obj << /Type /ExtGState /OPM 1 >> endobj 374 0 obj 945 endobj 360 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./bdm-hyper.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 375 0 R /BBox [0 0 403 127] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 376 0 R >>/Font << /R8 377 0 R>> >> /Length 378 0 R /Filter /FlateDecode >> stream xœÝXM]' Ýß_Á2­4Û€ñ¶RÕuÒù¯JÚ(o‘vÑ¿ßc¾î}#Uj¤lf4‹¹|80ïkH‘Bò¿ùÿv?~ú áÓßGo ~}:¾4¾ç¿Û=üüŒá-PŽ9<<"AK”–(<ßwüÃóçã—çãýaáŒûóÖ¸¦èCî‡4ÆghɌ×ã·o˜O,GK÷õùŠÏ—bn)i Ü&“ßwÙ{žRL5Q© ±¬>é^µ[<0JN,y5Ò’cu´FV…Œ–j ¦˜‹ÉH,– š¬Q›¦UÂíÔb)%°IlVBVŠœ9ähk¡Eª-äR¢²{QL–C!§§Xï”#Ffã˜ëCŒ¡©€ˆ2"R‚H‹”J°–¢,Œ:qx©âvüÆBMk…."ÒH9ˆj‚¾LØd9I°*Q ºE©N³µKË©Äâ± )Ú2V³WjX‰æE"c¶–KLƒa­ !ÿRÕÜ„þìºR«‘p ‹Ù\8¿ih‚cÄUÁФU££òXôû¡™úš@½¥hŽ úZ‰âaC†Ÿqeƒ¯ë"LZ@êÔj‹I0G*ÜÍlÝÙÙ[q)}`syÙŸ›g Çê«_•;'òÅM îñ1)ãKCÛ·lÐŒÜÌýûLì'ä„'´×sCøfóÅ[ Œ‘`€ížJömvÙ\{›÷-nÈÓ½½±b†¾»…‘ƒP„¿Nd58!l£ÎU†3Âñ_í•ÀîãZþOŸÔG¾~¼IS—íóÜ—Ñ<†¦a7B^ÖèKÑ–¬Èt¤þîÆÞ‚oïaZOÙe ’-YX®V)Vì…¡u='>»Éå}r¾|ý•ìÎAj¹>p¾ÆåUËèáÀ½ÌË L "^%%Ÿñ‹ß?ê7`B-ÀÝöúpÖ4ÝÎ^ÄZN0|Q¾ئVÚZÍ­gÚ†«£ú>ñ*î?(6 ª… »ï…· 2éã;Á„Ë Ä÷Tˆ©Ì›~‘ûX½NŒ3…ú}~öxɉz5¶×rînµõbvÙ¨Òå!ªŸ=‚Æcg!l[GM?¬ŒRÞOãåQÊúš-üe{ñ;¬–No¹oÚ}‡½~#x>µb]…bc˜Í_^¨¢ô÷Òeš …Ûi¬C:ͰíâÕú¶, ÓÛ¨NŠ~™®aÌprÓ{“žxÝ< Õ__þ¸JÙOëÓ„¯_('˜ü±“:S<²{Ì—}; ^Í‘ƆÛÛÎ}ø6Õúõ<Ýñê-~{Oüibü$0N~Ãý~ÊÛä!b6¢©ªgÚ¶òÈöh8:]ïp^ÙÆI;£ÕB8éñBضöçí´”F¾,o•‘L ÙÀŸ öˆÉp#\ø÷½-A¢‚«Û[ü'°Qî<ê½ ,,““ôz3Ûø¹dÙ·#ë¼ö‘Î{!l{ÎÕbÜËÊ… 4îî5Dz‘|“ÅjÙ,'ÂK=\oWÜ¥ì^¿Užï¯ÜS=x¾­Uço—Þêžïˆå=ÞýR´ú6ogÑ:ÏøQµNãR¶îîY·NïGî×úûmèñ½?þEjd endstream endobj 375 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061120003656) /ModDate (D:20061120003656) /Title (hyper.fig) /Creator (fig2dev Version 3.2 Patchlevel 4) /Author (bdm@pbook \(Brendan McKay\)) >> endobj 376 0 obj << /Type /ExtGState /OPM 1 >> endobj 377 0 obj << /BaseFont /Times-Bold /Type /Font /Subtype /Type1 >> endobj 378 0 obj 1405 endobj 361 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [196.755 324.416 204.601 337.036] /Subtype /Link /A << /S /GoTo /D (figure.5) >> >> endobj 362 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [160.67 63.692 168.516 77.33] /Subtype /Link /A << /S /GoTo /D (figure.6) >> >> endobj 368 0 obj << /D [366 0 R /XYZ 72 720 null] >> endobj 359 0 obj << /D [366 0 R /XYZ 217.78 582.478 null] >> endobj 369 0 obj << /D [366 0 R /XYZ 72 547.758 null] >> endobj 370 0 obj << /D [366 0 R /XYZ 182.9 369.266 null] >> endobj 371 0 obj << /D [366 0 R /XYZ 72 175.064 null] >> endobj 365 0 obj << /Font << /F18 140 0 R /F34 144 0 R /F17 138 0 R /F47 242 0 R /F14 141 0 R /F41 161 0 R /F42 169 0 R /F39 168 0 R /F45 160 0 R >> /XObject << /Im9 345 0 R /Im10 360 0 R >> /ProcSet [ /PDF /Text ] >> endobj 385 0 obj << /Length 2386 /Filter /FlateDecode >> stream xÚÍYK“Û¸¾Ï¯Ð‘ª²`¼»—Ø•xש¤*Ùª=ìî–8#&9&){ýïÓ@ƒÉg$?¶R:„šF??4èê~EW?ÜÐÙóõíÍË7Ò¬#N)¾º½[1A çf¥'ŽÁÔnõkF׿ßþ¾ØpFTœû‹Ÿ{ù†ÙÉ׆PÍVŒ*Ò±H''t–(˜¡Hò¥4ÅÍîlOÄÖ&­F~ ‰!ă9"¥þ†KÍùm¬8¬¬®b›OÁ>ô—ˆ7µwD±–3VËÌz¯üÜÍßnoüAWlÅ %’«•†í90áöxóþ†þîŸa²ÿ"N¼|{dlõ×úæßðëÿÛôì6#~èml"­„ë•æŠP‰’}À] ·2ÄÊ<™"Z9Ð81NNt9ã&À"0s&[`¦'¼øñš &RÌ„"B‰3ðŸ33M¨µ+I„°£°›­¸ñz…% xĺ€ Vúë/Éÿü%“ŠÝ0­ˆ£fe]Ê@ù1ÁÂA[4”xJk@ W#ªËxñE^ìffÂ,íA”hPÈcfÝZ¢­ ºuOêVpv]xkª¯¿"ÿ’/[?vŸ¡ðÍóë†[ k{«RßüèMyjŠõFpéïÖ)Töc¾Ëy³ó³&+ÞŸÊk¥²üPTÛHš·øç}“?ìqªlëcÝ<ìËö8¤B¢ñ™ å…Ó¸ÿ­ýÍÑ?Nk–ueu¿†Üê²n_øÍšÚÿù±Å·ú.¥WEF%ðU²psÂè@²­›¦h<Ϭ®v‘yWãÚ8ß‹dJ-*$=Þ³¼('ýP#ø8w~õO›ì;ÿÐø0ýã{œì­&±v²Ü1© F3ãõòj—ôVP™µ³ý}»„Žj%×+Ô0Jp"¨KH5QVBª§´5««ï ðÎæâ4I-¡3œæº‘Ìemy,ysø„¯wuƒƒ„‡…ùàõ~°­§cÕ’õÆ0‘ýótèʇç.E2‘‚§kÉz³•i´Eϱðγú”„n&äî+¡Š?¯°»ŸeµAÝ ÕMu×ÍÖK´Ï«û…ÈÓ’X§çŽÉ“'žPƒ%ÆðIÉ)»}2,ao.Šw•Ï%傼bÙ¸L¼½YÝJ±‰[Ák;Œ‚Û@ žc©Ën÷ÁÃÚÈý ëÞ󮬫'»}ÞáhWüF™¬ 4cpõÌN£2ae¢LÀä1ð.à¥ðæ÷Ó}Õ€a¬ q(an&lDS›½íUÙ"Õ¡hã¨ü¡¬O-’„mÄÁijöA.ˆÊüGûúàS8 N‰SMñ‹R[@®Qšeeºæ(@ƒlˆ³×Éä!Áo†Hlq×k‹m]ípê˜wMùÇ‹ä2TKßûa!Åè¨h:½ªs±zµ£ƒšb(\Ù+ÈÛ ,å‹ü§À¢‰•œ&Æê¯,ñë4éLBâ;/÷‘°‹iš ✚žjëʇ€ÀHÛXrÖHV@¬J;51Ï~„êVÇÙÄè!:B( ]ZL2Â¥|γ(ÀÄHòk„\þdÚÜÇ#êOºæ°&~%²Ÿ‡b™O0ÂéìÕ©[2£”PÃþ,?Tc«ö–åߪ¶l»èõ]T#¶¥Ž¾Àp(u¹§y3ž¬;«S¡¾ ¡#dž›˜æàu–æZ¤NƒR®5¸ç³¨ÔØ$$HX¥ìÚâpçm"ì7ð/Lõ~4ˆ¸.Õ䇾s†0vºéâPϾg̲},9£‡§AíSMлãÚú ðãT—ðcp›¬b&GþEBÊ~¤q”²Å/òoñ 6é[*b0×É‘^M²çb½WÅãeõf…Ž"÷8”dÔ4¹žÚb‡mÂú˜ÿwÍmVà[]ÅÆÉÂ^©&â™J1g;5¿øÒÝs>–]aWݾ£’—ÀÐ-Ó>¿ïšÀÑv#Ø;úÎÛ¶î Š –y`ä ÖXg¢BÅ#é2f‰²ƒo?ú:ã5!Õð¡1½V"ÀÆ@•R¶ŸÂqÕ]âßE—T™…³é9ÿü¼P\)t–7qpÆClrµˆž‰^÷ª¨›J!&Í`°€7Ãæoö~â;þ|†7ƒKIÍ— /õ;0Rå=È¿Ý5õÑD<¬y¬ÿøa8¬‡q²‰ ùù»¾uæ€îž¥M‡H»BóST’‹ê[0˜™1œD…€“hÙ"Á oãWMqç=|ëIËcÄfM—÷à%ÌWóE»Óî½Çúç?€_•ÚAûþÎà·éÃ^Úò¾©O8ãs˜Gî1r#ôÂö[©ÿSl; ƒQ·uzGe±0‚8ápD||ÅÈÜSwŒP®û;Æ¡Ž ÿØ[v¥ú†s aH"RH‘$y»' €tñv­|ñzY¤¿êz/_¯ø¥®×ÀkV`ÂúÖ$A+Iû0²‰tplÖ^ÃŽ]vÉ;£‰g-á}BI2£â’› Ú¤#²Ë˜ñEfözf w^Æ"à Êêèqm’¡¿ù~v«Ì¦ñ'™k˜ñ§˜‰p°¼‚Ûs4’{ñ6ÚûJâzÆÄë™X¡± „tÕ"ÁU—1r8ß¶†Ê-z ãrK½À.3³~Lڬݗ4ž&¾­ÃÁ$œO«r|¯e܆E Rzß#Ŀà Ã&|ËBùRmW¬æÎ·ÔOM\uÂB…èÕ"%B.ر è¦ 1‘®øÃ×<ÃûNª”‘¯”"Ù#Àùд`m(B†uÅÒײÿZà×&Û§ò:Öm_½$‹XSØ +ÿXùÁÀ*¼ÍÊuä‚8^¸«Ùa+ÇQgmé »Ç¬†yÆÏv÷E›ÚM :Þ?‘:Vzxæñ黽¶ïöú‰»¼Ý#n€—ØÁÖ=2ÐÃU ìKQyV•¢*öÓµ}Œ<ÃÊýÁ08oÔ¿ÅN¢sJ”H°Q4&|> ¨™ÿ殪C endstream endobj 384 0 obj << /Type /Page /Contents 385 0 R /Resources 383 0 R /MediaBox [0 0 612 792] /Parent 354 0 R /Annots [ 364 0 R 381 0 R ] >> endobj 363 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./bdm-hadeq.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 389 0 R /BBox [0 0 213 87] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 390 0 R >>>> /Length 391 0 R /Filter /FlateDecode >> stream xœÝW»’Û0 ìõ¬S0Ÿà¤Îå<“sf|E’"¿$@RI©Jãâ¼w±+@>ê§qŒ£Ïøûø8>¿óþû¨æÏæÇÁWÍÛ—‚/¦Ôj>ŽÈßÌ뀌}íu|;¼‹²aìåå±Gi´ZP//¬ñu×Rj`áÝ—ÇJVbþwÓV.ú³‰¶˜çÖ¨yó cèó뽩GoR°P«§ÀÅUëMð}¡U/É™êl¨ºb£˜-:`wÑY4àéê÷O×ê=É©GZX$CÄU0 ¶ë‹dhb~•ô¥Ú¼X¼Vñ©÷=1x 55]е}1%—¶ ·®<Aš-W°1e›7,.àÑÄ ÙÓ«àbó¢ä»²€Qv0ÅÕfúAwæ1¨ÛÈEz4b¥®­Q±:S@ºcé¡|a¯ÆrÜ_ªÖûÜnÉUR<%C kg²„U Kº)åIÉáîê"%2U¢h¹% ¦MË–øŸ{u•ÔSmu!§}³ßGQpÅdš„-ÃÆâs¡À:ŠPâ:Šå¤lgNWxz¢îƒÛÁÿ³f_÷>ï9÷j©•ÁV§$¾äiËpËÑáP@Êv¦ºZM÷vÜ ?´˜m­y‰Rh4p’ NRMÅ\P¸¶˜ý™iB\Òl”ZQÜõêÂVw'ÿÜœû…zòéëœ*Ô=UÈ{*Å\Ux¶xý™*¦=UÄ=•யhT¶¸;ûçVÝ/µ*ó"¬©ÈV™> endobj 390 0 obj << /Type /ExtGState /OPM 1 >> endobj 391 0 obj 660 endobj 380 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./bdm-isot.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 392 0 R /BBox [0 0 201 197] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 393 0 R >>>> /Length 394 0 R /Filter /FlateDecode >> stream xœÝX;’7 ÍûŒÐÿ8cËG˜’dWi˯o€@²gÈ%šš­ÚƇÀ{Á&ûO<¸À?ùÿx»~þÐÜç¿.t_àþ¸†Õ}øå‚ˆÅ†äÞ.ìÁÕ=bu_®ßXö¥G!DìТ/®Añ9’!ô¥º„ÅÌ$÷ì»+Ý÷^›{PŒƒ±Í)FƒêSAW°Ó N–Ö|M.AòÉ3#=d“”LË¡ðåîc¢µŸ¢K±ûP`¤eèPae> =‡êku;úZÍ>ƒCÄ cñ Vó ÀÀ×VǤ°ÏÛÕaH®Ää{@Æ}í.Wð™¡$"Kfì±Òl,–²'%t¹Ì´¹ŽÙœi© ¨KEhæÒ(ÇRCÊ7}m¬'¼Ìø®QžÕ3Šê1Ù:8ÂÜõšõ¦ß×Í}MY¬'ƒã‰. åÖT}kÍ!©‘Ò-­˜}à*¦NTˆDÓŸê˜6^ýäölÑÄO–ƒÇ®`{/®4–`ÙG’·(Ŷ7Ï>ön^0ÈHk`¬;5ÒPœ‰ÞƒuXï={ï…Y+è(%5ý¾~¦¡é¥ÉÍ´Ë@–s!EŸëžƒæ©Ñcd—¡ ^jÜBT-©"´Ê£ÎÒ§Ÿþ¨¿3êxWÐùW)Å n<"ÚÐ!ÅâIPùqa¦~ë›åN¼:%À’)<¹›ˆ¼ÃÙèÌ;Ä ?EêzI?eÃ6Æî¸c~^‚È(I‰JÂ$µ‰4Ò §>½Ä{œn2Úä‘m‰ŠŽœ#¶qÄjÃÆxã§°—Av—)!E˜ëd„¢Æ“u@yTXÌ, m´‚æØ‡¡.óyqP›`L;‡u+ÃJaß „Ô Ål,©·hhgš‡4®°Fž —˜Ž¾žP­¯‰ôµ0Q¤iïëUŒ— Â%©tÔœgÎypQ¡ÔB±B1¨îdJ?É”z’QYr.1̓ñAFÃͯvC;FàGa^‰Î^žun2 œ”J?)©¼(©F1k“%ÇbU[–Ø3B ArÏ*/bæ¡(%ÂÇQ¬×#·mvÛ‰Wpl \ûxQÓF7xR3ÙÒšF€i®95¡ …(ãoö­ï¥hmG„ýrƒ¯ù¦SÔã5¸HéKÒÌòµÑ*[NÓ((‰`˜9ÁÆh¦_V<à÷Ëš%êdZ! ”Z¡ Èßcï§|/"=—4.Nc&þø=!Q«>îãæAs#2mé¾aÔH–¸€bo'<šŒ•íçXn‘ß2€St¤£[§ý/:z¢¿¯9Ð{jþ4QÆ‘áÙÿ_,üíÞMð®žÝ‘5±uß°ñ müAË%z÷Î úüHÀ6pÜzù›P%{Ö[q¥zeŠ07à9-ß?ê(Ÿ¢+ÅÚ GþP#Ã0eWéÅ.Yz›íÖeEÒZÏ$1ƒýþQSݼ´-qÞ»ì"÷2;§ØÍÍ2¢±sŽDXr=ŽAs…Ûèy;³ðzy³üb7xxƒì úJt¸<¿^ÿ@E_½ endstream endobj 392 0 obj << /Producer (AFPL Ghostscript 8.51) /CreationDate (D:20061119144430) /ModDate (D:20061119144430) /Title (isot.fig) /Creator (fig2dev Version 3.2 Patchlevel 4) /Author (bdm@pbook \(Brendan McKay\)) >> endobj 393 0 obj << /Type /ExtGState /OPM 1 >> endobj 394 0 obj 1170 endobj 364 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [280.676 491.783 288.522 501.48] /Subtype /Link /A << /S /GoTo /D (cite.hadamard) >> >> endobj 381 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [126.332 122.669 134.178 135.288] /Subtype /Link /A << /S /GoTo /D (figure.7) >> >> endobj 386 0 obj << /D [384 0 R /XYZ 72 720 null] >> endobj 379 0 obj << /D [384 0 R /XYZ 208.685 613.66 null] >> endobj 387 0 obj << /D [384 0 R /XYZ 72 432.713 null] >> endobj 388 0 obj << /D [384 0 R /XYZ 247.673 168.829 null] >> endobj 383 0 obj << /Font << /F47 242 0 R /F18 140 0 R /F14 141 0 R /F41 161 0 R /F39 168 0 R /F45 160 0 R /F42 169 0 R /F34 144 0 R /F17 138 0 R >> /XObject << /Im11 363 0 R /Im12 380 0 R >> /ProcSet [ /PDF /Text ] >> endobj 398 0 obj << /Length 2513 /Filter /FlateDecode >> stream xÚµYKsÛ8¾çWèHUEñ"ÁÙÚCv&™Êîd\{+[;3X¢,V(RˇÿûéF)SŽÊ³¹XØhýøú/îñâçW±ÿýÇÍ«7ï¹YpÎ2­Åâf»HÅ" ‹•^Ül¿EyµiÔ5K#"¶\)££«nÉ£]Þ,WRɨÉKÛåêäÿë‹û¥Ö‘-ój·¯q8Ú~jv$d[ú=ØÆ‚¦®>àÇGü=ÖñÞõÖ¥m´ˆŠ¶’ Ãýwëo—+ø’Sgg«M [úãæŸpÎWL©„Îã‹$j‹}QZ<LÛÚvWÔþËo8 L/ø¢A;aãÓϯ`²öŸÈz0ðÑ7ï¥Zð” ®Ú–TŠÅÜ/ÉårŹÐчªílYÕÍJâñ,.“RÀl7«²}÷8§]',‰³ 'S&S&™M³ÔØþØ êSk@­L®il¬d¬X–¤Ø`*–$ú¾hÚî5Ù®Éí†LÚírú=æªÌýŠuYÂLXïÓ»·?}|7·¨Š™á2Èuµw_žÓ:Å–`½Æ¯X´þSµ­›½íÏîë ÒäkØa¶‹#·ošÒÖIô¶tÆ€01‹ÁX+n˜NmèÆ¯Ëyd©!"K?0ÝDý•øèlèC½¥ mÝ7k?‡ÌÔÒ‡CSã¬ûb“oFv4ŠKÇ‘²”€ÏLP/8Ï»»BÓq*!ø³# cÈ7çsB+˜|)FêtHŠü«7þºkiK?ÛüeqÛX—"°™mOîmÃ&©†«h_ÜíÑ.&—?2 ¦<©ÕG-†*Lù¶ ìÊ“©ª®Vÿ®Š¯$Ü>¶]¾o `@µ¤] *|Nõ‡-yì 4úÖ¡H3<Ž ¶UYPZÒ©%)¼Ô•ÿ@ÄÖoN3‰=,|!í¨c——¥_ÇM¾Í8Ôãl²ÉŒJãÞ~Ég“ØŽ—Â;‰+V™ ª¦"a±8I.Z»q7&°£Û¯ A*’âúø› +¬eüb¨ÅÀ¹¥EÒ¨é«?{fMærN]7Å¡›­EØq:Möf]WÛâ®ofÍ…²<•ScÜÝl}(ܲÐÊ¿Ú}Ž–ÒÀ™ 'S/ÄŠºAc YÕåÔ¦c€ä3„Aä=a•»²J ×üÿF&Ê.ÛyUª2/" ÍÛ!®ž¨åÇ „L· !P j@f¸q%.Ewµ®m_–á¦} g¸‹!ŽpG‚e‚ÄÒ¯ñè²¶÷‘o«o¦€š#^<³öŠ“Z<µ×r%×@Z4¿RáÏOu<š2’àG±㯥ñØ8ô@WJlB8·9I8©PÂZ?7ˆ9ÊDÚN0I  %}7lÆøÍ`Ùr7·n{áC¹õü `ù„soÏsè ×z3$ÍsÖâ@@³Áw¡Ðº·"> Èg8)P 8²¯õˆÈT©9\g¡ã}ÁñWè 0°Éª"ÔFªrÛœHTŒåäL°c-/…Œçï´'—¬ä"ìÐ#n}îN K›KÐCe€£§ݘ»kwß×òH®ôøi :Wÿ¢_["—y\HfJrT⾆Jhlø„v!Áp#ˆå ûvîË0kgn©7ó5-1.ÙgAиŠZ¯ÔÒÏ]×pFœÞ1=JìLSGº¦îo1)1×D’E|6ñíæ¾ ¶<½Ãk¶k¿È@¸âLqqšpäsëPSG×ôtYº'Ùׄ®aQWÊ}OÀÂÓG²y”-öá bØßÀ@ÜÃy3zH«/ç€îŽ)ÇÅʯ{ô@­ë|Ó;BcD° ºHÀjh}âtô1ß„dÆÞüCp1N×gi·Î˜£„…m!Ôïóyn¨¦Íe„Þ=°¤ãw àôî;‡uæ÷° ü~Z«ýÛ)Uá²õœíKU;£xçîœï¦ä1h÷þòWçc|œ?+9y3J@,»¬ÆJ–Íø7RÞdÓ!Xú) 4èÕm8^9l%< ·‡ß§ïŽ ÑÙऻWŽ0ºžÅ¿„eÉy·þëãÛÿüŠþ7Ñßé'¾l}¯oÅáöÉÑò|~ý)ÍzfýÏè£+À–O?]øï;2 5iU|RT•aæøÖS)¼fðg 8Ò…kH¸|ÆÐº¢õ®_æH8“š|¾Ðì¬ü¿ÈÁƒ@IqÙý’3[<ç&(“IvÉŸøiôíâíÑjO·wýÝ-È“¿hÁëïjÁ‹·7¶ mï—ïnÁDýE þr©_b@ÚÝb•Æ,Kõ&]=RJE¥û_\æ£Žê ²xZ3pÔñœYWP*]ëÖ]Q¼Â¾ElAI¤8âéGC½@ûIfü†Û’@^¸²5û@“°ôh–¾j‹»Êÿ¿nq Žg¦oeî|'o8@OȬg52NŸ¬|W‘ZÇ|Ï-Àaz"‡é“wU_ùÚðÞæº‰ZÝÝðÖ†Ïïðrò¯çD2…%G{1þÂ)ÌDæÝÍ«?Û*ïÝ endstream endobj 397 0 obj << /Type /Page /Contents 398 0 R /Resources 396 0 R /MediaBox [0 0 612 792] /Parent 354 0 R /Annots [ 382 0 R ] >> endobj 382 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [166.407 692.603 174.253 702.3] /Subtype /Link /A << /S /GoTo /D (cite.latin) >> >> endobj 399 0 obj << /D [397 0 R /XYZ 72 720 null] >> endobj 58 0 obj << /D [397 0 R /XYZ 72 672.63 null] >> endobj 396 0 obj << /Font << /F18 140 0 R /F34 144 0 R /F60 323 0 R /F38 159 0 R /F41 161 0 R >> /ProcSet [ /PDF /Text ] >> endobj 405 0 obj << /Length 2648 /Filter /FlateDecode >> stream xÚÅZKsã6¾ûWèHWH0[9Ljç±[›ªlâœfçS°Ä˜ )ÅãìŸßn4À‡†¶åŒ“½ˆM<Ý_¿@±ÕvÅVï.˜~uñÍ[®WœÇ¹Rbuu³Òy¬T¾Ê˜Ž™T««ÍêCtµ³½\'" YÔ·µo:Øþ@Ô—•íi@ÙÕqsÉ#» ~üÎOÜ›âÚo/•ŒÌÖÆ—k™¨èêR‹¨¥)ÝqœÓÛWDÿz¤ý²èØÛËWÿüæm2;gq¦³ÕšËXÊ”ŽP›[ØUq;[W·=MŸ~-tœÀœÙÜ»]éÝÑþý®=V¢›Ö³²ï€exnŽETƒsîé¥=öÇC8‹ñ“*šÓÞöÔS•·8g\À²]×vÔTÛ¾w’¢SËÏbÁ•DÖÙj-eÌ'¦¹¼\s.Tô´’¥mŠûË\FñÒ±anÂbÉ’AßÀ˜ÎPìmgea*j¸CþÚ®?¬ ÓûAv²khoFþÆ=c€¬ör{4ä‘pÐ?IÉÃв÷}Þ“¼ëd{(M˜¹ŠvÆA=@×oNŽj»öŠ@ú‡òßÌïæ¶¤–ÈX[ñU‡fÄOï.`ãÔw‘±@ÃG'=@ 0˜r5‡É{·³“…ý5(¸¡zÄk=Š_³eØSÙÑõïL·¡ÖCKO´°fC½¦ñ7@Ôí°reúamЇ{n;³ßõKº‘‚Åœ§›u<;üµÓŒÝ™QúÔÆ?Ëï¼”ÞOxV÷M[ƒBI€kôBk®c•zT¾wNH*åeŒ´Œ¶åoÛò^ÉQ¦ÞWž¶Ÿmq›?”mC-‡²FþtÒCÂÐãGZŽGcÇšÚÿáøÄ_¿¸w0úÌrXå@ONwïE˜Ž4‘Ú±/›-ˆ!åytWvÔts¬*¢Ú=0\ö€^Pòqjmì9V‡qhÛôôB!ÎÕêè6˜…[¾íjê=6àµý”áwW’gEÇ0å·'eÙ¢D ÚÍ‚²$|뼸åL7›¶&ÚƒÐÑþ¨@ÙÍÖ៣L¯ÍuYLœÕZ! ÅyƸs$€?Æ“•Œ3–ygç õÍÕŧ î-8aÈ2±R\ÄY–­ŠúâÃG¶Ú@'+–™^ݹ¡5,$ÀتZý|ñoЉ³ ‡¥˜ŠÓÔ‹B,Ù†Š%òÅ… A¨«LÀºCJB$¾zD"yäV€a·õANòYÓI a/Xì7@*•„!èa%8¯<9q^† âÔÒfIË\œl6“QçZÃÑNÈGÇ)Hz=Ö˜¦ímÑ6ï&&hj6š' Æá¼åñÖŠKÅèí¢´ŽDðžQ69Ë£×ÿúùÍ«i}ŠÂÅÒésòJŸ:}ögžÍ4N&¥©ÂÕOˆÊ_Þ`ÚiÅü\èq@B2ƒfž€Ûm ßéÝüÁG:4„b×ã24šæ¡Œ­ÊaUÌÑö%µzË<Èt–Àª¦r!` +Úñ Ö!Qèlué%ÄCN°¡×ãŸbÈÜäßµóïÔ‚¡Ôõ¸v `ÅèŠq™aªß¸+í8séè°%†£o0c>f¸è| (I èâað€ŠÅ…‹t0)ÀA£ß|.ì~©Š3~éÉ;W£¸ÛÝÓ[_ƒz ¬…SfiœæÙ£ú%ÿÁ·)y5Öt•_Þ¸PÄK€b Иyè(äØÒ6aò¦ì Hc}»ýt,àïxTù–½é¥3%·3T#þ7$ð³©>ñ–`¤®üÀÑìdkl½ÿVbÎŒ/Lµ(œ¶Ûïʾ¦Æm×÷=È<Õiô:ˆí$cN`K}fÆ ±W &¾¡¼Äz±òrlíJßBÙ»7Z ©&¢³.É´µ‡°Ïx³$fì$}i}:ÐÇÀƒÝ´U5I„7¯†ìo­CT"žíÕÁޱà;Ú!ø³WäʯQ'÷D»³áp>ÐÙª¢ü ‹3oÍlÝI|–!6…zj–…:?™°4’iÂ4‘Þö3,±>D{€Ó€E6A*Ð.Çg·q‰> £g‡ØìüȲ%Qu Üö®lõ¡­ŠR\¬¡ç$ÿîÖ'ž…x9•]g‡´n´ȈQ‘…‚×ÅJ½:ŽýK:M!1‘ÏÔ2Ö:™8#HS¢×¾žžŠ¨ {“ÔŽKzlmƒÀ„jË—ÑA^„g‰Ñ‚ŸH%ÜrÜ´ÇÜ„Ú{¸¶pö<3¶c~(~ Ã2 å½+Ï€r¬g Ø´ äÚ˜]ú§+p´ XøÒ?@­Øúvw»K>RÎê…rv­ øÅ×°Ì.lÛ´3”LØ@‚Q#xÀqQ ð0̆ru”_<TÃÞ‡Œá± ˆ+çòe]Å·3œF-À‹Sáî„”Hƒ*¿Ìþ4d¦ â,÷NB¨åü/OáLã°ÿ.Kë1iÿ~q; <½>ÂûdÜ·'XËœ›aŒ¦¹ò{”þíqÙH' 3HÝDöÙ(ö ³ù”YCøtgH˜²”?O>çnù|@:"ŸI'Üw*†âKýÅàØ— õ¹˜†‡5X©KÐv¥#ì)ÜEåmªf‰œ…„Õ§£Ù,Þ^‚‰01ÈÆø‹–ʽràš?¡Ý$cSɹêÅŠFO*q¼6Èb‘Ë'ᙯ ÿUé“âg.Ô>$æåKkʾDÈAš›_8~û€àµÈ_Bð)¨=Ïæ‚_9tçé—‚_ƒÇ‚JïLéës¤ÏÈ?ýÿH_ýõÒÏݵ.J_?Ç«%/åñÿ¾¨ìŒçglw¶G %Ò|Ô¾8B¯Së—tP+¶ÿ!µê™Z‹ªüt´ýŸòl÷tSˆ»î±ÌìL å\G-’Ÿ$î[Èü†ä+À r¨Žÿ”øêpÃrªÎÙãK08´·/:½bô7A1ÙL1ú!ŤP‰eç(/¢æzÁM÷£RðUáC£üI9.NçÊy!¥œ™ˆ¯Ë‘”;Q6º5’Òû¬sÐÈp7õ峕"Ós•’ä§ZÑs­èÈŸaª•”‰?E+ç™J&þR·™}e*Ð :E)&N^˜@ Éç]Á_Bû‰¿tPOùK•Âq†ú3¿î¸¯–A 2ˆƒc²ßW¥û {£Dv&ÊÅf§\Û‘È´—ÎË«PôN¿V8fyTÖö˹·¡$ö•ìäœáŸø‘în\³ÿ4­°Ë¦<¸ë3÷‘|vcŸ¥¦õuÝ6[ª­s¿ ák( e6ðL•64Ý6T‚6ô:Þy(ts]†”©¶m|ºº7OðÓ<64•>X¹«ÆéäñbzV‡›{ÿ‘öe]V¦£Å†z·“ß…YTr ùyt]Ò•¥ ÜcPôŸÕึ+‡àީ޾¾±è½Ád˜ÚXfQm ¯*,]^ŒˆÇol9O¢bÎ=ÓPM½¹ºøx…à endstream endobj 404 0 obj << /Type /Page /Contents 405 0 R /Resources 403 0 R /MediaBox [0 0 612 792] /Parent 354 0 R /Annots [ 401 0 R 402 0 R ] >> endobj 401 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [512.191 603.703 520.036 613.4] /Subtype /Link /A << /S /GoTo /D (cite.miyazaki) >> >> endobj 402 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [339.923 356.098 347.769 365.795] /Subtype /Link /A << /S /GoTo /D (cite.mathon) >> >> endobj 406 0 obj << /D [404 0 R /XYZ 72 720 null] >> endobj 62 0 obj << /D [404 0 R /XYZ 72 658.813 null] >> endobj 403 0 obj << /Font << /F18 140 0 R /F38 159 0 R /F34 144 0 R /F39 168 0 R /F41 161 0 R /F17 138 0 R >> /ProcSet [ /PDF /Text ] >> endobj 415 0 obj << /Length 3234 /Filter /FlateDecode >> stream xÚ­[Ks㸾ϯPr¢«,ïGmía“ÊæyIen»{àH´ÍD=¤4üút MB-[¼X âk4º?4À6]=®èê/hüýãÇø™ÙcÄ)ÅWV†¯ µ„Jµú¸]ýRü|gyÑ´wkAuQ}+÷Ï»êž-ºf_a½*š‡Ð~|ªºXõØ–ÏO]¨ná×ݱB‡â—;nŠª=Ö›ª /´ÕçSÝV¡yß´qœãSßVá§«6Ía_:6¡ò¹…Œ£uä魙$Rê0¿6øÕ£¶lœçÅ×úøJ =X;«oëú€¯|¹S²(ÛD–#€ÞÌXoÌ2¢¸\·¹S´¨vwkøÙ}>• pxi¢lé èúwÊçç]]mƒ å1üª]x<Óhî{©ë.¶Õû8¾¦­¶§M?"è ³æ‚iõT?;PvÓ½Â…Š ð Ufˆ×Ì¥exõ'\^<”ûz÷Ë,Ú/ºcÛwß×mõxÚ•mh}1AûPbJ…æÔ4xQ¶¡éØÖ_êrkOÇìäæ¿ïnNÏa’ƒ 8ÇhÊ/&eA‰AS”bdPPåêCjzqÆÆ zc0Å1ô"úq) ¥Ñ¸bWF+ ¿ÙÊ«.·ÿ9bÿÇœq)F xs4®_©¢àÆ9ËuÄR1î®þ|ª²Ö*ÑT÷ÃŒ$8ásÙ–ûêXµáQ ÅÁ¢%ø(Z4VŽ,¹[kÃÑŒð±«ÁŒÊ8ToSX~Ác”›¸Ê 8ÞT)Sû‘|D-Ì™kj¡‘PR\&lŒ PÂåÇ^¯/?ööËÝ¡fX}¬}Ö¯>F«Ÿã«¼ö¡Ð°¯ÂâÖ°Kzq$‹³fNÚ)•ý3'¹!N«ñçÆ“ ±Ó?¢²¾k(ÃaKZy¸¨vAshÐôjÔ-.´‘[ µ~ñ¬Å®>TžüC7¿pð»ip5Uxò~€²3‘Ð}uWÿ/vôw±¹úVmN^q¾!îI8J^Ük›žäS'C…¡`3,¸ƒ_!ŠÇêPµå±i»Èb"r;‚óB­»ÿ«­ŽˆŽu8›i'¶Þœ> 5¨N¥(Æ£Æ9£$qÎXíçœ!Ëît÷@Æ÷’Ò‚猕DƒØÆ'ûx»³è”0a ÀÑœ§½ D1`?â̸´E÷\n|ÑÕ¯”éM]6ßCª!öi»Ø ½'Ôb`‚¿¨ð㣧 ¬Q–`lÔNÐï6Ôõ¸¢~èûGY¼óœöø7êº âŠ-0ÿæ#ÇQÕö±ŠÁOœLeüÈaq÷GÒÄY þ&DÔÏû£`–£n?fÙ›X5ìÑ‚ßG}ÆÀäýVïËc[%ë‘AQ@æêWP0´Xô}|˜¬¡`1œ‡†~ ±Œ´¯„¯&ø-wC™ýò_:µÏmÝÕ÷¡8¾Ýö‹VÜ‹ðT€‡ð.:JÝÃ=\êB8%bT‰Eăª ?Ä¢ðŸp÷Ù”è!]èv¨<”`á¿Ñ,ÃCÙu`}—ú°…Øs{*w>È…×?Ž÷¡TÆËÐøñ) uª·p\Êøð [à±8S(yÉI´ºä¬‡­)-3œšö…$º†¡¿>U‡P º„B‚¡”±r Ü]Uc9mï'þÝ2ŽÒD‘!èò¡:669á¥Ä±!zÙæ„ׄÚazA‘¸š„»„ËËͦi·`uÑm›àÈ•°"áC³Û…á¥[ùiWy‡ÎÄýïŸ?~øü…£+Ú@`§Á›™ `y›ý‡_~£«-´ÁÂÐÄê«ï¹_q%!œFbØ­þýá_™1 7ôsƒ@÷0µ0†?¦' o ÐARA˜°£åOw02èø ‰%9M¸uSÐfLQ9¨ÉÁÙcTÎ0$™‚2šC•Âl—A…ÀZo&sÍÁ±¤˜Êس™f0µ·ØRñB!ÕÙTs¸ b$“epAņñóù怭Ä÷§p‚ŸO8 g5ÂÌ{€óž¯é­ôaÁ·ôíìaŽeIåˆ/°Ç»0Sòp„35Å”3ܱ&çÊßmL0õ s,©8¼1…dúm,ža›r9à € G¬Ô€´š!Œ%@•‚`'± FÝ [, ›ž±*ÕïU¼5ïäF³·0EFtë|¼,”ÅŠ’ÿ YŽÆ’¨È·adQxê/+°üX=á³ëGiC¡…Ór³åÍ Ç©7ñÝxí‹e8ƒßþʳ9Å<òv±sÏ›P‰÷—o»2FË»]¹ô+rr§úûññN÷w8æ% •ûP:u1@ìCb|õÚ 9n4Ñê%ª­»cyŸºŒ¥:E(:’äÄI3·à‚(›.·™Z*l/Vú±ŒŒÛZ—½ dŠ0&^¿¼»"4† 0a€8a°43ÔžÛÚú! ]±[c0­Áè¡Î‚B/ÆÂ {ÿ;AujF(PNsª‚ƒ>[•C‡¶3F͆ãRa–BÕ4±d®ùxÜ"ÙB°ǹN'›Q9QÎ-«^‡§“½¡*!‚…ÀKIy6ÛÜ®ƒÇ#­—Á•0¹÷BH.5~|Y XÃ¥eêAY`E9‘ô=ÀYÊóC¼ÆZÜqO8·…"¸ …€5lÕ¡«.3×2Àïø˜à.¿ì»Ë¶>‡‰sˆ'ø°¼—á{2[^iâh¢w¦gÐ#§-‚Ž9×&|_™Ú–AWx—%tz<ÜÛÁÏÉê¦1"ïÜ2FO!·Œ1òÿùÀíUÓ¸åêV­“qâ°ñ%óe Y¹§12¯ %ð 㳫(dx8•r“ÀkB¯à%àUÊTù\¾Î!‹ cxÄmª{þ:‰,‚®çhŒîôEð}Þ žaŸÆØç†1FÜ¡¹¾‰~4=-»•~`q8X¨Î“XfXh$t`z*…S™¸‚†–€ êR˜º‚‡ÁÇ{Gy†/ÙD´¾ ‚›àCtu~`¢Eà¥%Ê$ëÏçÐ{&ZÏkp(ž û\°×¨h t)¨ÿV5E¿É ¶¸aþÖiºîæ"ø@~oÏ2—™"!¿Ë—¤\hÂ{ñ:4ǧp Æûl³ð’Íøèâ‡<ɤà1~ý½©-ü‡vxü„¼øý%ë8óqœ;M”4×_oë=ëæà¿ºÃÈCöQH;Å×§>I-¤Dá%¾MnSKŸ'©L1¤ìâCsÇŠ‡PŒi¹d¼Uœ—ŠJ¹!± Æ|%äFj³f>ÉŒé%âGÌ»¦C eåpüô'Çi9yAñ×™äå$y¥ v”ÿ%g êBž–rèLpO:çðiVUz‚~цd¾ßÝ­™6¹[[ð¼?5ûça-£Á’kt6M¡ÉåE4Ó,±—\æx{žÍEq>™[®/G«ÄòÓ†[÷L:P¼ž¿&SX:¹~#FˆÙ u8ü+Ÿëyö¦Äpа½ñF¶9 Z0šHÎ/k5`™°¿31_‹Ì8Å=ŸG"ˆšåÌ8 &¨<÷à–!B…U”2Í}W•8*uø•%¨™¯¼‚KÂøB¨ô†Ÿü¦¨6ƒ {2sf!T—AåÙïŸ8×…–UJéýwŠš1& ' ú.¿Éù;LÕºICÇJy;ip8Xã—%efò»zÖxh kÑÒ–gˆc \»7~ZŸàJêô u,‚+£q™†“Á },l-ØY¬•s ²°€“£ 0„Ñpzža‘EÁM™IÖ˜mÁ¡m†J–€ÆãQ2e8~A­œa“7牀Îg‹^Á&@·º5 5ú…(\ Ljî2£,l,˜™SBù ŸÜŽŠ dÊ©3T3Ã&  âM(l? ªd3T²*œ©Hæ £ÏÐÈí C2U3²¦gÌ’¹æ¸SŠsL¦¹a7‚æÝ¿…1fþ•¿L9†©ˆ–Oþ—k|tú?šx×; endstream endobj 414 0 obj << /Type /Page /Contents 415 0 R /Resources 413 0 R /MediaBox [0 0 612 792] /Parent 354 0 R >> endobj 416 0 obj << /D [414 0 R /XYZ 72 720 null] >> endobj 413 0 obj << /Font << /F18 140 0 R /F17 138 0 R /F34 144 0 R /F41 161 0 R /F39 168 0 R /F42 169 0 R >> /ProcSet [ /PDF /Text ] >> endobj 419 0 obj << /Length 2841 /Filter /FlateDecode >> stream xÚµZY“Û¸~Ÿ_¡Ø© §ÊÂàÚ9j²ñºœdSŽw’—õV-‡‚$®yhIjÆóïÓx òÈy ÐènôñusüÕnå¯Þ]ùæ÷¯wW7ßáŠ'Lð(\ÝmW‰X%¾d~­î6«Ÿ<]ÿ|÷÷›ïcº*, " ¡×lÚë(õþÉ6uvìiËœ°ŒYÄv —p–F‘À%k."$|µ|ú¥®¦T¹œn‰–†ÜR-ºëu†^†?‘×Õ¡T4uh›]›U4xÜùµH¼= ó¬¦<‰ž`íaß™¬6“ê‹Ê½r±.RàxÔˆf7àÞ“‹ç €¥É¨‰u(Sï}OgæÐ¦.Ÿ¬0@T"&yJ YÆ´ù¥P-¬ÊXTE_Ð$M5zÕn³ÜL=ýžž¶êÑ×ÙâaýëRu=›F öZò]àL‚KC™vܺà‰ö>£ïß»n” w–S0¡l±¹$»Ä#œÅ¾ÀènyÐö&Gø)àή/htjײŠîPšBWë˺çžÁ‘Påû¦ˆ+¶óZ .K;@ð©ÈË Àe¥q«îˆRIЖÐ:¢¾v©tq³îð‘NaÛk<²éFK"L²á ÙNÑÙ¾3²ð™õÄ\]\·Mf;:S„ç.©Ïí6 Bm·ÿ1&† ÃÁ`bC/Úˆ2C¾*UÞ«eXÐéLWP.èâûLŒuܦصœ 4À/.|BQ_6sÒw˜¬ÕÀGc«rÛðÁ=öËÁ»kK85ŒoŠä0:€¤Óè …b£Ö—^>æáRÙvÇpQ 2Ìj‚M’[©­mL}Rû — 2}1‡4‹M.óˆgæá”{zýFì7K]Ôy«ª‰_ ˆ`5Ö_p4!³›\Tå°¨©¬1è"bQ½d_ìö;Z·”•ÆT”¹r ]ß.×ÄË׫¢2½Ôo¼• ”&¿õþþr¹ÕNBñœ‘Z¡šokŽí¹âþÌ=c¿ú›¸fs}áš`ö»Ë­yW7íÒ‡[ÕÍÒQbÛÐÚüuë[ÛÀíËe}õ<|ØóÑßZ'àX=øÞnÐÝD`¤Ä‡³ˆ/‰™H/ïO [ûë"]“n¦¹§)'tfq«luY¥ŸàŒöùÙšs-v‘LòäÞçí{¤g’SãAŠßõHël6øáä6±a¥bω;8Öš3ož¯Z>ª±ë„Æb?iÀÃÙëL#°˜èr¯£&þ'u ý‹³ëNév! ÔPá¬j > (šÃ'*•z]Ñ[–ñy»Ü—,I‡ûÞºŽX:‚eg»1brËoÜ4D8°Î/ 1WÆ8Jè]<à©pñïŸô0}ßíEš.˜™Ó™1³{V)æÂÇ´µ}*¨ÆǺ'¾ø(§‹‚{`PK#ý¯ð;)ÉpH©ÿ…e’œõÌ@Çf<úbK¢Ù×*p‡ý:ƒ›2šêTE“Õ6?}ðÃ5ŽoÝìS*¸ ãÇìáO H-æaÑÛ»«ÿ£wýe endstream endobj 418 0 obj << /Type /Page /Contents 419 0 R /Resources 417 0 R /MediaBox [0 0 612 792] /Parent 421 0 R /Annots [ 408 0 R 409 0 R 410 0 R 411 0 R 412 0 R ] >> endobj 408 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [137.424 630.32 360.886 644.267] /Subtype/Link/A<> >> endobj 409 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [197.077 615.874 464.037 629.821] /Subtype/Link/A<> >> endobj 410 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [127.496 601.428 394.456 615.376] /Subtype/Link/A<> >> endobj 411 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [124.092 586.982 267.579 600.93] /Subtype/Link/A<> >> endobj 412 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [268.12 572.536 503.886 586.484] /Subtype/Link/A<> >> endobj 420 0 obj << /D [418 0 R /XYZ 72 720 null] >> endobj 66 0 obj << /D [418 0 R /XYZ 72 720 null] >> endobj 417 0 obj << /Font << /F34 144 0 R /F60 323 0 R /F18 140 0 R /F38 159 0 R /F45 160 0 R /F41 161 0 R /F17 138 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 425 0 obj << /Length 3449 /Filter /FlateDecode >> stream xÚµZK“ܶ¾ï¯˜Rœ*n¼KoÒŽœŠÙe_’È{IÉ:pg0;t8äšähå*ÿøt£¾Dάå2‚ ÐèÇ× Ùv4ewÈ;ZæTµÈhÙm¦éx ýï®ó»bk=e΂ñãªöߦŒÝEåTƒEßWmgóÝ )0<æšO58Ç‘iÔžîšüv ŽmÝ4ÖTW»¢z ~Ôl)Œ‡èx@¢Ð]=‚qpÑÒ›}ÝÞ@_î`:ûXæ8t ÀPÒ´gíÃkuœˆ`ãFgÑ÷ûJ·w‘Â<ìÝ#á¶>B1Rv•ôû©¨{EäÐfYV½}½¨c½½¡ùH«>\§gð‘‹;ACcgKKF_$UتJRoþ0æ¬ùsØÂÙEûgNCû'äcW©ž*h‡ííLtÈQU½:¸žºpcêÊ£ÔÖ–å "dÎYMáç%*ý@Oåk[æ÷d8¥§çà—G•>,±#S±ò¬ZÅŠ r¿ÓÔ¥>Nלç^.È‘ÀÁ½,V(”fpWý<‰å\ïž¶Y”»€•õS,.b 4Ós˜ë» D³Aç!‘Ó”«WwW¿\1o²†Ç4Gñ4†ì`{¼zó6ÙìàÕ  "K7Onàq#@)ñ£róãÕ¿Î¥K8•Rl€£H£i!$²„*ÒÅUìÞ†ÔŠAî'IJ~åeé“èØ"Þ9ÞøÀëAƒ¼ªgã}†sµ*Šëæ !1hýÿ$hý8ƒ.œ+ÉôYo¦27t‰u—#±;gºñ×—f°± 5@Î#—c¥´h*á´¹ÿ¯½+êSKæp L¹ T¼»V“–'ÿˆrtÿCHNa¼Ap*iÚ+)D“ÞTÝa‰PPdÒ±B; îRö„"ê,1ðð3øÊ·ÛúÔ#¦J…ßòÛ¶ŽN­ƒ-èu¶cô8Ø& ï¼£6ÁuáðêñäçæÃÂàZ0zšZ#°§Ç£ ÖkEÚZ]&"Í!iW›Ì²}Ÿñ"8ÕJ9‘r…ºÂåhððó©í¨ÕÖGßçÌS©`Ö* „Ã^ÒNôb›WÔ8µvöÍj•N`²×Ø¿c¡B¿¾2ÒÐ '&Æf%:ìñÖóãÖå³çæ!½œU.>Š?’x†ç{à9>í{D¦|æ‰ÄÒŸS?Ç`žÏRùa@Áú`ƒt’ƒ·Z5|ø|¨Õ|öÙå²Þ šÚù%øwzà¼úÄ}qʵ‹ew­s›Ì4޵U~_ZÿÐ#¨£¸¦ Ú|ÃèMN>MÅ14¶ã*Áap@D£cÃgá–ÍÛ¢t)A‚ÕŒ®¦dTº£Î’âæKòõ«6 h¦‡ Æ×•}r¤Å;œM1 çÎ6n¿^®€ÅÛ´ðS ’2Ùÿ‚v*Rç—ªÁP¯`Ÿñ°À­…AØ1Âñ¶ÖfäÙÔ9¸¡CQÚógCBuðÏ×à2j扈…èâzѺLª[öML꘧3çôî²sú{ÑBìsK)B•P„Ú/ÿ×{ê´yÈð)`}OÏõ~r²p&‘æJÞ³Šo¥†øvˆóAwZ F'–ø’r¤ÖÓŸ pÈÞ6ÏYN]¿S—o4>²ØõÇa.Y÷c†ÛaQM‹šñ¢lËÂYÖ'HÃÚ¿_Ã>ŽÿoþGèoŸ#Sp ƒLyêËЙ7÷E×äÈ|ÙøH6*¤¦ãôeù°ÉÏï€ÍÓ#gäõU¤ŽºÊõ[.\„(ê6lˆÍ±IŠ‘‚Ÿ×³(3Ì)u¶*NŽuñ›~»ÌM`MªEôoç˜N4¹K«±áÒjl§„F~ߨwÁÍ(™)Bj dê±þýb ÅN/Ì2!öוí )Ì ¢iï\ì˜î&¯– Êzé½ÿŠÄý~å4GÉž·Ÿ¯œÏ@3.„L•gx2ôN/ïI€)3ºiºýµ¢ZŽ¿eÆ™L§ 2˵\ÅÛ'Wù1éöÕnª"QÙ›Þ ¸ïáeßã|Ñø.Wbò$V÷eÛ×$¦u¸½¢»Z‹Ö¤Ì¸z°Rf”²Ky«H²Ñ.nÒˆ%7=ÁÕùØb°tÈÒ÷/߈/ å¿Qž‘Üð·ÏŽ’!4† ¬hvÝ'“áƒ35»ñF,ž­Æ,Qg¯©˜G«‹F:AÿËs¨O0‡þs?BÎø1ÀðÏËP¡e/ÒäÐÁ?ìБ~‚9²·køCŦgãÅGÞë™+à_ãS‡£¿SB½u¸’cm Ì“"&ü•­O¦1ÂÐldÚetpìéŸÀC {[øsA,n5E>^s×ÂJ±:4t7÷4¾èêdZù¨=!>ZWc³;ØåªX³èùñ§•+EÃu7_˜Ç̺Œ¿Ä‚K²±=“ÃC¡Ig7®>†Ô¿:À}äÃ}|˜ˆÀP•}¸G¤y¬ð ¥ü Á'c çþ/+ Ý endstream endobj 424 0 obj << /Type /Page /Contents 425 0 R /Resources 423 0 R /MediaBox [0 0 612 792] /Parent 421 0 R /Annots [ 422 0 R ] >> endobj 422 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [359.749 593.574 367.594 603.271] /Subtype /Link /A << /S /GoTo /D (cite.mathon) >> >> endobj 426 0 obj << /D [424 0 R /XYZ 72 720 null] >> endobj 423 0 obj << /Font << /F18 140 0 R /F41 161 0 R /F38 159 0 R /F17 138 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 433 0 obj << /Length 3285 /Filter /FlateDecode >> stream xÚµZ[¯ã¶~?¿ÂhTF^E)AÒÅ&H[$éîi"›­Íc«+K®$ïÙí¯ï ‡”E­|bÉ‹%’#^æöÍ ÍVû[}{Çüó/w_|Ãóçi¡µX=<®8ãižç+Ãò”)½zØ­~JÚÓz#Lb»r¨Ú&]o4´v½‘Ú$oWkž4eMíSÙ Ró-}»m¶_ÿüð×/¾Q|º¢`*Í€ ¹µÞ0ɉ,Þ˜IYV¢ùü‡r-òä}Õž;ê?B‡I>FD~¤u­]…»·»@¨³d€¹Ý6d´Àœ`ÃUªTFûùÛÒŽ9K™VaËpþcÙìîav‘%oϽ4­{™¬-®®Í¥NÅ… ïn^4EJر֩4&ÞúáêJ'áyîí㹦÷Ƕ£—lw¬šªÙc‡Jž¶éGËÆOÑà)Þ¯µJÊ®¥(]Ç/`çÒn‡êýš­TÒÃiÑö\—0‹Ùwåé@gañ!¾oXWz†~D]hÏÔh¬“1´ôìl?´¥ááà?Ÿê.ЉTfÀ}>¹ÍÚ&|îm¢hf˜fì=«¥LUQ€¶°T 4[³ðãÔ{%xÊQyª3E/HZ=­ðt¨¶¸äš0yù¶®ú-†ÜrÝJŠß}{­;+»{ùp÷ß;Œb+¾Ê‹Tëb• FmVÛãÝO?³ÕÆ€•©2ùêÉQWB±TH ïõêõÝ?–\„Ej ³éìÖ䢭hã(£S~¥¹þ°´(¼ ÿìû3½šô~¶¨äyªt”üå…3J§‹øl»j_¹÷Œ” ;IãºÁ~ vƒJr>®Åè:Ðpp/¦ðî©vö±<ƒÖµQ‘ñÉ<áMý‘jÚfÓØ}9ê¶Ó¾+˜w©d#õÙ´(p™ƒÅXz ÞöX  \°†ÊŠä뺦QÒU »hNçaÓž‡“s&0ÔA”¡§q°ãõ{ßB"R‘,áÝXÙ”0•äv&w“f¤ÀÑ…ùÜe Ùu¶Ü¹9¦ÛÈL¦¹œyR0Kü-2;cp^Çn]\xNT2±ïQzh‘Dמ÷¢$? @ɉÆ}M¢¯¶È üÂ1‡ÊÚ7…_ÌÍk²‡»öH3°Eo„†NФÌDЮ¹÷ŠÑP&UŽúT9iam¾¥‰Höuû vÁÎ7i‘¸P5‹ü"ÍØH|4Xh ‡pH“”J¹?¨Ë·kÍ[ƒàṿ¢!ùe „:-½ËƒcЉѦúmWyÖî¼×„=j0숛•÷¸¯1À1£s#¯Öí½{{õíÝê'給øSp¸Ÿ:§Â:±oú|‘sDéõ*‡È5I_‚v!3?PׂzÂXpNnŽ–žOºð­rOESöÔùŸsï‡ýlŸî¢.ûaé°2ã€C዇D„È—ãiÀ!›žÀè!ü«IILbr4ÄÛÅüôûˆYªè|Ðv/ˆ ©(F{j»w}õ?»´Š2?É©`u¬”IylÏ!ƶ.¬ÚŸÊ­ßÀ©k)kÙ\+'Â%lÍÁ;Šìf¬æ£Á;,ÁU}Ä‹;í±í6!\•iffêqà=¢˜E²+‡ãîƒ"a$äVª£Ÿ\Ç„±ø‹ö¡{¦8˜o5ó ‘Ã6šQ“ Ã¥‚.NçGûòh#ÈõÞ¨ì/™“Ó·ÉîpãRãÆ;ûG¯Í5XLmƒ;*ûðSv`BhÑQ "©0}ðaSy“Bÿé—‘å»}ÓvðÁ~D½0£^ˆ`ÚnqÒ©®ì}ùT >1xÃ¥ZL ‘ÊbÌ 7KÛÉR®G¥ùÕ³ 0+PÌèp»ûÍnQ ³´¸¨!™ `ϸTÁäc8º«ö.Ø€´oÑôàUf‘’Ãä¯7ÿ|‰-îó$–|³æ ‚è¿¿~yOÓ@ÓÇdà«r‘8öËäßëœûô‘%­Î½ß~Oçà§±ƒ–æÉ¸¼hõêÑ»_™w1˼?"%­àï3;í'ÃŒ›Le©fR_Ùxòý2ž‚Ǽѓˆp‰¶sþÀdL²O>Ñ$ŽùaŸt‡=þ­¦êI{ê/Æv=B‰öØ¡'ÌpÄÀ³‹YJôâP6{!IC1>)ØÆ·‰`g“™ÎMí²îýȶ»í=µÛŸ ÇY`©drcþ,O9K5Ï#¦=-pQǹ™¸9ò¯\º<’ðY%n_>b¡!O0dsA³ h†9œß'5‘9Tè©ãz`kÊQ0­*$<3ôÈౄV:5rÎmðôµuû5®žì}¾¤tÙ¬¤âC¡(¿ò¯X+žRÍ#f²[2Î_¯à§ûÍéFWìÙ¸3O¥•…ð®l_•‹˜™¬Öæáô“<“+9³™zcÇs.-ÿNº”¨ÛÎg,„PòF¯!;SóíbVCž R®fјOaµÓÛm`ưÅïÊÔ;iˆ½p2†8çà29ÝV½7å{*S EžrÁ©Jy¹(äzј]\ED–JLí=ÌŽºK?\Ò£®B-ÞçXÊç—"*ш•T˜s9-Õi–™ù>e1¡ÛàÍD„ ÍEN”|qI–­{$ÿ]V‹«ŠÔ¨|ºêÜá¸ÖÒV‡Ðž¯Tïe\ݤ¢ð¼l^pä×ÙXJVŠ£¦u‹ù’àBåL,ÑÁ‘5 ©)ä3ÌVÎcN¨¾ŠÎÍ‚)˜Œæ׿” sÆœô¯¨s‰¯/æ£åš+9JŸ®9¸¿9Â_¬vàJ·!‚=.fšEjøó™&èÞÅuâ"ýaô-°=CÖ…ðÆüª°öãïS%Ô¾â$u\.Ô¾€Ýס„ƒâÛO¯c…ÔiÎ3‘©œßÇÊâr‹q”™ÝÆš ÇXœK«šŸ\qn¦£àYò5mzSE']CL½Ô\>»¢Ò\Ê2Wã3H ŠâÖ´-WqÞ ¤ªŽrGÂj¶®¾(3æþgAáëå,½³B»÷@|ï«£õ¾,;8„>Úº÷ÅÞCH†²ÛSyHÜyÝ«»¹Âa049xoO‹‚ÉQ»³_úk‡ÒÅ$N¤ÐÁ/F•eàT$½-»ñâ :kÃ…ÐG€O¡*n¸h"ýITk_pƒ÷’Gª8ÃÛÎeUÓ%gá¯ÿNáÿDLøØÐ ï Jÿ‹„3vOÒ¦¿Î@Wom ïåX¸‘eäjŽÕþŠñÐ YF¨¯žOóÜÍæÉY–ûP®Ž~x¬ÇÚ²÷iŸ+/õÞqõ‹ì crÑÌÒÌèßÊ¥Õt—nœPTÎ_Üì‡MüÒeÈ!J^¨ä¼mÂOÀØ:_½G7ÑL—kÏùdáf ·îo°…±‰½uÕ¼Ã0h» クÔË‹YD÷ìŸ 2ð›c˜V¡i°tÄ¥bx·Ï“ÒI‘y ƒÑS\oGú†ž>ÅC‹Tx€Ížr ÂC„»K÷„ß}ÿ/*d¼úÑ¥¼?¼H‰tÄEÚ`\ìöç£m& ª ãÿÁbÊøxq‰‡ƒ*Í Áùü^w~³çäd;8ÞåÏLwyÒÛyaÀ›zH€|¨)eDH÷l­é endstream endobj 432 0 obj << /Type /Page /Contents 433 0 R /Resources 431 0 R /MediaBox [0 0 612 792] /Parent 421 0 R /Annots [ 427 0 R 428 0 R 429 0 R ] >> endobj 427 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [155.52 545.388 163.365 559.336] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 428 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [423.494 253.084 431.339 265.703] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 429 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [163.212 129.282 171.057 141.901] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 434 0 obj << /D [432 0 R /XYZ 72 720 null] >> endobj 431 0 obj << /Font << /F18 140 0 R /F41 161 0 R /F38 159 0 R /F34 144 0 R /F17 138 0 R /F42 169 0 R /F39 168 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 441 0 obj << /Length 2344 /Filter /FlateDecode >> stream xÚµYK“Û6¾ûW¨j/TÕH€§|ØÝŒ]»v6U¶’K¼Z„FÜP¤LRžÌ¿ßn4À×`2š*å"’x5Ðèþúë_Ý­øêý+nŸÿؾzý.JWB°L©pµÝ¯,MÓUÂSÆ¥Zm‹ÕoÁF¬ÿ»ý÷ëwb>4c2T°óf½‰Â8è_’àÜévSè/\ÈZÔyj›õúvº8·šÚ¾pÅË=ÍÉëu˜ÐdÎ÷¶±7B2)c’Ë/ÞZÝ”ïkøÑíZ½þcSÖkÓ¦d·%í §¸µþPv4ž œfÚCzŸŸ«þE¾H—4$™I˜PÒèï›ÓZñ ïWr3•dsÉá5$çÅÿzÔÓÝób­õDW9p[ž*}ùYå5„~;çE{~‘\u ¹;¼Z]­7ð¨ðä—˯.•p¹üä/_Ö—ËO¯!¿(»>¯iÝÅvž]CtYî/?¯àWQxU~;¿ÀÊ…¸ú5ã.—^]>(þrñÑ•4§-Ô»ò%Ê—W?ü>‡àx© õ—È÷^©WÛƒî Ë4]0ŠŽóÖôbxîvmùÕŒ@‚ïÍó³ÞõeS£PàC|%V-’"|ùôþÕê73(³ÝD—@4[o2‘áhKH J}È‘C|/›skEÚ}íÛ€$ †Eg稈rT$1T$Z…Ü%R= 5æ§SUn=M]=ØæžZˆŠAƒÕQcÛ›½]Óõ÷È…´¾Á¯4øzv2‰úÀŒìÅ4ÍÄiÙ¢DŽç¶qîJ¢ËÃÙ3/-,äLeÂÅï^ËâL¦£Ý4Çc^pJFæ"<«¦‹ãÈMùpñªp†8´Ç…{¡ô„Öö›Ëˆ#0aè=ÒôM …O]$tò6?ê^·7FI*†áÂöt° ¡ÉÙ>›ZÃÑelm›´ã<ú¿c©Ì…¼õX2™ÅnZ«Ç‰ä°__¸š¯I–ŃÈ? ±öÆ ÅRKù‚¥¼À¾X34J,% ¤YöL¼Z¬«˜õóÜŠ”ãòók‰87ýá­7”o$ ™Û‡ÌI´ÍeÀWÁí¨­êÀD¼`ž™ÔnW¨À;F[ÅÆ:6œeYBíom{ >¶þ Î.<|ç,ƒ©Óö7‡¾"…u‰^ßé–òöî|Ô”nuÌdP€<øÑ¦Œ4Šò² íÂ|ÓÉá…| ^šÂxç½½4añ“Že]Ößó¶Òßá='H5„|Þ$²h0‰cþdž9Ê@«2["úŸÉ“x©[ Ý:äàÖÆßBÐF¯+;5’Ó©±`"¦Ö9`v$‚ï½Äà‡ƒŒÞÂ$3Ú8âœÔ`àe™°'¥h¨¬™UÄ‚OZ wÙj»*Æl¹?”„ŽådÌ’P,”Ó[Ó0w ° oè#ÛÃ⢭©Ïrö)¾2²Ÿ­?zh'ûÙz¡Ýô¸AžÃyéSØ•?»ñÏR¤æÔû<8‹‚œUÙ÷•¦wˆ«°{ûQÖ0ô˜y4bpc¢tf‚NgÇZW€íƉ·°ÊÁöŒ!—ô†P KGzö;yú[|È€Ó——õˈñ1Ö‰ÂÜ?ˆß¡­ D©b¸ÒL »¢j·¨•¦Šž¡¥Aa< Ìá”Á‡¥A¡¥A¦^£Ý䓳_ôt:oí^i$˜Æåúá…ê##)“jÏ÷%ÙlF¤ÆB€rHH­F"iÕ"JsÁ¢LapÈÔ‹Ìï÷c&ùpdKhùQ>e\ÄÕ1ÂÄqÁ–öãœòŽxî­±{5z6g˜¹ðãK¶`JŽU³¯8ÀܬzŠJÐMŽü¯'H—ácÒ‹/V’t3àG# ùsИŒ’)´ƒG€„êAËÜÃX¦üŽÜÃËQçõûɲ•£îðF÷¸&“†“E2kXçƒ pÄ¥aË*ÿj° š/a¸×­«‘r9Á3‡“›>w"g&IcÌv¹£Ó< æ%Z˜a…!¹¼Wè.f×¶€Þ/œ{Ù/zö£$ÇQDÇa€¤ ç%Ä^ ˆ/Æ€Oɰ…½]^U®úlÐW^ߟë‹ho[‡¨S­S%Û˜AÀ,r{ˆ*zŠûG(άáêñ¤Ð'ƒ+æcç;\¬X¢æ ~µÉfjY£~Ù ¨ûæøÜ€Ü©‘ ºì ¸5ãeéøe[0üîYH¦T¶T@ÌœHÄ3W}$`% §ÂX½N¼ýÀÇH|š±ÎW[‰ÒȦÁð2F[øÈ‹ÂؼöÍÆÕ}ѳÓÀ¾K 2­ÖÜjMm›æµd-<¶6û¨·›•”cUeö‚xÕZHéMgñ †LÛváG8bïàè§²Ò›¾<ÚIÝÃ$º5•Ť_>ß~úÏÏ?ÞÞÐ4üü;ûeûóO7¾rŽøxûëíÇ)ü^§"ØþóöãGj¢ˆcû>ݾ£©O “7ùª&i ™ã`ÍE«óãóÛ¤A‰˜#Ç“@Âgbi`(Y´pˆ‘zØÚêZýæ©c£žÞ€ŒïÖi˜ª|Œ¿j[=²“‚0zjKÇô°;·£||;0Òá³húÎ.ÿíœWôЦhž¦L—€êV4zuú(L(›Çb¦L&ÔàHõù¸ÓˆÍžõTÈ u#_?»Ö®)ü²R=qù:ýÎ[’ §“ôÜ_Á,M”º7å' )Ëhª„ieÄ[ÂQœöj ¢.Äÿ5ÛTŸFËÞÂãiÁe7à Óæ¢Æ•21Â÷£ìœUZwØÎÒEÒâ©8B²÷Õüo½HX[ëÉ®ÊA­s\»YÔ‡–µàäby±by±|¼X—ÊÚMpK®š®ì‘8j%GT™‹Ë8P ë{¢Î?1¶{[¡œŠìóÖÕDàÖeÏQb†e5XÛ0hÒÁ”Þ±–3–¶£6[G‰Nyo“µ¢A³¹¯—Ù^Kí1³ÄIm_:>œîŸý¢ìNUNÂþS`HÛ}OÅ€ŠÍ ¹Èã‘@#aQb³»HÎÝn_ýÔÎ)Ø endstream endobj 440 0 obj << /Type /Page /Contents 441 0 R /Resources 439 0 R /MediaBox [0 0 612 792] /Parent 421 0 R /Annots [ 430 0 R 435 0 R 436 0 R ] >> endobj 430 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [331.177 459.145 339.023 471.764] /Subtype /Link /A << /S /GoTo /D (section.9) >> >> endobj 435 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [518.694 353.906 526.54 366.525] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 436 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [343.448 292.005 351.293 304.624] /Subtype /Link /A << /S /GoTo /D (section.9) >> >> endobj 442 0 obj << /D [440 0 R /XYZ 72 720 null] >> endobj 439 0 obj << /Font << /F38 159 0 R /F18 140 0 R /F17 138 0 R /F34 144 0 R /F14 141 0 R /F61 324 0 R >> /ProcSet [ /PDF /Text ] >> endobj 447 0 obj << /Length 3641 /Filter /FlateDecode >> stream xÚÍ[[oã6~ϯ0Z`Vb­x‘HÍ`w»mÓ¢EÅvÒîCÛÅV5¶ä‘äI¦¿¾çðPÔ%”íÌL}‰DŠæå\¾sc¢Åí"Z|}ÙççWgÿŠécaÇ|qu³` µÖ é0’ñâj½ø9øñõåÿ>ç*øñêûÿ¼<_r_kT55òl…Ÿï¨•íÛj[³ ÞÝÍöz¬‹f·ÉιÞѰö.·ãëÛý6/q†¶9ÿõê[Ø”nJp*ÍaÏf;å~[Õ×…;:@,C­’nhV®}róénPÓf×K¶XŠ4 ¥LK&ÍÓ|›×mþè[LÄa¢ânž_¢8jr8”àIð:_µEU⯀ÞÑ‚-j$:¾üðõÙâg¤m?;h Ú­ÐÜ£ #¾»üéò;`‚PiÏlôLJ›ü-¶ò _¤=ù’òãŸ«$Lûc¶o}¤`QˆovÌ…o¦Âq¦(×~šrŠ~ØìDÊmguGpÎó%<6Mñ{î›UF ÎêôYAÆÆóú&Eò…Šy4'r"L#ÖM¿º+6k³@µ/[¯³PFºß𲞜ÄÚ ¶¸ë5ÅŽ_"&óÍÚËLÆ€™ƒS–îb7s›HÓƒTÓa¬ôiš ëô˜fŽÈóÝæe^ã³¶ª½ójFN8«߬K â¼ÓëØé½§° ÁD7eD1(ô‡h¶ùåQUxy¸ËÚs3xöŽú¶yVZÕ·ë?Qý.¿zIƒ¿¬èçeÕÞåmH§céä©ò%%’¦ù—÷¼4О÷ʀİd þj+Yø²Ú×µ… êx{€oö ?ÐæŽþ’„N$a,:lg„‹©¬§I@ÙzÙðM‚"¦Êëhއª¾ŸE J- ÈÓ(ØV=8tLšj‡RÑ˜Ø ö/'š”hôö[¤Ú5QµÎÁa Ö·¤‚À6 D¢'È_”~º†½zÞú ‰á!DÂŒêy‘Ö½;ĸC°°i¨kf'R…q$zS(˜o;*ŒÔ@¯b–ßÜØ¥öínßÒû]f³»‘3ÛXu¾bµùš:Œ?aÐЙ6øÕM]m}ÁYošv ‹ú]ƒœH9æÁ¾U#ý#ÊÁŠ¿0!}KØ%ÒþŸ~Ö°Þ`~Bó®ªíØsA“7p #EØ0¬0K õåñ²¶™Á#êkhT¶i*‹5uѶ¹ýÜV^ºè8Tqrœ. Æ)c=}¨#YŠ˜YØ4ôųagDåvt`as—Õm§†ãÏ(ÌÝëù)âxAkîËMÞtn©¯#*‰%ò¢ÜXÔ®J»WÔ?A¸OJ¥c~qE^g[cÐZxÏÌ\ô~ÿ/ŽÊ:±òÇU¾kiâÖ"Éuç<¨à;j ‡ñ’$ÏGbñ@zÑ^™trõP*šë¼AFëL©ÝHå[CË0‰Óc\D­vD+:)NmàF‰ˆJ!ˆgµ¥%\µ~vUr·µ ðxi¥ (q[üÉ23E—S·c¥9ÂM¨R«2Þ‰d¨ÀŒF½:_²Dy§²DI:š“=gΗøH衺Ç+ê´ëI>XO1×Ûú•ÝÀÁ( z0é,“;o½[w»ÇŸ·žMÄF`†{(ü{Ðltæk‡;Šu¡n#C{}F!ÐDj3D·6f›¾R¬eÂDóÃ#©0 ™ÊÁhÿOåà´ý“k ;±bÃä$¦’ZõzÄåŒ7Ù)’o"r&Ÿ7Ϭ³'Gv  䙨ܫ»¼DdVʄϺžµ! Kz7ÄK;ô™F.‘RQMœÆAGMÎȪ㠊àëk6d¥ÛR^úX d¿ýæÛLØ[¾çɘœnl$c¿ù%QE²ê‰n×uºa¸to4£m†§2„&%ƒÁÍB=ò’|É€çxÝ{Á42qÏ `*<Àç›~&ÿsÀôÞ¦<Qú`ŠtŽ8D˜ˆO¾ F Î%¸÷ŠÇ”z3ŒOùˆz¨A<µŒÅÇØQÜLÜÏÜ=ðªÐe‰ÙúC ðXòJø”~¢A˜Jà1‚¢gi¢gjFôèÙyD¨5É5YÇt. DåÜÔòxrÑå'ŠMîÔ×íÕD$¸HjJü¥‰s1t ŸDCOÉ7^Gñ0Mf3Þ¼lßÙôOºN,!ò†'Ø4Þû9Ñ—ÆÙÁ!œÐ&ã¨à 2>ã‚ËèB3ÌWûÖÒ^Èi~%ŽÑeá›`—;JÔ¹Ó¦.#µo¦ü}¿¡üØÙåÕÙ›3f“\: cÐ6cR>]¬¶g?ÿ-ÖðíÛœhñ`Fn<Ï<Æßm¯Ïþë«7@¤.LRðCq%Ç\ë$¬|<D]ÎSM&á tf"”b˜¸ï+ø2·Áj¹6y H€a8>)š‚§ápÓðeg!—¢ÏO¡ÿa’ŸXRñæ*rdUeÈ9šu›Õ÷y=“ÖŽðmâ‰õù-)»\3Ó¶ØC•ê¹­«ýŽ^ “£fº÷¯±1¬E`ïÚŽ6¨ãa”Á>ÉOc†p#µÇ©ë}Yš<éR±È¤r T%±›¤ÚŽçwE$Oò»¢óPák†ù#œ³ìÒ3‚,~ -ÓõB»ŽÀÿœË7>?O¢%üTõNú£ÎÛ}Ló‰¿ÁÖuž­ÍÌ>!Cúë>Ž®’ËÅOËe£J×ÓX¹}‡'hÁ‚Iš¶X™¤qd$˜t2à C΃×hlrt”-øËxÊü¥a ~µ¹Zirí Í+4´iß_lI¥«ºÍú,·Ä,%g£‰ý­‘:²üÄ”n½6¹Sè3¼~³Š}aè>OŒïžs<ÕV0ošê'ðc”ô4jUíkš·y×€¾_Œ`K íɸ¸4"ò¨Øæþœ¢"#:|z â³ã¨ýEµ£©}^DS9vçwj”ГÄ^qc÷žcy¬Ì×¶ßïª8T=bv¡f<òUp aÅ“c“ø26.'©^ÌÞšU]ì:>$ƒ¤oî#/üÒ}¥êÓ™P;ŠÝIúð¶¯G©€ªõ¹Ÿ…"„îÄS¹~~B7êb¾H«¬¬Êb•m¨c ßÐgŒÍ&£*aûɽº_i,„šztÝÖÙî.¤ àÕ‰‹°˜W»o Jë”Tû)Ê®´“SoK]Р>˜›ÂT‰Ü‡¨ûMŸ(*VùD3ÙUÎÒIq0» ~X”Co\‹Ô£óš= $šˆà{“¸Æ^ tMS\oìy²›Ç«Å#ïI¡ûñ¸´QÆ×ò®ï'9ñ¦³m·9Õó‘eÞª\ 1„;t“oÀ*Ìa6 ¸bì2þþ|ÁU`!°ËÔ™*êÐËuqkêи£´_ê‹xúòpW5v®AЇÍuãCq!§†Ö1ƒ`:,¶¥t¢°5ªÌ¡lû;°ùòŒ¸xêx첺h :%¬;cO*Ô%ŒôÐX*‘ß4ÖC\ ?Úw«cÔ²9!4ˆ[Ûp5fœOFÁ7v‘]]”«b·É/|Ú ´,+K–¸•%Ìëî"aÃV pˆÛö[77 mm—Û 5¯ÑiÁîgI°®Ê¿µôý¾$2Óò*ÞQ#\zŠ-ÉÖ?MANЉèÜmͽ|Û7Tu(l•¬> ßw?;gK½àÁÐÝ¢e + `ÿ°kÐD=âÌé¿ÐõÇåñq'"€¹tÃøŒ#ÁÈ ŒåÔ Ay7èØ]Wƒ—Þ~³ƒ]V®¼É+ˆZ“ø ¢b2¼âB¸‰A,ÓÉŸåð8ø¼BfáiŒº'wÆÉë”{Eylf ÞQÃyWÔ´òK•s/F§Ðé –éÈži’ïÂpαﳣù.«X%´Þ7 ·É[ÓBŒ©Œ·¨. CÈo‚—6‡(Æ8ߨ°0¨€Žy©à’ÒÉcë>J8Ça%¾|óäòS(ä¨z0/>ÊÌ-8®Þñ“tÄp`‹‰¤]a/´ðØ#5I'`Åå¥þl鹃 É1ÀçIŸw æwjã¡0nJ dÞc>xH¿ôÄ2dŠ/|"ðxo­b}\<DZqƒÉ[º8š÷Ól˜F 뢻nr Ì’C‰™®D:œI¦Òô—ãVzn¥½ò¾ê½•T«qlûÑIŽÔá ñ¿Œ y- h¾îÉŠ”ÌPî_¾É€ycº^ýŸØ›¾‡YrW¡ŸZs™´ò( ýô{n½ß„ÝÓ:œ ý;†ã9ïupõUë¹`[ö¹‰î¦ ­”µæþ]Šþš/ã `öô0Cð¦ë¸¤gY[I·!nÍå4P£åŸÁ+{0›v¢mQîדòF}À0pýuÐ… ™-tq­B1©sM „7˜¯¨¼åÂ4 ¥ßËFL-W™f5@Æò#XÖ'åhôLï¤NMOMev‘vYäÔf"ð%˜SÌD`Ó$\ñžÊ›}^®ìènÌ.+ü•vŽpÚ_}Öåq¸ºôßëødžÕÀé0¥ÏçÖ[Q.åb¸¹ç)£É•‚ºW¤ÒdZGÕÈè^I|OÈŸüQ”·øpNÍu×¼Còþ<æ8 ÿÊçŸU©i,†uö“tpok鹆B®=n³.nénKtOйU>.7,Öt5¦LMòÄ,)Æ5‰Ë«³?Ó„áõ endstream endobj 446 0 obj << /Type /Page /Contents 447 0 R /Resources 445 0 R /MediaBox [0 0 612 792] /Parent 421 0 R /Annots [ 437 0 R 438 0 R 443 0 R 444 0 R ] >> endobj 437 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [201.014 689.614 208.86 703.562] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 438 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [194.44 646.941 202.286 659.56] /Subtype /Link /A << /S /GoTo /D (section.8) >> >> endobj 443 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [141.984 403.686 149.829 416.305] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 444 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [327.282 389.24 335.128 401.86] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 448 0 obj << /D [446 0 R /XYZ 72 720 null] >> endobj 445 0 obj << /Font << /F18 140 0 R /F17 138 0 R /F38 159 0 R /F41 161 0 R /F39 168 0 R /F42 169 0 R /F14 141 0 R /F34 144 0 R /F45 160 0 R >> /ProcSet [ /PDF /Text ] >> endobj 452 0 obj << /Length 2766 /Filter /FlateDecode >> stream xÚZQã¶~ß_¡^Î ¬‘"%*HhŠ\s)Ò è}ȨV–m!2å“äìm}‡œ!%yå¬÷nM‘93œùæêâhÅÑßobúýöþæ«÷\Gœ³\)Ýo#s¦µŽ²X³Xªè~ý²zÜWæö×û¾z/ùtr3•¦°”›µ§)*ÊXžÅÜÎHY–èH²þºI1Nšoš²4Ï¢õdÚã­ÈVE»NDº*»ªª >Ô®3[zß³m»%á8Ï™VAºÎIò‰tŠ¥q­9Ëògñ%ñ$(!¢É¬;Üøq_7ý€â û ;Û®ÞÕÛ¦µj<’àg‚¸e5Õ% ºd—t<øëtWéÂh­Ù¬µLãÐ^s G,qj»´ È¿d÷Vá§ãí~HI²L–y¨Ҹݞ îºötËWGv {§«ŸLó„3p­¶ï뇆V,¶CÕ-‰-”bà~$ËçeW³jÅÝ£µÈ%Œ'b&Ùåc¬â÷ðÇyD#‰RssüX÷eÕ4…©Ú“÷Ôöp(̦·ïÜ|wóéÆžYñHçL©·iyêºÊ”Õ,fÍ 5ÕèÅ´ö–`º£ÜZïLÛYQS8gœž¥¶?½œé?¸EAW¥àP¦j{ª¦wc œÁì±U‹†nÐbEÎWÿKcç°‡C(ÿ^ë±§ÀGJà‰"Íi ÏF+'•,z~vd_tE9¸c ôlÂHNý©h°¯¯L_éë[~º\ʼ—£‰>[øêÕ›MãiQ¡–\hB#.$?<<0b+ß¼|`ßVÈK“leÓ0f¿$óÇa›Û®=Ø– ³Öƒ“ž?Æ\6î¨ÒŒòôšâPá›N‰ÄÓ`hà Øî‡¢sÄÏ.<,Lìzê5­Y/0íÁ…vt™ >èFqYèå !=eÒß¼Loh0BXU–á¹1‡mÛUgû›êó€]Avae×Av‹0üa‹cý Gýv=¸ÍŽ:9Gd2­õ”Â8×·í‡)GÛ¶'ÌÄ·Ša¨Gz¥­úÑ+‹ ½ýXû™×‚ߺ ´/7Šé<€¾·è—j=5°•ëHÓl|a7´h…ˆ®ŠÏ¬€‚¥è„Ö–*_ýgïˆtÂ*ëv»¦¯u´Í •` Uç¶‚ÎÖà¤aï4õ‡À_¶øBí~N´"… L ²_ÄkÖ†!¢€dß{l(š¦µn€4”ŠBЀ¯~w=Í3LÕáT|eÜ?õpÄëM5ÔØ5 lšsØæ+,mÜõPóîîÝ»Å"e9aó·¦u@˜xœÈUõ¹öâB7±b×ÑB®N¦©úûk¯û³¥R̦è6ӥdΛ`O®»Úmïœ*ƒ´zFu‚D2#ŸMbGf“3˵gñ™GA©ñX¤79AA9AAI(x>QP" zÔ€Ç9â-x•Ç¿©#^ Q±7–Èﮂ¿ÔÓ. ,Š£9ö{gû Ëka#cªÅëû[ t«ûc‰E³”g¯y4E=‚yˆ*Kd î¶—Y3Ë:¤tÉ^ W½?½·m't,/ Ž·0súƺo¬WõW. þRЀ¬;ÚÒ«í–&c®ÆvWïö@3Np¥ÞoCÃ.²bŒÁÌtÎK´Ö1šq.Î\o8#7Ü̘àîßž#]ÌÒ)؆¿¾Æ~!g¸m75pt.ĵM’TÊÌgO²\À•ðâh´EçslüÑY*…Š6Ö1Ëó ûÿBýÀ³'½^ÔJ39ÞZ~‡âB2¹¥™Mc[šRãùuKš0„wÝEKÂÁy—Ð:c\ä¸5,K£³'dŸ%ÇÜäá½E r–… C}¨zÞAˆ“ÝÛõXÕ0¯u®¤¶£¥½<ÑÌú@½DTèuƒ­Ž2\Û (,F+VgNZ‚WCÕ„0v)×çK »m‰"mZÊ©6ãB~ Ùös~’=¥Ñ]W÷×Pvª±>½LÙ>ÕÁûfp¦Ç‹÷—¯Õz>Ö Õ4€¾@ˆíéäË¡þÝïYm8îýÐ>6Õ„Œõë„Ý̉É07tkèâ•ÇË@ 0B%9]!ûœX:ÎÝšºtuô4% Ç]Ç+îÍ©Ä8Ë„f/]HæÌújËåi8‹Ò2ì7áUt½gfÉ<—V€ßÍ©¢‹BO T'ÓÍ@–1ÉÏX­*|ò²ö8Ô­é]‘œºbÁö>Ùulñi\ï^òFwá6³¥•:ü=´~>z,¶·~¸î[˜q„è8ØÚZÇîøp„~GG¬à (x b»$v±È{ƒ¼‰Ê¨BVÞ`Ðè1G)‹ö:L§Èqª‹,‚³ÊglÐVÔíƒr­ ÷ƒ¡ÎÊà4w‹Ÿ´ Ë%c}¸_„hÎâ8›b§“€$:™Ò H¬Bçî£Ö³Cv%OÓ„ôÓW_SL¾>¿+ðJÛè9úåA®læ°œ‰1ulê]w«b(¬•bª„»Ý\ºej$V›EcÄ,ïéæ"|7Ys yÉŸÝ@?ŒM퀖¡¤0TŸ×µ#R]¼- –è}=å5àgŠ&EãdI Åò,ÄúÝâåêônõ·—MaóÝ,Kƒýãj“ö£M…ÄϪϼ¤mYˆ¨€è ž£-‡œ]>ÿ|ÅÓZ€ô¶Vç°’|ü€•0¥³³ÏW³Íx–0.r·–JH|H)N–2bN¿ÊOŸ¾ÄO%Fjáî{³`ÓpÇ·lMà "5Lî\ VÛ£ûmíŸr1ã€%q®IXýKtUê‚®Õ¢ÿX:Ðõukæ4O¬¹fBêk©§?ô¹oßÓçYÝ­¥Á¬–Óµp.<@ Tv@0ûQBä¹§—Âel(/‰?Øž9À¾ ²d©Â~²ç+Úd–ém‡ßlÜ¢=ë¦êîFfK4Ô}í^ËÜùÿ%p†x˜©}áÑ×ÿ«G ÿU¢*¤62'²”¤³Y³ÿNäkB endstream endobj 451 0 obj << /Type /Page /Contents 452 0 R /Resources 450 0 R /MediaBox [0 0 612 792] /Parent 421 0 R >> endobj 453 0 obj << /D [451 0 R /XYZ 72 720 null] >> endobj 450 0 obj << /Font << /F18 140 0 R /F41 161 0 R /F45 160 0 R /F39 168 0 R /F38 159 0 R /F34 144 0 R /F17 138 0 R /F14 141 0 R >> /ProcSet [ /PDF /Text ] >> endobj 457 0 obj << /Length 1667 /Filter /FlateDecode >> stream xÚ­XMÛ6½ï¯Ce bøMj E&@nmèa“ƒÖfÖlÉ‘ä¬Ó_ß¡8ܵ¼²œf÷Dš&9o†ÃÇ7¢É}B“÷WÛ?n®Þ¾c6aŒäJñäæKbs¢Tžj •*¹Y%·éG÷mÆMêšb3Ë×i[lw7û|óáí;!—›œHj`ó~áªqŪ*ö]˜:´¤1\Ç©­kÛ²®Ú` hœï˜´]×ÞôCÆïf™² ƒd–I¡Ò›5NþD™lÚ.LÝ5õÝÆmp½ .¬Âï² +ºuïE’1M‰Î9t$‘RGL˺Âî|î—•ç£[vÚo1¥ KXßùûýUrÛO2øw9l{ {_ÍXºrͦ¬>“.=Ø5 M±ì\ƒp1,p×mìú©ßw!0¸ünÆmúýÉÅ~â¾u `‰-¢H%9Í™?šdB•c~›eŠ«´ZØÐ¹ï7ùóæêëCo­ RÉD+E¤ÑÉr{uû™&+øïCB‰:yègnn‰þÔ7ÉÇ«¿B ~lKA,Ó°™!”Š€L !RÌî\ºÓo€é‡DhñC~ÈœŠ«üÑÀ‰z$8vß»õeðB2tˆ‡FMxñÆLž÷ÆN<`0°ÓDDóüzH=a®“åöåæ)'–b> 4o&ìRF¸É§ìùS™¶«`?®L°+Ñ®ºh^YCŒx±×Ê(D¬«ë‹ÑVFBûr§5'LáÝÑ1Øä¼YÏ‚½Ü®n ù€t¾,0ÇgIGIà €ñ*¤3Ààß“Ã#ñØî*K›ÎះÖÜrß¹ç£Û/塬îƒc»èÌ¿"Ÿû—ˆ§~¢ŠRL;è3ÿ;^;ÿ{lÍÆ}s$8=KR~×Í]ÙµóÁõ0n…CeµòÞn9'²h„¯Ã)õ ‹hä6‰FŒ¡Ûæ¾Ùµå¿n¡çмwUœ¡¨ê•‹CÛâ0£FºeWwÅfapîr·®ÜºÐ[„†’xTA8´cÛa^×gÓY È@;I]À ÜLg3¨8 {IJ8‹jÆK)›>Ä—Ô… ýÀ‰ü5'ïé)޼®ñŸ¿¶I°'Fäëùˆ{¨W Øe ùü뾦ɭJ2ÿrãä ÖŒN+wèBïIaš…iPaBÛÕ¡]9xô· ðÂÏÂ+HJ²­·u³ƒ³X—í6Œ¡Èí…ÝCÏ;®ÂÍÓË¿¦ ?ë/áwÈPΚ^ÅÔl¯_aäÔ’d9 X…ß24~ß^Ôµ~ñ˜®5L§ÿÌ,÷™å7êöM…[™¢ÕÞ ?öÐñy<¶]€_û®Š öaôm[ø¨D6îGê­{¼hÇâ}W,Ýë]x˜$ä24Yíöl‚ (–ôäû÷ðÙk?HP–’çy"`Œ ̹>z}‚j5Ìf7Ùùõ9*ÉÏS‰kJO"QßËI$PF*©O¨ä\²þUýÿFSp`z²š|MnPt”øÏpÃi±Ä¸|ÎòUÙáÍ›ó‡C†¿ÒáPMl޶—õv>Âz6¯‘ OçŽ ÖÁ¥^ŽûÎúh0>åÊU]¹,6ý=HžQ4ËñÊ@…,“±X’eXªÉ Ó@eÓ"ú&Ãe6ÃUyÆãuÌD¼™(êÓÒ‰3E˜ÿŒ.áõVñ{ݰR€û}’ endstream endobj 456 0 obj << /Type /Page /Contents 457 0 R /Resources 455 0 R /MediaBox [0 0 612 792] /Parent 460 0 R /Annots [ 449 0 R 454 0 R ] >> endobj 449 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [209.264 690.278 217.11 702.897] /Subtype /Link /A << /S /GoTo /D (section.7) >> >> endobj 454 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [213.363 351.88 221.209 364.5] /Subtype /Link /A << /S /GoTo /D (section.7) >> >> endobj 458 0 obj << /D [456 0 R /XYZ 72 720 null] >> endobj 455 0 obj << /Font << /F18 140 0 R /F34 144 0 R /F33 143 0 R /F32 142 0 R /F65 459 0 R >> /ProcSet [ /PDF /Text ] >> endobj 464 0 obj << /Length 2682 /Filter /FlateDecode >> stream xÚÅMsÛ¸õž_¡Cô4Ââ“ ãqg𦻳;étÖ·$Z¢$6’¨Tìtÿ|ßÃ)’%ÛëvAÄûþùl=㳟Þp}ûæ‡E2‚¥ÆÈÙíj–¤Ì˜tfy¸6³Ûåìcô×új®¸‰2¼ÄQ³)ª%ÍäÙî°Íßâ]Ý_IåôdQîëb™WôJF“u«i|·-¯æ°~/}¡¹e^ë=»ú|ûË?*ÝÇK&Ši£m‡Ò>;6WJDßiíe™´ÝÒE¶oQÚŽï—»²šãû³¹R “‰Í…fZÇôâaSÔ; ]seû%Ü­Ü‹lKóÛìÎQ‘o·Å~]ÓšrE‰ÄILD|F$ú]ïöïô Ùä4 hîÊ=wy³¡=–4A[ã–"‚Eðú7ÇôªðŽ>$‚¶UÖÆ1H°¤¹Ìßç_Å·+££l›»Mš_”ÛòXåKZ½®²Ã†]ÍmG¿GxYûý3zŃqRÑb ¥W­T>„' “±i—l²š¶Ô@`U‘7E^‡¶ŽS¦eܾ÷àõ´˜¥– ·‚Űt.˜M­!4³JÎz«Þ†À%,áòyÐä4uÚ\Îd*‡r}w5±¥K —7;YÁ!6Õ#B´¢„| BâLÈßÈ^@†f–gIÚIý}€ŸÀðT½žôìeh¯&½‹_MhcüB{Ì­»0þbÀ,gÙ&úâBïóhÂ0maÿÚ5eRuøâ†÷a88ë ¸ ?§}DßsZ‘×%ÿà}\|8WEÃû¢ñ£ÖSæt_ç=ˆ4si4S‰ÚÛ*D‡ž'/r;c~Œ÷z¤(§;KÏâ ¹*É´×1¼”Û¼5„Jþ74„´W&@ !õÕçÔwR£€0KщW¥U”gÎ+m¦œ’4#Ù7'áúó¾váæ›ÌEg Ëp¯£"ö>§1ÅUg8¿¤ñ9„$@=bÞ‡O§ñS0¢¤'·m×sŸëa¦&Ñ6 C¬Ðu;lßÒƒŒf!gX®sz>aGÂ(óÎ[L½€¼iZUs g°½Uü¢_õïÞ1SÀ”ǫƘ+¡^„ùšåªM…/ OtúçˆCÏ&ûà&ͦ Coi¢ÛMN‚_•[ˆé ÷{Òm—.Šh“—U¾£û¢ö:²Íw>¡ÌªïW‰Œ\nßÕã$.1GL0(8n»­­‰äxaû;ð¡6cÊ(zXÎ= †·Ù¿Ëðif]]Áy<ÐmTWaÁÁ&v¹x);3uœ€ýŠÚÃ[Ð=Æ1wýI%TH?؇‘£ ÊŒUWˆÈ‰&ILôs<-˜>áþ!žRfüPjhÇÈK=ÎPC 5ŒÇâÄpvøà =Ìœ<1A_ìËÀ`‚ƒëàâÿN´|DùDˆ}ªûV µŒŠÍSµå~ûÝ/  Iûµ×¤º«—¨ûy)?­â˜2 @[wzŠwúó´ÊÃ&> Ýú$ÕëÃdžº×2òvNýL|rÖîöÑ\[¥Î/kÙÐ_-&©R©…e^Ç¢ ‡÷dUGŸvBÎÛ_Ë{Ç|tN+ÛsÚ1E ¦Å#»ù¸*œCÂèðš¢Üî7{KÑX[»êçu™Ñ§| ¢Ž ð{ïó*kʪ"×¾8€¸Í¿¡{v:½l@ Šé¾¬îЦ¾(<’/ýT±_¢¯¡§Ä´fŠÄཡ{Û×¾ca#Zltñ|lBÛ¬«C]ü'¿ÑC"í ÏŠ} U‰ŸÚe€æ iMÙdۛد]dûãa™5y}#کÑM±ËitCP3N#jV×!Þ>ÊIó€øÀbyÖéf¥}ŠuÈ”3ÑB^õa›aù>2}âiØ Œ† j†4œ|÷(P0õ*ÒJàš2?B:à*î¦Y f¤zVÄP{šKœè}Ló§hë)žÇ !Ùr)è!0Åå]à±S½ô²õÐÅž®¼Q KL@Á£*ìJx Ñ-ˆtk¶¦/¾GÒûc«¼Ç1üJÃy5wôùT,d {²%5\‡Öš÷8»´Ë“†kÛt)¸6®UýÔjüо"C¯Ì} ¹Ž¯“ö" Ï2É«˜‹Ð‚‰¶ÑóõX4¡ò Š8Ɉ­s™2«<š?â±J‰]¡˜ƒ³ÝûOŠðn•튭K/ð?ÂëøÃ+œëÚÑðÔ¼¡Y÷å”{…”ŒnU‰¶LÖ±¤9_Æþ@]ËÏ3ÜnÛ¬¡Ò?ïò¬kz jÕö«%•Æt–×ã¾øẕQŒw˼ɫ]±wúŸÆÝ7U8&Kq¯öW`Â#ƒCDÆ­iüÄAó‚°ò  f"´È™ÙÛÐW÷›¼B°Bz¶àÈ€C÷Y=õˆ߉¹§PÝùUÄgð/#¾aŽOYQù…ޏñuÅb£_]Ãd ÏrkwÎÇQŸêSŸ2óŒnÆ7Ø2nÿ]åîãà _Ü5\m5ï©a‚'ã€0½GÈŸãEÑ}™†*Š¿ iàš•34ÔÑU‘ Bg`rR'}´…F£ÇVÊ— ÆPËçµv¾¿ 5ŒJ†=÷ѱ0x«Ù¼·ìç|¢Q[ñôÆ\4Ë’ÓùÏŸAv<0ŠÄ5ÅlôÏ}ËÞœ^™Y 2¨ýô¦°×ÎO%mý­’Á*p¨ÿáOÝK endstream endobj 463 0 obj << /Type /Page /Contents 464 0 R /Resources 462 0 R /MediaBox [0 0 612 792] /Parent 460 0 R >> endobj 465 0 obj << /D [463 0 R /XYZ 72 720 null] >> endobj 466 0 obj << /D [463 0 R /XYZ 72 632.473 null] >> endobj 462 0 obj << /Font << /F18 140 0 R /F34 144 0 R /F41 161 0 R /F39 168 0 R /F42 169 0 R /F14 141 0 R /F17 138 0 R /F33 143 0 R /F32 142 0 R /F68 467 0 R >> /ProcSet [ /PDF /Text ] >> endobj 471 0 obj << /Length 1916 /Filter /FlateDecode >> stream xÚµYKsÛ6¾çWèHÍ„@‚¯ô”Î4™é¡‡ÔÒ –P¤J€±ýï»À”¨Ð¶,·Å·ß>AÓÕvEWŸÞPÿüùæÍ»¬\1Fª,KV7·«"Y´$”g«›fõ%ºÛÉn§¼ŒÌNi;ª¢ð4Ã(ß®ÿ¾ùõÝÇ”Ÿ ©8I²Žp":1šuÊ¢\:?/-HQ±°´Š×,‚S˜ˆ¶}ÀéÃЯ㤈j©†Dx›Ö¿Zßo±êìÓÈAËÚ¨Þë°ÄaçwîûÁoýgT¸«uW1K` €'œçˆÍì,¸¤,"eðY‡‰9,;ã`ÙA#µÚv~¶Q SÊ$"ë˜'Iô¡Õý[x[eÇ=ß×IÉÁÈ{¯Æ÷uÆ#1(8Þ=‰®µq'ËÆCóˆ~÷Zƒ:`mºb«ÁšÜ>z³úâUþ5:ü™é+=Iˆ‚SZõÍAsæ°ôö¸ÂcÀI=Ö–‡Û±Å—wÊìp„¶‚%0ª3WiÍU.› 6 ¹ÈÑÅ ’°Œ[¿°œš1Ër\”ÓÓEiIŠ4 ε¸Yõ­^˜QBÖ’%_K—U«8¥„ÓWÞ€R !d0d—…@E8›¢å Ð×Y‰-ÆË ÌZ·c¬IÂ>8p­Œ_Òßâø"Ð¶×ø«†ØßX‘dzò”œNìÌ1rJr6©¡`¦ÓœƒªFâ„ü‹²¼Ví‰á”ò”ð4Ÿ»×įn »³•€'á­Ó5+¦É¼v¬ 8eƒïUçõ›!N('Œ§“~vs¾¨ZBÒr2|?, c)‹‰+}à§ËÂJ’¥“-oûa/ Dz™TÖQ´Dô8ïU`ÖAz¦%gs¦Ë)ï\ˆW †x•útHÖìŠjs0š˜{³„VÀ"´loc›~}Í÷+1$®÷ë8KÓèë¨ .–÷²Dž[Ö½ï¡2ÿଂ¾iBÇ;Ù Ô ’§ÉYƒb¥P¤=‰þ'äý¡ðu&lFu “0à`p+…éœüs]²È¿ê;WöaÔ*§+ÍŽûBTXcçJ¸Æ%xÖÉÇÖÀg=„¤ü ]µH.heìê„Î{œ…”‡2 …Y³Ð 4ÒÕ¢‡M;ÎmAm2?òYc+»í³žþþ¯¨Ýi„ ýÑiŸú›'qÄxáI1Ù,¢I9Éóä8€¦[†³Qußö£+¬—ÂóGžã3 f™± |<¯ž£LZ{-at‚ÅÞ÷Ï€ógÍÀa¾œ]s(ùÕô5jº^̲êVaCßáϱkäÐ>¸žgbùi=<°™û±5ê±"Q2~µ{ˬ¾ MŽÚ^›üL›â"mjSN.3ˆî?³ Èjúýå^¼DpÝ®²º·€ðêfɲݓOH{a|ÍëšéZðH?7Zš—‡\+6²½ÖjÛ‚v}§jÓ¶W=á/u/HU3Ãô2Ϭ]÷ý‘GÄ¢t ÝûfÝÁÔ¾!v/]ùy~[ë®õ‚F…¯{áV…‡“0ñ±¥ºôî²o[nÖç^Â9Ьpw­žTmÀacÑö·‚÷l=ÝÖãR˘fÐÔLÖÄçñ˜˜å©ØYž{Ó_ Ùùhž ºù*jÙÕÞ“¶ò¢/ Øç¯fÀ½ÔÍŸ‚ ÒEã¾!LNðrO¶mÿõ)Â&4Ø/Cå}]TÕÂ\ÙNÕ½m§`¿ì¦l?}-8FÊÕ½•hÙlårë’v¼´.K㓺ð¦³Âe0¦Ä<¾œúëµÖ'÷1ûÚ'‹§ÛÄ3oo ˜¼¿Ýnä£*¸ªæ†ÿ¯¼{ŽjêAâUž–?€¤ÅÒ~;€›Ž½£2f‹°[Ú(í§ÖáÃ¥µGiP/c¶.“„˜°‡pC,ñ0øÚHþTZ%žßãÐÙ¶HI™ÝíB¡jùœOÛž7›ÓùÛg \½»’N·9éþà?œUy>š`xü¿Ä%TÛÝ: k¡‘ßá'@üÛàräìtŸK\SâÃɸøqÊ9åí”C—Â1ð,ï_ÎrÝyU‚¹5tÒ®píb]÷C3ݧ÷Kš¸qûÏ*à@gþ³b%%Œfîº[TþK:ÿ×À/7oþéK– endstream endobj 470 0 obj << /Type /Page /Contents 471 0 R /Resources 469 0 R /MediaBox [0 0 612 792] /Parent 460 0 R /Annots [ 461 0 R 468 0 R ] >> endobj 461 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [518.694 690.278 526.54 702.897] /Subtype /Link /A << /S /GoTo /D (section.9) >> >> endobj 468 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [159.514 496.139 173.212 508.759] /Subtype /Link /A << /S /GoTo /D (section.20) >> >> endobj 472 0 obj << /D [470 0 R /XYZ 72 720 null] >> endobj 70 0 obj << /D [470 0 R /XYZ 72 658.813 null] >> endobj 469 0 obj << /Font << /F18 140 0 R /F34 144 0 R /F60 323 0 R /F38 159 0 R >> /ProcSet [ /PDF /Text ] >> endobj 476 0 obj << /Length 2265 /Filter /FlateDecode >> stream xÚ­YYsܸ~÷¯˜GN•K€¼Ù{ËIìly•TRÞ}Àp DrÂCŠòëÓxŒ)É›äEC€`£¯OÅ›ã&Þüø&¾ú}wûæ‡I¾áœJ‰ÍíÝ&›,ÎY,Õæö°ù]lyÜþzû‡>ðÅÁD²4@Æûén¾îdG©L¹åQ¿Ý%"‹Ž­¾œ:|N#]–M{°õ‘–}CG4-¶JFºµ¦ßŠO~?ê6~Âg=T¦ó øñRð?Y3‘™&ÔóúxÖ£û€veôSöÌë’ƒ.E gŠ{¿ÿ°ÍE4´@¡%ðòG&ÂG[ü“q=ŽsÊDE_Ì?ÓõÁç‘WS•ÍÙ0‚i"7`PÁ•t°†g¥ €·d1"â ƒ $Zšz›@3•ø|Òõ¬ÐYÁ=¨+‰™Œ=©Û“E–Ò"áÎ-*K¬¦™Wì›®÷Gí±¶ìR“ÒÉŸýíô…>øo!¨ÂM¼ˆ8ƒ´;‚ƒŒ¤Ê—뜚¤‘`Ì›å1b„;7–’cèÆ·`Ô àÔÐ&ª”öÑËpÇÐ]žVßÚ«+z5Så ìd˜@Œ?wò;ž¥ WîŽKžŠgüaáÂPe¼Ò®1îËû·¿ÿô~Õ1ù¨2ï/~sÇs¦RI¯~‰U¬á” ›?CJè Æ™$jÍ¥5!Ø`L!̉\:µà‘eñÙúßÚ¤GZtÃ…²^Óöä_‚c€l1¢-ç_îCã?"tkHrÅòLÌ`Ø9ŽÙiM …+r¹Tj|…´,KW(—«˜ÌXšñIÁ.nü¹®ž®"X?+÷qÀk’åävS­§¿=À%·Þ3Ù Xûà0Käwºõ(©‚p™x$ ö¼Ñg4~?ô¶²¡^¹– È]¼‹_Oà ‹ÓÑÙoÖhe £¨?q*¨#^×ÅK–s4uîW¯Ò|@$¹rÖÍxñ­§”^EIœø,Ÿäщü¹¹÷ô³9ý\°}°-”ÿ®ìÍîãÍî7»Û5r™©ß °î)åøzò»ñÕÀJ*dõ2Á:¿—úàleëû1À{ð*8~¢E³‹xÚ©ÞJ_®‰Õ]"òyýùôŽ5ëY?C_5Yº¦ˆ4–'¡È#_ß/8§î~ͨ<†¬—.Yçcé!Ï´ yÂTœûžûž!÷=ÃÏ«Rê|%ÑÑêñd©ðÍ„vM ê⫊ê´rVS-„ømfˆoÚû^R¸À hu˜œA½Þqèäç ÈgGªc€yM¼Cƒ®Öúi ¬B{àU´žBbÅ¥V2÷λó‰~X_½¡Ð@ej¾cÛ —õö :…4Ï^ËKåq™–둹pú¹Ð¼¨'Áª‡å”õÒº"×ÍÀ†Ò\M(ïšëàÄ©o\=Ü^ ®Ã¸# Ab6ßõojOÌTælÆy ží“ÞÞúÐÒØ‹°â&Z8ŠšÂ"ÂE{†¦âÁ¶×]kˆ!4>^‹!PÊåSny-†(‘^Å«y¯­¯[Êt;D–°dUH?5½sDqä9KacB3,œYw‘MDˆW…Ì¿WÄÙlŠ/ǹbp™í® ¡x€]O¼aôt}²è·0øÎ0e Ï—U$)òE8Îsãlv®©sÃj+½¯ü¶õa 1¾6BËS–-|ù{AmVßÚý0¥z !}Ô¡“| ·Ïþ°V©œÅÅHú¬ïÍ ã««‚¨€Â']$æiÚ¼"gBA·Vp–&>6Èxqêýí›ÿc?“T endstream endobj 475 0 obj << /Type /Page /Contents 476 0 R /Resources 474 0 R /MediaBox [0 0 612 792] /Parent 460 0 R /Annots [ 473 0 R ] >> endobj 473 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 0] /Rect [337.197 653.748 345.043 663.445] /Subtype /Link /A << /S /GoTo /D (cite.boyer) >> >> endobj 477 0 obj << /D [475 0 R /XYZ 72 720 null] >> endobj 74 0 obj << /D [475 0 R /XYZ 72 588.443 null] >> endobj 78 0 obj << /D [475 0 R /XYZ 72 334.163 null] >> endobj 474 0 obj << /Font << /F38 159 0 R /F18 140 0 R /F34 144 0 R /F17 138 0 R >> /ProcSet [ /PDF /Text ] >> endobj 481 0 obj << /Length 1145 /Filter /FlateDecode >> stream xÚ¥W[oÛ6~ϯÐ\t° ›uñ¥7 C6ÃÚ©‹ Kƒ–(‹ˆ$ÇX÷ßGЇ²$+†½X¼ó}çJÚ¶¶–m}8³áûËúìüÒõ,ì!×›9Ö:²æŽ5·Èö|kZwC¼@xt¿þUž[4ÏyZ¸ŽÔRÊH)ô £Î¶u.‘c»æì«ÑÔ·íáÍÈÅCŒ\gø †4Mݹ?ŒxžêÑž‰X A ô˜$ —#< äÏ^mùJ®…m´´—X˜bÇC¶ë[Rƒdåj"çcÉÄñ‡ë˜z´Ëù6'©™°LÀÆ–f4'‚ç0—$õ@ÄT¤xÊóÔòÛœ—;=äªèZxŽð‘¬\䃛³é#Í}hž¶<›èÙ>¦9 dúcøX-Ó BE¹Û%L9SÍ6‡Ͳ 9ªHØß[jWtQ‚vÁA È&,{0Šul*zLŽ3–È4{ÃzY:v£ wæÈ^.4ø1Ò …Šª!Û64bO†@ÂR&:ÁøtñÇg­Út±1q|Þ†Õ!XFôÛ¶=š:òSçÉûÆAQ3ÞP‰«, ’2dÙ¶éðÓ½Éé…ùH FSìË\7Èû˜qÂøåM!BÆQü®ão.nâPšÿ%F²ã „Ìø&KHΔ°ì›íÛjWãä[ð &4–«w÷ò î³ôïjÑqTQ¶wªÌ€š¹SËŸO÷¯û´Ô²©ÎÞOv"ƒÏ7LzÒ+múHÍÕåÅ×ßÖ×7ë«ëÏ_þúp{qóQÉwª­ÊŒ×=¾P*ŠMòÎU³~(*ö<7ÕÂó‡bGzçwlë:_çÍ$<>§œ½…u¦7sº‘±¤L@ 3„”«5ž´Š>é”9ô²á´·¡H Xºsø±n^{Z§L¶­ëˆ´‡Ÿˆ‰hKí‰qO·/…,Š$ˆÙŽržMù³P{§@0ßçLЪo×·_WÀ–4ÚP£É?Ó$•A3©Ó™ˬ/H`/jÀjoáZ’zóDvƒÐTÂâÿ^qÕÕ)áÁ7ìz™ôiÐz_AC:)ƒº£#ƒ" ™Öö2L~Î*BÕîO` L¿o¼][ ´šíêÉ´wƒ´º¾„DªžÞàð¦ÕP¹›œ’(³Ý*¿†E@ðÝñVø_NuiYˆv¶°¬Stù±40B/Ã*<ƒ‰aÐב¨ôTûš|þéé‹îKˆ6n.x‹ù"¢u~¤½/G’”¦¡”æª:Ö0ÉL×ÉÉ¡~):>š;ó“òlA-Ú°EE,`´Ûbž„­S‚©ïÚ:qØÑ–ö¯ŽÛ€ú‘¶£·õ‰þf>š§Ÿ"Ò–&m ®¿a©Í߯oß¹ús59}€j<ƒ=×i—ÊÌCÏ·c’eBýtÚêLeò-¸­ åܰRÙ§@æ ‰¢«°ñÇòÏFK߯þàÅL:z&Ÿã3ä.á9îá–Ìj}ö/«> endobj 482 0 obj << /D [480 0 R /XYZ 72 720 null] >> endobj 82 0 obj << /D [480 0 R /XYZ 72 720 null] >> endobj 479 0 obj << /Font << /F34 144 0 R /F38 159 0 R /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 485 0 obj << /Length 1100 /Filter /FlateDecode >> stream xÚW]s£6}ϯ`2“6‰1lüÑmÜÆIÓIœØÛí6›é( c­A¢’°›íô¿W ,ü±yBéÞsνW¸Vl¹Ö͉«ž?ÏO:×Ý®å¹ÎÈyÖ|ayÞÀzC«?ê9½QßšGÖÓyzÑüàü'ùøì.–Ö|||x¼šÝþ9‘³¶|xb'‡sÙ»‹çùoV[xò†¾ÕöŽ;IOK¹t¾„r° IB6ÇrJ2މœ… Q£5¤h “3¾\Ž6Ê  j ¼*¬gàŽ®ô”åž値àè%•&ü+7d¡Ý©ÏäüU)É9Â9í~×uÏ/;¥KÏszA bJŸå®¿Â% Wµš%;µ±=˜ú}ò8»}˜Þ^Œ¾¼)٘ч`Ã×0ž'|ž_*ßB.U¬vƒÂ(jX€Q,?ÎdÑÚ^·¶Ôpd|k—ß´·%ÔGµI®O´:¿”¨ÍXC×òRKäÕ!ØÜý'¬ƒÈC…¦”õŒŸžwðPM«rÈ8 œ)Ü“û÷óO³É\ξBJÄíã0”ÇñÕÕänr?™Î+ºµÌ°ð‚xMÃQrÕ'R­UŒ¸æjŸ  …V@y*F»T Þ¶ZëÒåž ÿ-_ú¾¨.CóKlz¸y¿ÿõñácá;¶×vZ+Ý5“Eó\®l.,<r]M§ZY†ÕÂRlgxgŸFv`ãζö¾°þÛ9£óEaæôbH'”éê¦Hç¼XðËÓYô\øøá³×íáS¿1åg‡ð@ÉÃDɆ¿sD«Z tÅ£P×Ô¼ÀDTÉØn$JÿF²g€‚rHMý•®¯–¦NVLN ¹ª¿‚1ýpwçɨJQhòj‹Žœ5©Xªú BŽÖPW²)ƒŒT†£¨`g€±¸É `«ƒé59kÖí.@ž)-fGSº2ÛâT팋~"@Ø„ŠJÂìïd3QÉŠBV&«Ûw¼ÁÈ jCèŠe „vpy?þã^¶&aÊH‡®Óí{¦ôwÚ9C_áæ‹–™™ê çkMèÚ\¢ubšƶzJC›q Æ&ßQZšSÑ £‚.'l$fH"¸s©@úÚ±¡h»¯ÖC) 3  ÛfõCøMW•µn=ZĵgVU_^ÌA\ózÆ oÝ¥ê€øîñW‰òRß~^u- quwGQeÓuê? ãKθIFvt¾Hˆ¸ziÃÛê[Íqx-ÆÅ)šêšÂŒŽµà—œ7ù`K’'þ¾Š¿uÔÃ#Ù¶UæE5')¡Ù±tGÜ5Ǫù9îâÔ6UÝD6{Íè ½þƒÊFâØlí­~:×âÂ/B_üø¾øðÄŽáÀñ‡jKÏ7öLæ'ÿÜ)0 endstream endobj 484 0 obj << /Type /Page /Contents 485 0 R /Resources 483 0 R /MediaBox [0 0 612 792] /Parent 460 0 R >> endobj 486 0 obj << /D [484 0 R /XYZ 72 720 null] >> endobj 483 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 489 0 obj << /Length 1154 /Filter /FlateDecode >> stream xÚ•WÛnÛ8}ÏWYl`¶¢«/íf,’¶)²I¨ØK[´DID$R(»îþü’æPG6Ð[¤È™93s†CYFbXÆû ž'ï\ϰ=ÓõfŽÄÆÜ1æÖ´<ß"ãóÈ^˜ÎøkðQì[t÷yž¹p¡e·‹¢šoñwÇ ao_çÒt,Wï}3žú–5z»ö…c×½È!ŽÆSwîbVæj´!> endobj 490 0 obj << /D [488 0 R /XYZ 72 720 null] >> endobj 86 0 obj << /D [488 0 R /XYZ 72 720 null] >> endobj 487 0 obj << /Font << /F34 144 0 R /F38 159 0 R /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 494 0 obj << /Length 960 /Filter /FlateDecode >> stream xÚV]s›8}ϯ`<“Ý$Æ0Äf»ûà­Ý4×é$´lÛéÈ cjIØÛîô¿¯„lÒNl]î×¹Wçbj‘fj7g¦Zÿöφ/F#Í2 Ïô,Í_k–cc{¬]{Žáxךj.ÒËk»Éå£éšHŠ}¹¼¿»Ÿ=Üþ3—»\,~Î’â°yìÙå'ÿ•6°Æ†5±µ=6LÏ“ž†Wò¨¿RXã$ÁûEr‹3c¹ @¢¤$ñ:†TîØ0)í•@”Äh+¬‰Ü"Ó52\GùWîVpš¯X¹¡Ü¿rƒ×¥;õœ}•"Á9‹¤ÆåàzdšWÃÂ¥eŽëªœ'Òg¡õ9ØÀ`+ -QÒSéËé[ÿñÝüþáöny;ˆþxK¼ïÂa‹Êw›RXÅQ+ˆ€l£ôâáÔ[ò€Á@I3Tµ$Ýž [/1—HY>¾Ò¦aÈѵܱûº³Çåt±¸{n l z¤GŸé·ß^Z¤Ñ«‘5enS[4³I!Ûcêüo[¤UKž{•vÛ+QiŒÓ°?aý‚zÆøýª:&«˜QµxPâél6_Ì_Ï—åÉ"­>vŽ:ÁìP|€ÊyH TFÐB<À!<âÓŠ÷$f°NäþÊý$9læT`ÑzÆp¿)`êÊp„MÚ«=3°-©8ÜÄ@T{ÜæWõ¨¦i;.O¬$ÿjþ©ù–AA¿¼¯.¦aXÙ4 «*a7_rÊšX€ÂV,ëóá[>įœó$GbUíA/b³»xO¡†úÁ¬rÖÆƒnpž„è÷*‘ªçØõ¨9œ¿Ç×—ßRœb’mbš5w±"µsÃ\÷ôfW÷9üýT60¡°¦Q¯ùrÅÛ{«.ªãëI>*-þdc¶ÉÌ;¡\}U_pã|{®k‹OJÛæŸ—W¹æ)MÆRÅq:sÿì=þÌí endstream endobj 493 0 obj << /Type /Page /Contents 494 0 R /Resources 492 0 R /MediaBox [0 0 612 792] /Parent 491 0 R >> endobj 495 0 obj << /D [493 0 R /XYZ 72 720 null] >> endobj 492 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 498 0 obj << /Length 898 /Filter /FlateDecode >> stream xÚ½VYoÛ8~ϯ\°™¡®Ú®wH´)‚¶ØjŠ4(d‰–ˆÐ¢ ÃnºØÿ^CYŠ• Š àˆÎñqNb+µ°õæÃ÷Exrváù–ã#ÏæZáÆš»Ö/ö+L¬ë±³@Þä&|'ø]>ßG ÏZW5õùæ¡xû:—ÈÅžá}>™/hžÐ<̼y0®3¢ûŒ3X •|ËË"£ÕVSÒ’7…4Ð^À|…EÏr0Zâ¥#-Î×GØ ,!'`xÚòÙT˜vƒq(TêUQò´Œ¶fCó ¹ yMKX÷IŠF¤–|L¹þæ³)kòMⵜ9r®€å¡[pv—òÜÖÜûŒ+ o F@m¶kRêuÕ£$Ñ»õÝ=ÈMEJ4™98ÀãËÄ IÌÕ¸‚„5©á¬A˜ÑüÖhÞÓ:q_Û‡eÝ­pb‘‰àƒ’ÎpŠ‘29ëºÁžž8îáåBSŸÐ£1 ~¸ãUP޲¿ôö`£€c¬°2èlúÛþ/¼ã4¹/iMTÞ}á,H¹mꨦ’dZØæú&ЂÏ °ñÙˈ±û©#Húî5ïš Ô)û÷kâ†<ö³±ü¯"º®¬ÎþI‹š®z>ã ‡„—w§zù§þàB¼áò@==¥Ê ‡²ÞH#Mxê&#»¸¦7’guÄôÅñü|¤ÏTÖ!ÿïÍ‘Ž»ü»h®?/Z‘zÏËÄÿn«"ŠÉaõ˜’JV´½W¯/Îÿ¹ ?| /?¼ÿôõÍßçßJÕ¼…R=ª£Z³[èír·z(ú:Ëí­½VE€eš3¨*/Il¸ävÕïÍý„6*Ãã{5¶UvEbÖt&D;`à”1 ìy;oc’4¥i)ºKû>Frvw3¢ª¹™‰mëé \š‹þ°ít¡¨:‚R6yÕïMm5wï !Brrªf+qöú²Û ú¶«„‘aÃJÚ£Á ‡0rhzί—ëýN&0æÝ~z¯ÍÈÎ3Ê<-ƒ@=Üœy€,¢â=CÞ^Q~Гyžü'H±v endstream endobj 497 0 obj << /Type /Page /Contents 498 0 R /Resources 496 0 R /MediaBox [0 0 612 792] /Parent 491 0 R >> endobj 499 0 obj << /D [497 0 R /XYZ 72 720 null] >> endobj 90 0 obj << /D [497 0 R /XYZ 72 720 null] >> endobj 496 0 obj << /Font << /F34 144 0 R /F38 159 0 R /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 502 0 obj << /Length 979 /Filter /FlateDecode >> stream xÚVaoÛ6ýž_!H–&²,ÉVb¯Ë/Vº ®]8ÊŠ¬- F¢m!’(”·Ø)’’èX]¶öQïÝÝ»GR¶±2lãÝ‘-íoÁQï¦ß7ÛÙ#Ç–†ã\ZCgh\ÚCËxFŸNãå›®çz§ŸmÏ&!È–|Ð9Ž:æIƆŽx{u%¬|<96æWaìrý—à–@×é[Þ`$b|/']—g"ÞÈà©D¯SˆçÂ|œ/&w·ùâ©+s¨ÓêéËÞ ž‚k>ñj­™š™9ßú‹»ÛùìvÂq+÷Ò²GC1y˜§ÓùµËVäkse®¾’o%H'I‚ÂŽæÞÌ@¹óÄí8£fùüÀÝkñÎiÆÿâÝáǘiþt‹pd²¿'’ƒÖ#祇›Œ.®{¾ÑT`¿VÎþ"•&gÏÏ7û*ó^ˆl¨g¿Ò¼[Œ?ü¾˜,›inÌ´µlÿý‡àáÎÊ•?Z8žLü©ÿÞŸ©¥eYçY·Ôêqö__¸uÕõ·Æ¬œÌ1k²ØÄã‚¢á|“”ˆÚ‘Üí×ŸŽ£/?vúƒ¬c¶§WîÁ×,WÞì~:U:A9QÆ„ö\B8þå^ê8µT¸:ÊÇ`šåÙ¶5ð\½”Þ™l¤b„É+JQ$튡¸iåc,O”í:×{KW¹ZÆ$™^N™ÑÀ¶ÔY¥ŠXIâ#„™Š…0Œ¬7]‡qtz+ÉÝ¡B "‹{y†) ^)dÛ²Ní@öjÚÆI¢R¶’£!;2½Š ߯ÒnQöÕ!X²Ñ¡Ø`‡q|–Þ4NÕœÒJ}<DzØ5Msƒ·1fEɰl 4÷[ Ò–&“F åà £dg‰‰³ž¾‘šBkèડŒœb^ÏÍxzç7´ÊnQgèêç™’ªÿœƒ,j—Ù^ÞJ¼q&E5•/ Õd¢ô¯voˆøT‹LYå&)&æ Tr“pñN …Õ“`­($æ:© !!€ù½¸Ð|üàè Îí endstream endobj 501 0 obj << /Type /Page /Contents 502 0 R /Resources 500 0 R /MediaBox [0 0 612 792] /Parent 491 0 R >> endobj 503 0 obj << /D [501 0 R /XYZ 72 720 null] >> endobj 500 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 506 0 obj << /Length 1001 /Filter /FlateDecode >> stream xÚ•Vksâ6ýž_á¡Ó P£ø`3í -l–N&É€ÓÎvw'#la{°e%‡¥ýó•­+0ÄyìÐú÷Ý{t%C 5C»>3 ýÝ;»øh;šé Û¹´4o­ -mhŒá¸šh_ºæ9½oÞŸbݨ¹ÎqÐȶ„—zÅ%ß‘ïòaí±Ï1² [­ýи†Ñ]æ¸`¤7°‡nw©ìmcÉ^°£8}9ÀI’‰žÙõ13Zì7¡Zjk¦ÆÆØ¬P¦å Ãv5áAP±%úE_À[n׋b&{y‘…NÕ ¦>„„’󬀱`);<"²#v¥Y‘ _`Y™Ën¶†E5]Í"sd V6r!¶tðD N¾t–ìÂŒêr´H(T6Š/†Ù2] ÄÊ> endobj 507 0 obj << /D [505 0 R /XYZ 72 720 null] >> endobj 94 0 obj << /D [505 0 R /XYZ 72 720 null] >> endobj 504 0 obj << /Font << /F34 144 0 R /F38 159 0 R /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 510 0 obj << /Length 505 /Filter /FlateDecode >> stream xÚT]o›0}ϯ@‘R%|8¶Á–mÒ6­•¦ªOì)Í †Z-'ûRÿûì…¸eÕÐõµï=çž{¡S9й™ÀÞ~Î&Ëë0t)L‘“•Š ˆqì¬ÒDéÊÉ g3ï*ÐÁdþÁ˜f½âÀùÒ5w‡zG…YóÒØ#’íigÿÈ,B¸6¶ß}?(ÔÖó˜JA—µG©ÁüsÚÄX5/±O”¬ã†m_èbëñ¯B×ct*’nŠ{Òã5ÒUÎtÕ!º˜‹nL//øÈ46‹—¥ð Œà¿(<›"kϳ5¡~³¬‘¥æšÞІŠ\rÑô<¼O©¾lfÅVóî…Q3õíŒ6­Éò—ÎÑ_%òöÁÕ±W]å?å;¿•÷ýöÖçbÇdç_ñV2Þ¨E'så› £¬ÂÈþÁÅc׿{êc·ökßà uç¬Ëkx!Riá5íëj£®üКeÇ~ÛÅ Àrꟊ•hõ9ò @—„ºÓ©u¹žÇZBŸ::ÜÜÔ>Ü š?ö€ zst½*ú“æÿ£šóã³¼VØ”¬_ŒÕ+„TFH€W=_”XI_³É_ÏÅ- endstream endobj 509 0 obj << /Type /Page /Contents 510 0 R /Resources 508 0 R /MediaBox [0 0 612 792] /Parent 491 0 R >> endobj 511 0 obj << /D [509 0 R /XYZ 72 720 null] >> endobj 508 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 515 0 obj << /Length 867 /Filter /FlateDecode >> stream xÚ•V[o›0~ϯ@ÛKRkN`Õ2%í2U]×°‡i›*â¸Ä*˜ ;í.~Æ—†DtEáØÇçúùÃz…½‹´òM68=bÅ ŠÇ¡—Ýy“ЛÀÀ{ÙÚûÎûªK«[p&Y^2ñØ€¿Vµ¼¸]\-  dvÚÑ]Ÿ¥@ÇŒ<çO:þ‹îøÊU_*ꆎ0€cd‚ÇéñçÁo\‹]» endstream endobj 514 0 obj << /Type /Page /Contents 515 0 R /Resources 513 0 R /MediaBox [0 0 612 792] /Parent 518 0 R >> endobj 512 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./moebius.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 519 0 R /BBox [0 0 484 242] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 520 0 R >>/Font << /R8 521 0 R>> >> /Length 522 0 R /Filter /FlateDecode >> stream xœÝZ»Ž%¹ Íë+*\è²Hê™0ïvÿÁ»ccn°vàß÷9¤Tuï…;-40ÝRI)’‡Íï{:dOü™¿¿=¶?ýÒößþµýß›ìßüëþË_·Òê¡Év9Êèûck£9éžG>Úhûís.ÿçoÛï›Äßó×·Çþç/ï»ä#ï_¿nq"þ=èŠ|±#õýë±ý¤øúÇVûÑeŒýCõüãëoÛOÆ/¹u·zÄTáÔ_¾¶Ÿ7S+ .–òA-“Ç]jåøÇfCó¡»ô”1Ê–Gëk®©s»}lØÝËp‰}ƒbâxÒ³jÇ•q`Áƹ"8êõšÈéùÏuìZòø/K¬$¹8},ÎsóÜÏ'ÑzˆþÎÚçbT®ï±¨æÑ¯%çÌ%ÁÊuŸÿ‡fÍÀ-ˆµâ:TSÁªRÚQz×_òüÀtÌ çLÎE¹LU»]Èa ¡û‡ï9âÃ$Ìä#×ÃñìŸJ=¨ãj bœFC ΆÀ¸}º% Ëã-/Ãkü¢>ÖôtÐ}‹ô|àƒ¤t˜^'‹ ž E•E(Ž€šË¦‚›¾ȇQ…Gö'êP\ãþÒæâ‡¦Â奸\—éÎ ÃÜ?%KseŠJ˜*t,èR5»·Ä÷›Ðñ=Õi«öŸ¿ ¾XÌLù±hN’ჯ)¾Ö7‡)½¼ Aqqñù4…»¡-úPzñˆWYo||¾Éö ÍñêSPØÀŠ Ï¤Zs‡ÿÝÖ{=:Y„£E¥ÁË¥Š?€Åér¥ÄôAèÉ9cü£ïœå¬!vÙ(û·mNd˜Oé\Ûs&xp}¸ôb=WÚ¸ðzíáý9±ÎŸÛ/ö^øÿ¶ýúÇûÉôÝí Ðb0MÓÀ´Bï€}´~­•D@ð™“Áq3hˆé&à›æ"5qÐ …!ìëûa}\O;ÄBU…b…{‡Æ¢µäf´£_ßéú*MÉ•h#B“z$®aßõt7‘\M½¥ñ ÝÑáøDtmH° ˆ°à± Ó½€uCTË~foŒ 8¢p! €–0ÑÀ:6@B®"#ÖD`ÁÆ6;`Jd ˜AfÓ š_Ù@$)â¢ãhæ!Go¬‡Žî$+¨t€*¼ qä(ÐöHe/„ߌÃ* ¬` –Sòô$b¥Ñ¥ÂÀ|Â:Ïk ˜xØÇÔ€vålÖK+{†”FаX\O†!5˜šT-(°?! €¥ë!M¿à® 0à}øøUˆPÕ=%£ÒÀ.8ï@‰ž.¼ì€ÊP7ñôŸ€»f"/ °Iÿ‚óV ξð¾ÑÀÇÖø¢ÎL…Åá3ÿ®«{ D•Á ‘©3FEEΕ7¡rqÑäÒˆ³È01.Aþ ,Ð)¬«ò& év«8ª mëÈâ”Þ#iôèLŽ>ƒ†›an¸š´tf[ž¨áLë<#ÝK ®$͇¼Qlxõu[Ù¾{b ç6ß”áÈI¯CÞ[ð: ¦¿…¯êÙ´dðá rkyUæÿÌó»äÕ*ÜP³ƒ¼šgô˜@()»¢Ø&Ög¤ð€qDg  O·yÕë#?…ÄašÉoAœß¸w}ÝM¤H,hrº{Šè‡g¢BrKê¨m°¤Ý;¢$Òºn ûHê eÉŒ‡'L0MG÷‘ˆ;Ó®‰î,RšÃ¸£{¯¨?)V t‰íwÀÕ%°½Ñàä[`û›3Á¸¡\ˆ«²í€ù ‡%h¬Ö¢Ž­øÍ•ç kÀðšIõ¢ 0BÃ:cŒÃØ{®Ð “Â_gœ3“‹Eaqù.G âm…sHÌlÑÛQç;Þki^‚äT¼¦@z;V ÷”¹Ð#<¶3¾ËS€7v¿qÃ+À»ß°Àw"­¸£\ÏÏ#g¾´Þf¾4ßV¾4ß®ti¾%¬li½%Ìli½%\ÙÒzKXÙÒ|KXÉÒ|K¸’¥ù–°’¥õ–°’¥7ö_žGî"’û•’É @^u£¹áaU–øFÃÀ±´ÁL´ó%¼£Ž+žòKµÀ0°z4…8@ âq‚9‹ˆF<ÎëuŽU (wÃÑÌ„qcà›R¡¥bU' ¹µòHìdPÃ4õ€Ri”oü‡SÝN¨PÕÈ,Ë®¦§Ká‰S4=!FóÄg6=Íëɧž§)$”rö<Á•7"WÏÓøXÐ=Oƒÿcö> endobj 520 0 obj << /Type /ExtGState /OPM 1 >> endobj 521 0 obj << /BaseFont /Times-Bold /Type /Font /Subtype /Type1 >> endobj 522 0 obj 2436 endobj 516 0 obj << /D [514 0 R /XYZ 72 720 null] >> endobj 98 0 obj << /D [514 0 R /XYZ 72 720 null] >> endobj 517 0 obj << /D [514 0 R /XYZ 245.217 533.711 null] >> endobj 513 0 obj << /Font << /F34 144 0 R /F38 159 0 R /F18 140 0 R /F33 143 0 R >> /XObject << /Im13 512 0 R >> /ProcSet [ /PDF /Text ] >> endobj 525 0 obj << /Length 686 /Filter /FlateDecode >> stream xÚµVmo›0þÞ_Á"µj ¶ IX×I]ß”©J¤&ÛÔµUEÀI¬’ª›öß¶q€¾dÛ|‡í{î¹óùhS h;@ÊO£æ¹ei˜p 6šhN+Uµv"[N[ùÚÍþãŒÌña#{ÿØ&<¸}N0 h™¶-¶ýäsq¾ÐrÄÊ‚ORÛÚ-´ZÓ3H…x/D-…>\ÇÎ È$'y.h»~Mߣœ_=:R¾îí)N> 6ùg>ªX÷Nw‘xywTWÌGW…›ä ‰b3¦×†!cOºB7XF±ÐÆ2ûx…)O`už¼Æ„.±X4ʼÿÊìPÇŽœ d×âjCˆoƒ«Óaïû™x3dšóÌ7Õm¥Ü¨»ŒŸî½öRÙ^=ЩÞ?þ2ºþzv5ì ú½S%aØ‹±/o³?-zZ~²ü:Å!îöåì‡> endobj 526 0 obj << /D [524 0 R /XYZ 72 720 null] >> endobj 523 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 529 0 obj << /Length 828 /Filter /FlateDecode >> stream xÚÝV]o›0}ï¯@‘Zåˆm‚’(ÝÃV­S§¨{X¦>¤U倓Xa’®šúßg°!©6­/{@6Æ>÷ø~œ °V°¾œ=~šõ¯=Ï‚Àƒ1´fK €;DCkF.øÖ,´æíï_?N§ß®îÄ ÙÌöºÌnÅ8ŠxÐ’«pÒy˜}•˜ô\0VÇäV—m;Žüö5°IÇz>h÷»jáv/Hªæ|©Æ-I3¡Þºý2¶_‚I[rš³Óè!MI‘P½‘puh ]0)KK®Ïç—§ƒ@™këÕËýó±×£¹gšó«XDHz}tè²íœ>Ô.F'G|ìU;&ð×ÿç~ ™Fæ¼z¢¸W\‹…óÝ=ÞDêÁ&,æü%jDë£ch'¢èÀ¡ GHÇR2i?Å ©©XA[ÍR"6Q¦#ÊÔ¬´]Ìt=Dùш²Uu£\†:î‚Æ4Âiô²3àŒ ¡2×cO—ãzYß§$ãjLR⢂3]Û"Áy‹t 5IÍ›¬)ÙšhKk¼%U›‹<Í(ލ0Ò€5égb„Ã|Xð-q;”ñ««†6Èð&{Éã›?«'ënä‹<¹/í$cöíéÔæé‚f¾àIF9“‘aù®\:H1ö«wyæéSáuc;–b\³!ý³—d§ã8=”ÓCïK•è!eŠ›óøŠÇ NµûÌ8£L—rªšhªJ^)-wt¹¯= -pLÅ*Ëýfv®lIJY¶ÌZ7‚ÇšÕºA…Îyز©“§åJn8þÚô%ÈzuœÀ8ýCS^$‘(Rf÷—Û¿†#+—ßGÅ/®\8–ºày.éSÊ1»3Ÿgg¿û¡Í endstream endobj 528 0 obj << /Type /Page /Contents 529 0 R /Resources 527 0 R /MediaBox [0 0 612 792] /Parent 518 0 R >> endobj 530 0 obj << /D [528 0 R /XYZ 72 720 null] >> endobj 527 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 533 0 obj << /Length 198 /Filter /FlateDecode >> stream xÚu»‚@E{¾bbãÌ.ò±3Q «íÔÂ*QÁ…ÿ.1XXMr'çäæœ`áQ§Îϵ&´dÜ 8ÖkC R$àŽ°öe–×§ VE„¢ÄϪâ^”KvÀ ë(5ož[·„0LØ@È%²ãõyQöÞôV¥ŸX©¶À/°/ÓÝu(Lþ•A²Io|fuÛ“m†r°ßÆóÆÍŒVDµ(ÕìÁ !F$îQ?ÐÌyoÆ€Nà endstream endobj 532 0 obj << /Type /Page /Contents 533 0 R /Resources 531 0 R /MediaBox [0 0 612 792] /Parent 518 0 R >> endobj 534 0 obj << /D [532 0 R /XYZ 72 720 null] >> endobj 531 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 537 0 obj << /Length 1106 /Filter /FlateDecode >> stream xÚ¥W[o¤6}ϯàqF›;«VjÒîFÙv«ª™>u[É ˜ÌüûÚc0!í¶ÍClÈw9ç»ètn >ï÷7·üÀA1ðP8û£{N ƒÐÙçÎo”n]„¼póÀq[n]?7GÆÜwêaèH®n‡­6—íïû·"87êø ŸW›E϶aºau§„ma‚Ĉ¶œ7Z%B CO º^ƒ8AŽxÀ R¥±/+‰Ì‹6êŒ7}IÔ‹Ï5Ñ>-Sq ÄEûÔô@î×ÜF1ˆâ‘ "c@Í)ìû‚ …)ºBEAPj ÆJ÷{Òe¼jûŠÑ­Š³£: ëHÝ1ÍÕ¥k1ïˆ~KhÆòŠ×À—.òA¨Sæ~ùÏ\ÛðžšcèSö¾ìÔý7ßfÀt$Ö´msÜ ù¾¨‹aŒ¸˜&JüPÂq­¤Z^ѬjkÒ½»ÊŠ ¢&”‚¶Wka:4Â;õPi¸ý5ùò–/c‹9±es’Uq=PáU«²Ã©bCW_ÖøíCE1¿¬rº‰ê•Ô‘³Æ ÓîK‚sÂwãÛ–ñN‰ñ'É´–pu©+J€èH·ý¼. åtQP#$‘o—]i[½ÈJÌqÖ‹ðjœØDýpé‰Zâ“Çê8áz Ë|µ rL -ù.òtQ¬^Ê*+½Ëéñ¡Öïïž¾{|\"FÐ!Êhˆ[£"ÝÙyФzrî'+:SçK)jýdû:ŒŒžJИ®Y&(­–—š¦sá£0§8Iqw­'î+ ñ$h0¾Ö=¦4MñZ ê~¶gPMhÑëLf*4ANZN:AÑ€Æ4«köÒ)Ìž'ç Íóý7¢ÑßéD!!‚èzÈߊ«Qœs•5‚d<”£ŸqnÚfQÔ¼*JÍò¥2D Òùkð3Y¨Íiëh†º—SÉŽOôŸÉ­ÒK&zÞDï©­MªDå3³ØÐv 4cbõÎʉP)*œ³û?$ßÐÞå¹ij;ÎÌ ûnl®cI¬±1 ]G‡ª]UakèZóÿ‹9¦±áä™ z;ûRÔõl¬u‹‘$ jLh ’/f÷8¯å¼kþÄv‹ÊS„ì´ÎÆ­™©Ä„)dèŸo£i2@;5?]7¿HÉ󔤜PÖ“åº;¿þ9Û9Á†÷”8 îÚ ÒQ}jÆQN¥¤ÞNãÊèIAøß¬þ‘Òb ™êÐ^o ÅpÚ9Ð’¥AÅ~8­ï?rÑëˆjðGk†|ýÆ„"ùÿHÍзtÞïoþš#ZN endstream endobj 536 0 obj << /Type /Page /Contents 537 0 R /Resources 535 0 R /MediaBox [0 0 612 792] /Parent 518 0 R >> endobj 538 0 obj << /D [536 0 R /XYZ 72 720 null] >> endobj 102 0 obj << /D [536 0 R /XYZ 72 720 null] >> endobj 535 0 obj << /Font << /F34 144 0 R /F60 323 0 R /F18 140 0 R /F38 159 0 R /F33 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 541 0 obj << /Length 849 /Filter /FlateDecode >> stream xÚ­VÉnÛ0½ç+Ô[ X )j ’Š&i‹¢=´=06-±°%A¢ûïK‘Cm^’ñÁq™y³=;©ƒû3 ãÛÙÙÅ¥Á(Á qfK'¦È|'Â1Â~àÌÎóˉxÁ¹ÄØ|umÆ|øÆIü(Œh053 ¾97òçŸ8À¹ú#æ[f|„u™ÀEšIXÛI^O~Í>:ž× t\BQà'ñB³­¾66¶ ð”ñ ÔnÍ ê‘¹G‘ò|!8CC÷QXó"gÕÎÈË¢Z©€ˆäH#s-4/B8h·[¶.W¼¾œ¸DA2ÎSÜy!K¨ÖÒ¡gz;ñ¨ìÐKÍÀ¼þÀBÔÂÞ™6>a#µ XÛÇÌû!&Q€Ãè8kVaéà¼XÖz둯Ên1ò΀žàgGâÇ*=‘ãú…~l´¿ãõ¼¥E>ÌiZ±2 »Œ3‰È=ñ³ûu9X{L2(»]É/õ!{F/ôZ-š¢17ª&+>—|ÑCVÑÕ‚WÒaSõZªÔšëÃú¢#ÀVæÌ{Δº}pÖ雫«‰ë…ê@SOBfÅúEõÑàJuÿ›6ÏC  õNXs¶¶ °•<¯´ã`PžðËrŽ|\Éæ,‹öÞ›!cõ€ÜþðJŠ9¯tò÷JÈ1c)56²RL’Z—lÚlñ›Íy>ßõ« ²¯Š­ÛáAe11ËKÒ‚›Ë¢ð[zž§2W4õººã.< ÆM-òtOT3} æuÓOµŽ©‘½V&=Oio¾“=BSÀ3Õ×:Ô1³Œç#p:™C¯xYñšçm—4ê·wÛt7:^‹ÀÚ/,˜ü:£¶ìÇ%Ä)»6îØõA".) ®0ÛÿZ²oÙ·Àdp:Çr•öâáè¢5ا§qc¦gïßj1|&ÉAö|(¦§S«3hA•µ™Ó„=CèuɪšgôàyBÿ?J·Î~{]…òSQ”õ(yëÍJŠöéÕ ³O!ÅVk!¤½ð¯wú•.‡ø¥—Cûœ½¸#±CJ‚ÀkÞ²ž§ÞµD=Ë(E8˜?8s;;û þà¬ý endstream endobj 540 0 obj << /Type /Page /Contents 541 0 R /Resources 539 0 R /MediaBox [0 0 612 792] /Parent 518 0 R >> endobj 542 0 obj << /D [540 0 R /XYZ 72 720 null] >> endobj 539 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 545 0 obj << /Length 1061 /Filter /FlateDecode >> stream xÚ•WMs£8½çWpKRÀ`ãÔÎa·*3µ[©™=ø–ÍAÙ¦ +„ãüû¨%!À©Ú‹%ôÑêîׯ»zG/ô~Ü…0þ±»ûú}µò¢mÃmäí^¶EQ{›0Ca’z»Â{}@íúñm÷—D›a3ˆ7(ÜnÕæB ÇÕcÆéC+x—‹Ž“§áB¡$Mà|¦Î?ãü¤9n`Êò¼kJÒÂ%j"ÈU¨YUR‚ƒ(LÇçkNX?0®&„;ý9µŸ0ǹ ¼õ]B©þ ¥ ¨MŒûWN'bÄ×j¶^}¹újú~"öC5üöMW÷s½Ò*ï´@û¡9+¤Å º™çÛ$îK¡}s€§¾9ü£¤3G猶ek…=°ÔX‹¤â‘ü‰ÔY#Ú8V}Þ?Ý÷V¦›t¸±;• \ '-¡€—`j,¤%=ve{R‘²MÐ&Noø¡·á¬µ¶0ae•=I&#z37(^0ˆvõ^[£Ý{!\”9iÑŸÔÊYY9¿ëm…+ƒlj€±&‰•0ŽÝAýU‚Vë o^kÀ£˜°uW‰²©Èè=8¡´íš†qA ˆÝ}JR&4œH4‹™ÎÁ{~â+¼@}0;%5w3Ë ò³÷µÒÄÄ{v!‹.Çe®‰+f!vn›ü² ìm3_œ?ƒ]d¢ÐRÀY†SB s5]8qXDðKIõmŠù‡›²IJà¤Æ%•¤›y[% pøŒüÛÉeqÜ—×Èýkø™ÈÌö¯‘Y‹ÌZlÖô !¤7k³)gÎc³š±-ß–JFd¼èO8býõÆÝ³E`1´þÆùÙ Xk`ŽD~ñ) GÉåSßáS} “®q1ÆKo» ×Á²vÃùÀªŠ½CDº¹*Oÿ 7^ùgˬov=ö‡tïÛ•Ä'+™?Ê[š¿C¥Xûéè¬1·O䪸ÝÃØ>ēګדlš³tØŒ´ô^è›2¿:Òc¹Âê iRåùËĬšé-KN –DÑ71A'Ⱦ—âd;™…çÃ@JœÆ)eÝ®EÁüÅœÕ2Ä4—Üä6lãÇc‰_½ÞËV»jAýÿ¯ÓçôÓ0þDK™¶Z¸ºjV×´2ukz—c•i>XN Ù¶ÓÀ4´»°²ø´ “Ž)LÚ´ HÅØÙ,Wåy„WÁ±9Ù¸‰¢£]Ûé¦9Çí¨O˜änºX„©v”@vÝ×Nj°X5:IÙÖSS­”¹*Ǧö»Åu±­tK½ÆÑzÞ6š©!ÉÛ5{Þ¹8ëþcj®©Kî#… B^ËþIƒ{êtÿe·^œÔöçÌ_¢¯ß£¬¯êÛ4ûÿCÑ6Fq¶’=Ù …(ž¦ÎçÝÝÐyyC endstream endobj 544 0 obj << /Type /Page /Contents 545 0 R /Resources 543 0 R /MediaBox [0 0 612 792] /Parent 547 0 R >> endobj 546 0 obj << /D [544 0 R /XYZ 72 720 null] >> endobj 543 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 551 0 obj << /Length 846 /Filter /FlateDecode >> stream xÚV[oÓ0}ï¯È­h\_b')BHëP‰‡mHnâvfkr)ÿ;¾¬i3D_üÕ>>ßù.¶ƒ]ƒ› ´ãÇõd±"$@¤0EÁz«LaA #¬óàvº-ëYH1J3lëro,h†¶4£ÍËÙýús€b€„ˆ¥†Jn ds+ïued™Da¬Ã`ùðÖD‘Ëí»žj:d>zæ÷¢×˜_ðâ©Æ*»¶êZcÿÖ€ùáωûÞ{8žZÖÉ2ëD4 B˜&fý“•‹¬Ìe±››¿ÜNË"+÷Õ“h­Ž;Háf~Tƒ¾âÒ–‚·>,¯Ì’4Ö‡l2^ç"C½½«÷úȵ¿¥©×ˆàåŠ8~wé>]y³|ãDç2ã­°n›Š×`¶SÊzÏ[0R®¯Ý¦­yf£`ä¼³|\¥²lÌ›gï…»hÕÒeK÷N’Ý ^?ÏOÝ»J5òè0­å<{0R)ˆq2 Bˆ­ÒlëCýsóy[£¾ÏüÝÚ…·•uÓ¾„7,aQúüØNiìI“íÌB¤ºeZ\Å#Ù.B+«"·[ÈyüºÛ¯ˆî6ÇömÝË‚ø½.㻺ìªf,áåvpÐ}Oš“„|Š­œ‹ _4D ]DcC¡Ktuêêâ2êF÷fa;¦?;QdÂÎgÀ¹s2gn†º™ŒeÇ÷ƒüïÿѹΩx®o“3×bÏe¡`nO튷“‡ó"‹|çŽt½Cl5:ƒ†¬÷¹X¡DW0¥ëWDu> endobj 548 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [71.004 281.345 276.445 294.296] /Subtype/Link/A<> >> endobj 552 0 obj << /D [550 0 R /XYZ 72 720 null] >> endobj 549 0 obj << /Font << /F33 143 0 R /F18 140 0 R /F38 159 0 R /F45 160 0 R >> /ProcSet [ /PDF /Text ] >> endobj 555 0 obj << /Length 1004 /Filter /FlateDecode >> stream xÚµW]£6}Ÿ_´“H…Å€CXiÚm³m¥U¥NV}˜Îƒ‡X26Á¦Mþ}M¸&˜™L«æ;±Ï¹÷ܯà;…ã;_î|xþ°½û¸ #Å^€pälwN8±¿öü;ÛÜyZþÒE(À‹Ÿ)¯–nã…¦G­ºåNÖËçí¯7+‚V¡%Øpœ1 -—8YH®ºÃcF¼ò¢µ=ZÕ²¨Iy>Ø›iŸæfè ßKüµ7Ý%^cÇÅØóê ÚÏÒÅÆf’ç4/hÑíþÕ§µÄ°»Aìùɺ£ø¦HA?Íq<¹üðl—?~è—©Þm솉ã6²Ñíîùù̃½8ˆÇ\#ñù(%ÙV†VßuOƒR5º[qéËHŒÖ€%ØvO§.Ö쉧`OINžíà'‘„à§ñOÚ¢31žKª¼95]nRÌÇþâ3R°Œp ÌIJùÐ`eï£ÐÃ8etîÎ> endobj 556 0 obj << /D [554 0 R /XYZ 72 720 null] >> endobj 106 0 obj << /D [554 0 R /XYZ 72 720 null] >> endobj 553 0 obj << /Font << /F34 144 0 R /F60 323 0 R /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 559 0 obj << /Length 792 /Filter /FlateDecode >> stream xÚÍVÏoÓ0½ï¯ˆÄMZ¼$mÚdÒ. †@t\ªÜækjHíÌvºŽ¿ÿhœ¦0M"—8ŠóÞçç÷½8 Ê ÞŸDæþfrrq3q„ò(ƒÉ2'Á(¢a> &E0=½Ú]gaš¤§sRWx^ꇫ']g³ÉGÅ&cå¹f¸¸„ËŠix73#B—¤óÀ¹{šÍ~£¥hœŒ b¦?á9TsI¤ù¶ä¸^ =Lßå K;2Ó¬b 7ã æÌÝ *IÙ°F vñ¥C³®‰E[. ø„­³¥¾^¬,èºf¨™L,©¤¤PtŠlÁêz‘UwWEª‹ø¦É–Oè!eg¥z¸ÂèÐ ¼6#–ÄN`¼n 5¢Ã’qðʱ¢|f4üÞ8}9|‡…„BƒÄ1ªy›ìäUv¨i5±.YÙb°yìê$FyL¦ŒVþ+·lB{À õy9¼; ã(N¿6uÍÁʉ›-©æ–„*}ÖJCF5J˜$»ôØê¼–Ï×vÙaÛíñ§ávã7Ý ¡Ö& ýõ^³úa/ŽY­4%dÁ¬v÷DÇáʶf#;º½]Ölã¬0Fq–øK ·Fõ·Œ¾¶„ÜÌs€F±z·­ùvÊÁst~·†Ûóã¾{n Ô9ª§‰µºýJu¾ß¥}ºtìØgkųâz9ù »œ[€ £ãþSÁT½hð·¦aÅŸ˜üü²\!ÃZ¥ªðww»Ú¾ÐtÜnÿgòp³Ý_â~åGº\åK¸·CQ¶Û+Ãx)£d¡ÛWûÿ¯–èÀs„eÞcÖúáeÓrO0 K±¬_]¾º[máX/B³n„þÅÝ ­™:Ìí\-’;œ¨ƒ†pŠy&¶â—Fü[ÑþÑÔØ³{ßNŠ.˜P¿xDû‡4.;ýŠónx¶È ¨.oóaÛ2~î·2<œ?*¥+BuJ»C÷ÅMœíœ§i²;qÇ£ ÆÊƒŠ2SFšyß¼›œüøŠ š endstream endobj 558 0 obj << /Type /Page /Contents 559 0 R /Resources 557 0 R /MediaBox [0 0 612 792] /Parent 547 0 R >> endobj 560 0 obj << /D [558 0 R /XYZ 72 720 null] >> endobj 557 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 563 0 obj << /Length 1214 /Filter /FlateDecode >> stream xÚµWMoã6½çWð!YÀÒJòw€\šb‹v/q·hÓ`AK´LD&’²E±¿½¤8CK¶œCÑõÅ4=ÙyóæQŠzy/êý|Á÷O‹‹Ãa/ŽÂy4{‹•YFád8éMæ£p4ŸôYïé*(û‚q2¶‹ëþ‡çÅ/½$±.½ †ã±³z,iÊVoÎRžS·+÷ÍxYi·,§Ê-ÿŽÆÑŠIÿ0ØŽÍ~\G š¡FsÈȜϫ?˜^cn· JUú^LÌhÅö4ƒ)ÏÍIui³V<›%˹hÏàˆ5%•p¬Äc}96(®J"€©¢m­! Á“iÍgPì‹•LÃq¤ÞùF­n{pºü²Ù½ëß…ó'îìôý–Šòô¨³´€p@'Ø:´;l“Ñ”{8%`tUÒ¶—ླG™Õ­Û”i¡ø €µúzÄÔ°FU_Y4k_;ˆ<ïCxµYú'G˜ì­÷Ô66™Xe¤ïÓ,§ª³»ºm?íÞhj¾ó6î:TÉ$Í«‚˜_³Q]KØ^2ó\«íóe—ó7Œ&IÆìE5›Û$þÂ팙+Q› ;„1G£œITËô膤oiÁR'ÃØ˜¢±å¦ <ëy½Å{ kɈՑn×{ã¾*¨5<$ëÉä>&’‘t>ðlã†?lË4ðÖŒÈ}­˜y9{¹•U‰º÷Ân úHÕ%³dv»ý“[µŽíÎ@ØI÷®X}Etåb§…´ïbûèC7ô0@+œ hÿRä_W?>ij^‡óñ8©ßUçI˜Ì†æÁhF3ˆ?ž·|îÿEÔü½ endstream endobj 562 0 obj << /Type /Page /Contents 563 0 R /Resources 561 0 R /MediaBox [0 0 612 792] /Parent 547 0 R >> endobj 564 0 obj << /D [562 0 R /XYZ 72 720 null] >> endobj 561 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 567 0 obj << /Length 1220 /Filter /FlateDecode >> stream xÚµWMoÛ8½çWð¡ °T%;vœ,zØ]´A{lÜ^²Y€–Æ6‰TH*‹üø¥¬Šrè,¶èB}pøæÍÌ›Q:ÚŒÒÑåQŠÿ_½ÿ4޲49OϳÑrí–i2ŸÎGgé"IOg£e1º>fb|²t–WBž°Ùdvœ«ªR¸–+mº•ZwÿyqËs¶»zmEæ×6™»köyÜ=¨ø“¨šêäfùÅáaÙ4™žã‘·ÿñH©$;xl{ɾDNeÙY’-EKÒs<ûJi4qÏæb÷"½büC5Ò" ®¬¸Z+Ïʲ[l4¯·¸¡æÆ¹é.ìÈGi¬æÂÙMÐ<%‘?s#‰1PsÍ-”Ï{ €ç[ÏãJHn‘I>ð²¢5ÏíñµV"<ìZ«ºe›v—ÂX(Ð{¼g¬’w¿Ev ûZMNöVÏ!ÌÐwŒ½Ãã$¾×ï‹„¡£w ÖeÒTrˆ9Žå ‹Ë++y†âw2†ÖK㊼õÐ ¯`ÆíZé=gÛg:‰¡Y’A¥ ÐC†!ÒnÄFеp>ÚÎ.›,vÊЕʢ³þ¡ýu (¡Øḟú‘a5~3|±3®YyCËbLK!×¢D§¯UcÛ«››éYr69zðéu´Gàê$¬±uƒT]ºè…ŠëÉ6ôh¶JŽ×À}LÄz/¤JR ‹ý´2b¼P`’¬$%áN$]DK2\ò”!à¨Ì8j»w®jÈÅúyàB©Ƀ•*}±ñæb7•$2Ãq~\5u­Á—Í“(×D–tbUuêÖ¥í¤mnCJ´rûó²vÉÚðˆkÖçló–/ìÒ_÷+åWkŸ× Æ/îïâý«K6TFÙ!"E ÛRŸ~ZøNê‚#t_^˜÷Ú[­\K[¢GþŒùˆ`¹þØ[iE´K<‚äË'œÝ† »£Ñ?]šLCP.CÚîäîgQ•ülT¥t½yh0F+X×mñÁZ«ê nUê;µÁÔ…"ãJD‰ìµSØÃî6ËxQ¶ÃK£ú`-†™ã’®{ë›M›„X‹&¢ »9b*ÍåæPÅ[e9flªÕ~“â:7Òˆ)œ(Ãdé8eQ¯©~&ð©ƒR/áÂüÚiHp´W£5QðæÞzŸ Íj£USÓmîeû ö;þZhƒÇà –F;û( ªo¶D< ááÔÉ«šŠÒ“t¨bö¥#ˆ‹ èÛÚ!6ÝtGbBa*Ä.±æQå¾Dh¥¸£f‰!ó²)È×€4#þÞ„ìVh’ U›e雃cCŸ¥eé·àô4™Î§ƒdò½;zvÛ]©ä†ˆ‘¢§|û:Ç]i–Ü˅穃gê;2dêÚ}¤~N¬%ÁËÀ@ ; ~˜uŸGßi¨†1œè°ªûÏ š$ÞÕ;1}Ëï-Jz5yÛPaäíǯ›êÍ1ÁüÔ1AƒUÿpÍäXÍf{ÿï½ÞÍ¿ÿ”-FY–œÏf“öS~2qŸõ™sétîw> endobj 568 0 obj << /D [566 0 R /XYZ 72 720 null] >> endobj 565 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 571 0 obj << /Length 1246 /Filter /FlateDecode >> stream xÚÅXÛnÛF}÷W°QÛ@¹&%Q·Âm-ò”((Ç+rD-@îÊ»¤lýø.Å^%ÅmRT€@qIΜ9sff)ωÏy{æáñ—åÙÕíhäø›{sßY®é”M‡Sgê͘7œeäÜ]¼]ºÁ0¸ˆ5ßnLù[Èòi{Yò<+O×J§û£±Dž )€$1U~c©4(™¢ü&ûBP¬Ÿ{m„ ¬U’¨ÇF˜]ù$Í¿özH*²J«¢ŸÒpÃ5·jîh²’2…%YÞ³v5žÿt~"}H<‰F³¡¼WѸþ”ù³a»Ž¯‹"¹Â.pý¯>”Ÿf…~4<†EÏÁ¢XòØ ¡îî$_nïé¾Oƒêg4øË~õÂ]¸©¤ÇáÉÜg“QЦê.î)‚{2cûÍUª":]‹îKÂføÆw+H¹<ÁBX‰P%*×p`üwÛá^§‚î n «ºÛ´ÓÝ|,ŠEg*}½ÇõYS…ÓCÕiyûnþ رuºeÓk‘‘}BÊ›-¾4—1TµùXÅPúšŽí®jÜö5Xxåm)p‰ÐÏíZKm§9GcO!l³#†œ¦´g­î£›Ìêð°A¡¸Z±)™F›ºÛ6èµõO€ÓÅìQ£ÞiQÄŽ›öC¬ó®£†öl£ Wsƒóõ&UJe£¨Ò4¤jGû‹m‡µ~Ô7K»5°³{Eú_k•b[°ëH]é ^> :õQ}Sòùó±Ü§Ê´_‹”B»r¥Í¡÷›¼Ö.Šö9ùvKMÖŠ†Põ»±má"ÍÓ¦–ØÑä¼yâé6¡{3a‰m0ª¼ó®Æƒ¤ÅbWñc_Œª¾¹÷Ìà:ÐCª X™ù±ót`‹É‰ìF'éC‘ªÇ—±g·Ö/fïç˜ ‰ØŸ{„µ`ÐŽ£þÛGÐf†(ˆüžð«?C®n-ßgó ÿ„ø“›ŒíИ7C€¿õÌ›åÙß1œŒ† endstream endobj 570 0 obj << /Type /Page /Contents 571 0 R /Resources 569 0 R /MediaBox [0 0 612 792] /Parent 573 0 R >> endobj 572 0 obj << /D [570 0 R /XYZ 72 720 null] >> endobj 569 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 576 0 obj << /Length 979 /Filter /FlateDecode >> stream xÚÅW[£6}Ÿ_”‡‘Ö ›º/ÝíŽÔצR¥é<ø nÁfm“Mþ}MlL`&mÕ¼Ä\|Ž}|¾ Wx÷t˜ÿŸww_çs/ üM° ½]î­çþ"^x«`í‹ØÛeÞó=¢( ƒà~û€â(¾oèÅ<éaÎx…e7ÖÖȺ‘/»_ ç~¼ØÈb²à¸Þ/߯<ÿ â ƒ7¥TðOd—.&xD¹€åû'@Ÿ8@º'æ*#Xí¦zEãRdÌ(Îäµ ˜žzâ‰úâ¯F˜çPàX‚};Óƒ”5Ô¼!÷P.ã0Xu‰O½ùBs6Uvw¹þ‡¬óš4Û2ÎGK—1Å”Q’â²4 %N ¼Ö@oýb‹FZt›Óƒ©C—vñ%k¸z§oœhå»oîBDSׄ¡ÀÍ‘”óÓØAžaÖæ70ä5g7H8½P5éÞŒ7sÕ¶!Œúgp†çðt(>µ¿î¤Í¦?½ë7&Äï°â?£ôs%ó$›}™½Ø[Í©tß]–‡o/gÄuà‡ëÐ=ègtœýa§R3¥"ž·>‹EQš?V,³—9)Aƒ¢ÕâZ‹'×êeyíkKl¤$'`ƒ¢ÄBh±£µ¿œ/]1™°³Ö˜ïÀ%I¡gÊÐ÷çQg8d ú²´ œг¶ÎZ9¦ |óêtèµdV¬>×lǦf™f_ÌøÁ€S¨¥uæ€=Å6  õ¼½eäo”n¥9MgsŒÚØv•h†[™ x»Eý–yø¾BGZ_'VlT§î^¸¿sb‰SF)¤ÒZ˜g,Y}¾-!·ãÉ)> endobj 577 0 obj << /D [575 0 R /XYZ 72 720 null] >> endobj 574 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 580 0 obj << /Length 1021 /Filter /FlateDecode >> stream xÚ­W[oœ8~ϯ@ŠT¥Ò˜á2Ì¥U_ªl£­T©šÌjÒ<ðï›Ø&ÉHýñ5Ø LÚ]u$†cÀß¹¯ðïæ"0燋å§8öÂÀß»Ð;½Mä­×?Þm¼CîÝ]}h~oA%W¢ÒB/>ü¯ßÛûÃg¥D?Ømµ†¿,лwàëåwu,Õ?RWÇþòÞÞ$½Xö"ì$ñÝâ¶âÑHÔœêÒÜaµcù`öìÇ ¼„ÙT«¦l£?kt¶¯,LŸ Çšæ¶ à”÷ k %ft6·nnÛ=Íð§fVf4 d}žÄ\%'G² U‡³s„ôèú'êªâH˜ò†õ‹"ÈO“ž±æŸ4ce¥üK‰Pàë à °·Ü# ,÷ ‡·´øÆ\! Pú&1fR 5ºãV²šÿÆ»›¸C%w Ë/¯ûYY¢Ÿ·£Áy§º,Yn˜ŸÛ¹Ù ‰iƒV7,•ÂmB8KiÂŽYSÕCÇ”aQtI•Ì»yÛÕYèûqÔÕ7~¸ Ý‚6;EÝ÷káø(êT iéZt¥6âìö)s7ð}…´a诒ÕhŠg®‡½îç~â É-È dŒR”uü1Œõ\³æªYÃdÓ9-?ÛØ¥Šúón„‚ì òLçšmÎëyMªGMÓÇç5 év° *Á™ª?7SDøÙ‹Tí"æÌ“œÂ@z♩ùOmg¥[1·#¶sºœu¬pͨš¾g Mi*|JÙp|AÐ9þgà—Äÿ‚¯û)r½¸Rû ‹IIXDÓQì¤' Nîk&ƺŒ>'y®[¿8ºï¥å§pÛ4æ.I¢æc)ÜE~´Uo6«µb#£d;{þ8\ü_"Ž— endstream endobj 579 0 obj << /Type /Page /Contents 580 0 R /Resources 578 0 R /MediaBox [0 0 612 792] /Parent 573 0 R >> endobj 581 0 obj << /D [579 0 R /XYZ 72 720 null] >> endobj 578 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 584 0 obj << /Length 1295 /Filter /FlateDecode >> stream xÚ­XËnÛ8Ýç+dшTɶüÐE¦˜ 2AÛ…]Ì"“#QgdR!)Ç.üñ¥D^êA¥ãEL…Ô=÷qîƒ½Ü ½?.BóýÛîâÃÝ|îEa° 7‘·Ë¼õBôôf¥’+® åßn?Ýß[Êq”(âQø˜àÊ@ÒºÈ%E_Þt‰HD9ˆ¥¦)”Á›¶%®ji"¼œ~©QÊkýBûx°(‚5awéì6`w5±K¨˜¬,ëÁÙ”‰h‚ÅØ¶Íà¡©êΡ(—ä¥vEE‘£^s²wì­¬fΛJGþ|.¤ @B¬k£…#&SsìÆ“»º*è[ã#œ¾_8”Sãk˶ìUZÿÇ{-)ÎzŒ67‘ú `¼Š€­DÄó7äÍûÒ÷Ð^MQ*ù¡dÔGRÄOΕðíäëߟþ¿ áfâBب;`¥‚P^²Ë;ùbo€èìßžýäì§gŸýÏg_üÚõï/N` îbè8E½GÔçjÖCÏ T;kâògg6ãôÛùê}ú㑲×IÈwܹ#»NŸq¶wo§Jû+‡»hí©Ký&ŽgÍOÑf„‘çÏçA¸6Þ^.¯ü¾»øûlÈ endstream endobj 583 0 obj << /Type /Page /Contents 584 0 R /Resources 582 0 R /MediaBox [0 0 612 792] /Parent 573 0 R >> endobj 585 0 obj << /D [583 0 R /XYZ 72 720 null] >> endobj 582 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 588 0 obj << /Length 1355 /Filter /FlateDecode >> stream xÚXKoÛ8¾çWð%BUò£¶ôMÐrY¸è!›h‰²¹•H…”b§ëýïKY3´HK PhFœÇ7ß<è(ØQðpÁónuñé~2 â(\FË8XeA<™†Ëå2˜G‹0šÎ‚U<]R‘^‘Ùxv)EþÖ®xÖ>I ßuûÜðW&þŠfñÕóê€L£0Z$ž„³é²FÊÑ5žÝtÖdÔ.o|])×eNßp›&EË-ì©öIÛ‡f/5 ¼'³£)KÀ«£^‘8šE—«-¼Ÿq¥«3蟨‹5u1ž½E½‰D¤à½Fsäú¿ÛòÄÊŠ²zs]ùÅ”lW£Þã"ã‚Woá0¸LwŠWà!4ý‡&PXÐJñ=DAÈÊ}9爅ÌÜãœé>ïÈ­k€¦…§Ÿ@”v¼Úºa+)ÆlͪcÐÆÂm¹Ë]²„gà™N”•±ã)jËyÁÁ'ÃÓ(e­sؘ/ˆè {!;Ç-ÁM¶L>OZ­¶VËD5©•2ÞØ*Êœfƒ¥>$ÒÜBÌ» - òº„Åv(þÊTÅöp QãoØ€to²®ÊUÙPq–¥ŠÑTPóNŸàä"'œƒ#R>t…I‘‚æ-ÁÈÚ(úÙÏ6¬e(XºahR*–°÷Ç*,%R¥½-¡Í?}æ 9}±:ª;=<:ÀútSÐ\´îƒrÚáË4ÌýPf5(³.KôÓ§bƒÒNE¿!#Í2–T¶n`«¸ÅEêa äµÙ餇ÉjõÚàµÁÐn4štá ÓžâS|•÷¬Ád 9D³ ‘aûD§±}ÂÊÊ35§Ú‰’ãÅ«ÅvÅ4_ïyΩzsÒ¤Œç¦µ,°§œŸØàâ?À@S¾i×_~ë㸡ù®é†Ýœkx"/ϸªdu r{ wv—æïfd7ŠÓ2³Ë¦Y#­Ÿ ºÍ·çç£%³p>ž» ÿij!ä†H¹)+¶)äR–$3­¬ÃŸŠ™ ›§¡W]^ú²q¶Éߎ)]Îva¾Óêi)µn2é›>e+Èå Ça†QsF±ŠÆg­ÈúMËBªÒ GÝtœ5¥ÔÌ–àp¦dá%ÁiÒàÂ6Ë:ä>K{ûØ·Ì“Ö‘á Žò„„{&›ÃÂï&Ø+‡æZ¶Åq85`¸©Ç ³0™ í ©.Å䕿5s'eª+s‹˜µ®’6Ê÷[Ï|jl›º%²‡TMðqV#ÝSX’Šv•=/êâ¤èLL§[:¾ŒCIlË<–®u_ ÝÑâABŠ ô8]³‹ù»f{Ž[½œºŸa˜¾k桾Q².qS$ã{Lºªç&2êk?ÚLÉ\³Þ¾³õµvÛ> ˆí«sšBC·à‹W`œú÷5cƧ˜ý7ØsÀœÿmG(Q£éy¢Wx4ÿå]ª-WPL¤Š“•xÍm3ØB6ÆÑßqÔ;²£•«žØœ”§’ù“<˜l{òö<ËLuÈ©­â¹px”ÛSÏÍRbxpÂë™øø–§äÎXÍÆõ`&µ®ÚD·¦¤œn¤ ùµ×‹>˜‰û ¥õp>Ý ƒƒ.ss‘Ú èîÔúD:=v𾓉ÌëBàagŠÒ>Ã>f&^4­b9›¿×ÌgaņQ“0Z€]ŸgΙ¯«‹ÿT@Ƕ endstream endobj 587 0 obj << /Type /Page /Contents 588 0 R /Resources 586 0 R /MediaBox [0 0 612 792] /Parent 573 0 R >> endobj 589 0 obj << /D [587 0 R /XYZ 72 720 null] >> endobj 586 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 592 0 obj << /Length 935 /Filter /FlateDecode >> stream xÚÝWMSÛ0½ó+<“0ƒŒíÄù`†Kè´Ór()=Є½vŠd,Û™þøÊöÊ_ zi )Ò¾ÕÛ·»ŠcÅ–c}>pðÿ§åÁéÕxl¹Ž½p®µŒ¬Å¤Z3gn;ßZ†ÖÝɉëøÎ‘ÇÄ÷ü#™gIžÔ“‡\eõ(¹Àa¶†ÍñjùUÃwlû“šzBS*O’”ª·Óü™qFÓ—zÊD$Ó Í˜•ây•WÄ›ÙÎM—Ÿz¿€-„1Äõìü]ãm1¯!~*ÃÙ>Œ;ŸV8ÔÞ28ÑÔ”³Õª²çÛ3oÖwûJ¦õV Áº%”ᚌL BÀ!´ÄV']ú¢ëAœÒíÉûŒ2a×…nî‘f•߇¬`!ñÀX…†¡!ÆY2±»SÓR H3€²+T×µ'¾ßgsiÎtýo©[Sƒˆs ! /,8#éÕxÄÄã¡4ž9ýpŽ‚¼ štPn sz¼ë°zSÐ7ïô|GÐ×?Ô–eÁúŸ*zò¡’.NLIØ$6 ²×¥rƒýÖLú‹»±ÞÜ–ëŸËuÒn!Jmf»sï?“šý!Z³ûb›8öt2Û[‚ÇÚbWhwŸª=ÄFb$JFg£§zFn›eò/ª™R¨,ÕÕ,ÃË’¢ÑhW¢¯åP#×{ѧ‹¶WU•Óp2íDÙDÜ”è$•IYêL÷Ôסˆv‚Ð\‘`ÚBKÂ~iõÙÊyhw<±ÇÓIÿ‡äppxÔj¼tcR˜é,7M%Ó÷ÓkÕhºúÎTœS2G“umuÖKòÒ=ó*IF(‰RH:3ü™&:€EèJJE ýÆÚÉX®[$b•5%b©yÇ0\v«J´/kkÎÑ/–­ªT¾·ÐŒ/{$ˆƒˆµ¥ê¦úå5wŠ*lëP®Ì¹mƒO‡eÈ¡’Û¿­ Cs+²‹x¹kˆi†Öt­2½MÈ}ÌÜâáo̰Ù*¸}Ð/†—ž´Áº‘X­Wý¶ Vhý‚ØTÀ¢×PûúÅE‹³«7s·k×´,Û»L4*Rk¹¦©¤0ŒR$9—Ûæz£¶Õeôö1‹.Ó¯ q±é[åyS Òž(:yÀÙ#ŽtΜ˜ÑàØÙÈÆFsY6tíLó‹áôÊ—»…ï{åÏwáÙÞ|¬³zl;stu:í¹\üÞZº endstream endobj 591 0 obj << /Type /Page /Contents 592 0 R /Resources 590 0 R /MediaBox [0 0 612 792] /Parent 573 0 R >> endobj 593 0 obj << /D [591 0 R /XYZ 72 720 null] >> endobj 590 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 596 0 obj << /Length 1260 /Filter /FlateDecode >> stream xÚWMoã6½ï¯0CÀÔJòwŠÚ&.º×u·hÓ  %Zf"‘ E9Éb±¿½C“£‹Y õEMrÞ̼yC…£lŽ~ûºç/›דÉ( ƒU¸ŠF› Ã`>™á2§³Ñ&Ý]$T\’Y<» y%íhËì³T,a)KÝì›}ž?ÛÑËž'{;,£šUö…ëà’D³ÅìâŸp®¥²Óì•eÎÆ—÷›O‘D“`6]YäûM|5uÇò<·£‚j4@Åνò¢.ìKÊ2ÅØ w@„Ôv;Ì÷DPÓ0F]H..¿JQiE¹Ðî0ªœ!Z–9Ǩh‰Ñs˜¹(km‡™¢å¾£n‡¹sEïeÅ|Ñè¸Ò šHÞ…–ÈZh„†.V,g Ìh*^ájé/Î W¦ Q[æ¶È}˜Ò<1yçðJس4ƒ•¾ä¦¸­àb˜¼éÂ}Ó¬ñ$x˜¢ÅËêœÂÛr†d릷¼¤€]{ãK¾¢1ES^ƒ{Ë•Áð7N§œLƒƒ¾Í®Ê¸Ò.7†èá5MÞ’œ'GF‘IKÈ_¸XKM]þ|Á3;ß‰ÞæGA׊S‘½·õÖEã¶Î™YØ‚mÈd#|J$v`bܰMøkÇ[¨*;Pì¹æŠ¥§%ÔØ§M¨”¬KGGþ•¹Y"Ϫ[nÈlg×nvÇ_‘Ë¥´l· tËNöJ DÅ —' BúaâÐV#7âT°¶~vX@á8ÇÆÇÀë$ï°CVÒÅVUý”Ñô‘&`§_b?aý~Ö:ŸÉÇÿhRHAÞ5k^É'U-‚h÷ã³Tîˆ'öV]⺞|ÖCy*hÊNbÛðЊ¥Ë6­*.2TI6½À¹ï¬xBÔØÌ€…4Úf¼Á(j,„qËÕcÙ(!Ík¬™$µjð™S<Ø¥’¥ 6îÎyÕPŒº¹ªTôîgÏŸý±P2­“Nö@9'äü¤ ÕUãŒ`'Š‚Às¦Aݲ'!_D´'›=«0[ 6,[Ö 4K¯°¦‰;FŽoFèn­yîƒý GêÄYóŸ <â°Áó¤JO…µŸ’~Ø+ž ¾ãࢶǒxy¼Y‘Ù4ˆVs{úµù9äTPåsý¿~½æí‚ùGE3vå1qG÷8_ž›qùÔøÂÅŽçÎÿ;Ykóv43 ñ¢_öëa­o:xT¦ÕönDpdsâ».È ']‡Ú„t6·0÷˜mêÞmò†&<÷,~Êìέ=<•¬ò_‘ކ¶NAµÎ Õ‹CY°><‹}ÂþehJ±²¡"ª´gõÖõÅwVíκ‘â\Òj½s |¬+ݹCú:i9ĆÝÇz÷HÔwîqÛ´Û—^Œ=)ǧå b 7Þ~i=|÷ŠñäP­ežË—SŽžæ©Ë+ƒcáþÝ‚ ÕI«þè_£bó#€86T}]ØÆMs—hŸÆx¨^ Íe‹œk!²ñø,y<úù¹.ỬB Þ³ä©iE ‡…uîgdz÷ü Š  endstream endobj 595 0 obj << /Type /Page /Contents 596 0 R /Resources 594 0 R /MediaBox [0 0 612 792] /Parent 598 0 R >> endobj 597 0 obj << /D [595 0 R /XYZ 72 720 null] >> endobj 594 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 601 0 obj << /Length 1260 /Filter /FlateDecode >> stream xÚ­XMÛ6½ï¯ÐC6€¤H¶µöÈ!-šbÛC€Æ@M´DYìJ¤KRön~})qH‰½é—+É"gÞ¼y3œu£,úé&ƒë÷û›7Öë(ÏÒûì>öu´]Ew;õ¸¹‹öUôûí»áó:)VÅ­h—G}ÿî_}^Ùÿåyº)6Q²Ú¦ÙýN{ùw쌵i"XÇø©ú±æ¬Ów¾ -¬dµ¾9RËÓÉzáZ€u¬—ÓföYG¤ÄU ßJ÷­D˜Â-Ó× ÜÔÁ‚]„Ž~Ü qïÀ.ã’óÜÚ’ãß37ÊqimµŠÌ5iô@1Q1!‰Q¦y>zB8’3¦±GC¼öj”ˆ¥ÂóŽP œž=só 1/òÁ½2¢Œâxi+àzŽù ® r‘ë‘QâdN#TUò‰™s ›‚‘ßùzѶè€Û–У'Ã9N#_Wˆ ºPb?]ˆ0œ|Y‰…¤D­‡* JQx`Q©­k\JbÛ*P=5OÜ(¦´zTÙt3”ˆããä"韊R—îÿ Öoˆrç?ÈÐé7g qh¡xÑ@1çNl‰ðü_R6a·QÉ8ÇâÄLÞy½óš—êKõÃ>ÐXç§PƒÕØtŠÑ¾;¨\T¡dð‘P:ÕXÌæÞ6ŒäZò¨³šoÓ|—»ÖVk½è­¾¬3°VlôÍv§óÚÛaDm!£y~…±{æ,Ê®&zÖùôœBÊØ[{â¬êK—b™‰Õ:¤%8P“ è!´lûʦé…›ÎMÙ0—áÍä…–Q\UјjPÓ!5ÚõÛ†ß[Ä —¤&vfAfN½£sñbgªÄ6¢$èœÝoêle†¤ä1öÙzÝ2S$íÖ'F¶ê,’“31N-&«²EB¸lÀ`‡b¼SJ/Ÿa­ÔOOOì§‘òg§Ñ¨ñFI½ÒíNŒP G`›ÔÑæ?¢ÏW5"¦Âý÷Ÿ~xx€ ÄQ©z=˜ÂO%>IÓ;ZãrßXåÌì¹ ¤§dTjì9`QQkEb$;L×”H›h/p¥›ÆÎÐ&WÆ‚^õêë+ƒú£i\ÞË›¬$Hp“«IOc â°úý’çöDtÎnÛ˽¦Æ1;àçi1‚÷-oG×Eº]m]÷Ÿ•é\ýÉ=_pÂÂòª`*ý©Û 3ªFµùRšM< Ù!Q*QL¡zSœ«)N;b\Ø  fÚÐÛ ë)0fέJ+¾`°·Ý+ýS9µ R_Ï ik¢;±´&'5``~ž•Ÿ×ÚX^0ždÙ&s;¨’ï@ž·jµh egÄ 2ÍgÔü¾`é?!ÙèÙ+ç%ªþÃîã°ï—!w°líÚàä¤_í]gùŸ=ªx¯wŒ_ÎëR%|°hÞÞ-ÞÌÛmà-¡‹ýæÍõßtž§÷E±~‚É·EšgjvY¯Ól ïvΞ÷7GfË endstream endobj 600 0 obj << /Type /Page /Contents 601 0 R /Resources 599 0 R /MediaBox [0 0 612 792] /Parent 598 0 R >> endobj 602 0 obj << /D [600 0 R /XYZ 72 720 null] >> endobj 599 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 605 0 obj << /Length 504 /Filter /FlateDecode >> stream xÚuTMoœ0½ï¯°’ËF ¬ ë‘z©ÔTiŽEê¡ÍÁ³ëÔkˆ?6É¿¯YÑR’ æÍ›7Ïcc´C}_aX¿Ö«Í]ž#‚Ó WÕ"¤HKR¢—)ÞRT·è÷º¼JhF×_ÂÒ c™j¸ùƒ)~ðrÕ &Tk¸]€ž¡)^Ü’Š9ŠK9"Ï`õ”дÈJ”<¥Û*h%Ù"Ó+Yðç3kŸYÃU#¸‰€í‚¦cªQúa4+eÞFR’ \Lî/o/¯⥬ —¼±!û ”PG¦%?r zT 1ööll¥åsòÉ-™êâ¹ÉÃXtVðÄÈôî¾üœ-+R\•Àæ@ý/-,`Õ‡µwvpìyv¸4z ïûþ56¥ÞÃÛN³ao@À^{'¡û=;òsúô¤*ËÆi7z¯ÎîÐ5Ìðë)¹˜b\õPoàú ¬åm`OÎéãÎÕ­ÐÐûÏ7¢{嘇B{{ ÿ}ý ;÷œáÐ`×k âo‹éþˆýý´W3øYÆIü0“ÛÆ= º÷§Ô¤ ¼Ž ÙnG?œqLJàÛØÃðÓX½D3Ü0h_¦Ö½ )¦&ž,Ó…³¹óW !iEivºm*ËøSB·…ÿcvSÍr¾Õ«Ö; endstream endobj 604 0 obj << /Type /Page /Contents 605 0 R /Resources 603 0 R /MediaBox [0 0 612 792] /Parent 598 0 R >> endobj 606 0 obj << /D [604 0 R /XYZ 72 720 null] >> endobj 603 0 obj << /Font << /F33 143 0 R /F18 140 0 R >> /ProcSet [ /PDF /Text ] >> endobj 611 0 obj << /Length 1690 /Filter /FlateDecode >> stream xÚ•WÛrÛ6}ÏWè­ÔL @}SìÄu§™XN'íBÁ'©ðâ‰ëŸï.I”Â8é‹„Ëâ¶{ÎÙ%¬'trõŒÆÿËgóW©˜0E8“b²¼›(>QT*äd¹š|L>¸;׸*wíôŸåëÃÊù+¦'Œ#%Çe’h™Nf)%‚¦aåGöÏÉ’ÉÇ™04yM¦3–¥É ü§J'/ê)WÉÔëÄ5aÈV«Ðø3Ú¾Ž¶7ÐS–4÷¸¨.WÏa°ä÷*tyßuEµ·Z»_§3™ê¤-¶»²ø›2áVx»ù+Á†ïH¥ Jj¸°ÃïÁæô­†pÅöSIÇ6D‚C¢Q5¶MFŒVƒmX¸ì®´•mŠ.xÅ}Bç<ààa©HšMfL!²°ß–mÜÎoY7Òœ%˳‹Û™–3*½$i ×v×w˜ qþÞá¡€K·³M·užÔEûEßv- [£wþ‰øìýQ>Yº¦Ý'•Ö†Àh‰ù©XÈ#žòˆx}@¼à1^8ç@·ºÐñŠ?÷³˜ãuÌñ‚ƒ#¶ ºaò-¼CGYÒ¢æ~@÷¶qm4ýÒ[Ю¦îwíqûï‰iÔ§Þµã4J!“«ó¬ 1úTT±”²ÏpP uä’}WG¥Û08Û|ãtÉ¡&;×™lÔëË©O;)4o _IÙíçÚ¿ôÒ®‘Pû¸¯ÇÒÆÍøÔ/m4>2»çLÀ1[®k(T6ß‘•Tv(7ŠÑˆI¢èÁ;W!b¡Î1ðþL†*dZð¦.d‰ Õxɧ_¸áõèm5Ĥͺ¼¾ñ…ÎÅ-¬‘z]ƒùZò3™Ä¹ “¾‰®„©:ÄÑÀ׸è:ª©<ƒ÷(õ¤¨f„ ~ÕñŠ)o˜œðá‹­ øA·1¢é™êÆ ònØó˜…íèqj¹ÌžÔ€=Õ(÷ÓKÏd€–-Ú¢6‹ëÍÁ`æz˜Á€¸&¹è/¼õ¨ÓGý…±¨°Ú‹à½¯Æ?”Ä6žò[]AÑ~—ôɶh#‚ë+“ómÐ\ì4W{ÍÅÁ¡æâGÍÅÞˆæúñ¨²ê‡*»÷°õðOvîãêÑ  0Ev‡‰›B;TƒÐÔ a s-ŸŠÒœÀÕ@t¨Ì¡Ü[ƒº¶}Üó]ˆ‹/úí(˜™åӇ⌳ÿ]%è#*…1Ø*3™f&ÜqP‹ñ$õ}có.j˜ÄZ ›ßÖZgî’0nFý…èøAa©ØÁ_)¥?Tf’?˜NÌû)Ð_søªLOÝ)ä£VñÙ‹P] çåþ›ñ§ËmÊ 5ú¬Ü†"ÛV=–ØÄB•>…%|üE™_Æ afðÁ¼Zzö9,õpŸVÛyeûîaþþêúÉr]®ú @8%Æ@ˆ¢DGV)zbõrùì?ÑÛ4â endstream endobj 610 0 obj << /Type /Page /Contents 611 0 R /Resources 609 0 R /MediaBox [0 0 612 792] /Parent 598 0 R /Annots [ 607 0 R 608 0 R ] >> endobj 607 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [282.037 606.243 517.803 619.195] /Subtype/Link/A<> >> endobj 608 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [197.164 305.372 414.909 318.323] /Subtype/Link/A<> >> endobj 612 0 obj << /D [610 0 R /XYZ 72 720 null] >> endobj 147 0 obj << /D [610 0 R /XYZ 72 720 null] >> endobj 613 0 obj << /D [610 0 R /XYZ 72 696.206 null] >> endobj 478 0 obj << /D [610 0 R /XYZ 72 697.069 null] >> endobj 163 0 obj << /D [610 0 R /XYZ 72 655.226 null] >> endobj 395 0 obj << /D [610 0 R /XYZ 72 602.258 null] >> endobj 614 0 obj << /D [610 0 R /XYZ 72 563.072 null] >> endobj 400 0 obj << /D [610 0 R /XYZ 72 509.772 null] >> endobj 407 0 obj << /D [610 0 R /XYZ 72 471.582 null] >> endobj 615 0 obj << /D [610 0 R /XYZ 72 417.617 null] >> endobj 337 0 obj << /D [610 0 R /XYZ 72 378.763 null] >> endobj 162 0 obj << /D [610 0 R /XYZ 72 339.909 null] >> endobj 609 0 obj << /Font << /F34 144 0 R /F18 140 0 R /F41 161 0 R /F17 138 0 R /F38 159 0 R /F59 288 0 R /F45 160 0 R >> /ProcSet [ /PDF /Text ] >> endobj 616 0 obj [559 638.9 511.1 638.9 527.1 351.4 575 638.9 319.4 351.4 606.9 319.4 958.3 638.9 575 638.9 606.9 473.6 453.6 447.2 638.9 606.9 830.6 606.9 606.9] endobj 617 0 obj [511.1 460 460 511.1 460 306.7 460 511.1 306.7 306.7 460 255.6 817.8 562.2 511.1 511.1 460 421.7 408.9 332.2] endobj 618 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 619 0 obj [591.1 532.2 532.2 591.1 532.2 400 532.2 591.1 355.6 355.6 532.2 296.7 944.4 650 591.1 591.1 532.2 501.7 486.9 385 620.6 532.2 767.8 560.6 561.7] endobj 620 0 obj [272 326.4 272 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 272 761.6 462.4 462.4 761.6 734 693.4 707.2 747.8 666.2 639 768.3 734 353.2 503 761.2 611.8 897.2 734 761.6 666.2 761.6 720.6 544 707.2 734 734 1006 734 734 598.4 272 489.6 272 489.6 272 272 489.6 544 435.2 544 435.2 299.2 489.6 544 272 299.2 516.8 272 816 544 489.6 544 516.8 380.8 386.2 380.8 544] endobj 621 0 obj [875 875 666.7 666.7 666.7 666.7 666.7 666.7 888.9 888.9 888.9 888.9 888.9 888.9 888.9 666.7 875 875 875 875 611.1 611.1 833.3 1111.1 472.2 555.6 1111.1 1511.1 1111.1 1511.1 1111.1 1511.1 1055.6] endobj 622 0 obj [963] endobj 623 0 obj [445.6 511.6 660.9 401.6] endobj 624 0 obj [611.1 611.1] endobj 625 0 obj [547.3 470.1 429.5 467 533.2 495.7 376.2 612.3 619.8 639.2 522.3 467 610.1 544.1 607.2 471.5 576.4 631.6 659.7 694.5 660.7 490.6 632.1 882.1 544.1 388.9 692.4 1062.5 1062.5 1062.5 1062.5 295.1 295.1 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 295.1 295.1 826.4 531.3 826.4 531.3 559.7 795.8 801.4 757.3 871.7 778.7 672.4 827.9 872.8 460.7 580.4 896 722.6 1020.4 843.3 806.2 673.6 835.7 800.2 646.2 618.6 718.8 618.8 1002.4 873.9 615.8 720 413.2 413.2 413.2 1062.5 1062.5 434 564.4 454.5 460.2 546.7 492.9 510.4 505.6 612.3 361.7 429.7 553.2 317.1 939.8 644.7 513.5 534.8 474.4 479.5 491.3 383.7 615.2 517.4] endobj 626 0 obj [413.2 413.2 531.3 826.4 295.1 354.2 295.1 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 295.1 295.1 295.1 826.4] endobj 627 0 obj [606.6 816 748.3 679.6 728.7 811.3 765.8 571.2 652.8 598 757.6 622.8 552.8 507.9 433.7 395.4 427.7 483.1 456.3 346.1 563.7 571.2 589.1 483.8 427.7 555.4 505 556.5 425.2 527.8 579.5 613.4 636.6 609.7 458.2 577.1 808.9 505 354.2 641.4 979.2 979.2 979.2 979.2 272 272 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 761.6 489.6 761.6 489.6 516.9 734 743.9 700.5 813 724.8 633.8 772.4 811.3 431.9 541.2 833 666.2 947.3 784.1 748.3 631.1 775.5 745.3 602.2 573.9 665 570.8 924.4 812.6 568.1 670.2 380.8 380.8 380.8 979.2 979.2 410.9 514 416.3 421.4 508.8 453.8 482.6 468.9 563.7 334 405.1 509.3 291.7 856.5 584.5 470.7 491.4 434.1 441.3 461.2 353.6 557.3 473.4 699.9 556.4 477.4] endobj 628 0 obj [826.4 295.1 826.4 531.3 826.4 531.3 826.4 826.4 826.4 826.4 826.4 826.4 826.4 1062.5 531.3 531.3 826.4 826.4 826.4 826.4 826.4 826.4 826.4 826.4 826.4 826.4 826.4 826.4 1062.5 1062.5 826.4 826.4 1062.5 1062.5 531.3 531.3 1062.5 1062.5 1062.5 826.4 1062.5 1062.5 649.3 649.3 1062.5 1062.5 1062.5 826.4 288.2] endobj 629 0 obj [514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6] endobj 630 0 obj [585.3] endobj 631 0 obj [625 625 937.5 937.5 312.5 343.7 562.5 562.5 562.5 562.5 562.5 849.5 500 574.1 812.5 875 562.5 1018.5 1143.5 875 312.5 342.6 581 937.5 562.5 937.5 875 312.5 437.5 437.5 562.5 875 312.5 375 312.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 312.5 312.5 342.6 875 531.2 531.2 875 849.5 799.8 812.5 862.3 738.4 707.2 884.3 879.6 419 581 880.8 675.9 1067.1 879.6 844.9 768.5 844.9 839.1 625 782.4 864.6 849.5 1162 849.5 849.5 687.5 312.5 581 312.5 562.5 312.5 312.5 546.9 625 500 625 513.3 343.7 562.5 625 312.5 343.7 593.7 312.5 937.5 625 562.5 625 593.7 459.5 443.8 437.5 625 593.7 812.5 593.7 593.7 500] endobj 632 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 633 0 obj [583.3 555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 750 444.4 500 722.2 777.8 500 902.8 1013.9 777.8 277.8 277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8] endobj 634 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8 500 500 611.1 500 277.8 833.3] endobj 635 0 obj [571.2 544 544 816 816 272 299.2 489.6 489.6 489.6 489.6 489.6 734 435.2 489.6 707.2 761.6 489.6 883.8 992.6 761.6 272 272 489.6 816 489.6 816 761.6 272 380.8 380.8 489.6 761.6 272 326.4 272 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 272 761.6 462.4 462.4 761.6 734 693.4 707.2 747.8 666.2 639 768.3 734 353.2 503 761.2 611.8 897.2 734 761.6 666.2 761.6 720.6 544 707.2 734 734 1006 734 734 598.4 272 489.6 272 489.6 272 272 489.6 544 435.2 544 435.2 299.2 489.6 544 272 299.2 516.8 272 816 544 489.6 544 516.8 380.8 386.2 380.8 544 516.8 707.2 516.8 516.8 435.2 489.6 979.2 489.6 489.6 489.6] endobj 636 0 obj [249.6 354.1 354.1 458.6 719.8 249.6 301.9 249.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 249.6 249.6 249.6 719.8 432.5 432.5 719.8 693.3 654.3 667.6 706.6 628.2 602.1 726.3 693.3 327.6 471.5 719.4 576 850 693.3 719.8 628.2 719.8 680.5 510.9 667.6 693.3 693.3 954.5 693.3 693.3 563.1 249.6 458.6 249.6 458.6 249.6 249.6 458.6 510.9 406.4 510.9 406.4 275.8 458.6 510.9 249.6 275.8 484.7 249.6 772.1 510.9 458.6 510.9 484.7 354.1 359.4 354.1 510.9] endobj 637 0 obj [726.9 700 750 700 750 700 600 550 575 862.5 875 300 325 500 500 500 500 500 814.8 450 525 700 700 500 863.4 963.4 750 250 300 500 800 755.2 800 750 300 400 400 500 750 300 350 300 500 500 500 500 500 500 500 500 500 500 500 300 300 300 750 500 500 750 726.9 688.4 700 738.4 663.4 638.4 756.7 726.9 376.9 513.4 751.9 613.4 876.9 726.9 750 663.4 750 713.4 550 700 726.9 726.9 976.9 726.9 726.9 600 300 500 300 500 300 300 500 450 450 500 450 300 450 500 300 300 450 250 800 550 500 500 450 412.5 400 325 525 450 650 450 475 400] endobj 638 0 obj << /Length1 802 /Length2 2450 /Length3 0 /Length 3006 /Filter /FlateDecode >> stream xÚ­’y<”ÛÇ-ÙÆNá"ó2„ÆXZ04E™,‘%4ff3Œ±Œ²‹,e Ee‰«d_’TŒB–¬¥(kJeÉR‰ßpïýÝûëþû{=çóùžÏùž÷ó9GIÞÒFݘ@u1T ]¡0L,Ðö8€Ð€ÃÑ%%ˆ£“¨S4úúZtcMXÃ@iGA”ªƒFò ÒØ–I0öi$<ŽXàèDЛÕ#6T< ¤34c2°ÞÚáXƒ~ -$h@€@ÂÓ7ЃDhn1™QÜ©€îe‚¿Ï_K ͨlcÂ$J!3èÑÄRY§,–ÿÖ¯Í1þd2ç½Õ~;©­ã¼IdÆŸª·?¤TH£üj=þ‡¦’ÿuŒG&á)d€ÿQ"ùaHA Á’DÇwÙÜ®ƒ¯¬à¶4ííѦ3µ?ït{ÑG¢ÐO2|þÛv˽­kV:4RàgÅ‹`Yß_3ç_;LÁS $Š ¥ƒp4Ža½–ÒÎ"…`‹XSƒB¥³¶¬HBw* ²u¡¬;ÑÄm•¶‚E©Iù‡DšôH–Ùÿo©…4ÛòßÿFSƒÎªk³˜Õµtà[€>ò?N¼?RèÛ¯‹ã_ÚÄ ƒ@.Èèq/Ô0˜ßáÒ–;Zq`êÙØ‰Z«La¡˜>:ߢ|àAbàÛù±*R>3¸Ð}Ço„…¾´¼‰HÈ‹TcUê[?ª¿‘5y´¥ò%i ™ßq¶ñ»ÝøWtºt)Žó¾‚åUžë¶ù¡X‡2ÕlT-2ç&óZåòW“CØù§.†Wá3¼.¡Ôe÷GýDõ%nÕžœ;;}È®¨s晳ºFƒ~=óŠ ¦â˜Ë·",zIjP‰æ®ÙÂÔf!ÓŸ ßvˆˆJ=´9å´´ñá›/Yêëød¿3Šq/ºÝ3Õu2(Ô·b§\‰ÕîyM©Štn6]sãÃ91#ü6¥¸­w]ôzõ3Fõc¯¢æ ˜»¸O¹íög˜ˆ@Æ“E„éà´Y„g)®ÈìÉ­=ÅwÏgr]^‚èty… ç–ž·ê~Å¥Z<ñĘ‹äU×^û±#FÞJ–i±½y†ö' :PD²ßVÞ©a|[Ë·f”Ö ”ö6.Ï{8\’I’»›Nšì°¸´6þeî­#г~R=…¢pDøD6PÇ+ÐfÑ¢«®ñ£›4ÉCY®ªU+ûСNÃìBR¹’dO—…Õ‡ò¼ÜòÈ[‹|vò×í05…bðbCøq±1ÁÁ̹–A>jxÍõ|Óã‹°ŧÆJÚ{e1_ê5Êw~?t ¶È¤¿Xt?ÉÕs’¦²÷ÇcóyÞ•þÖ[Yê•›6i'?.÷¨=ûÁ¼\þü=Ã/—ïôô}hy?ª9ìð~½7lÉÁ*3.Y£±7¥ »½ßMDá%%C…Ó5¸ÝKèºÐ„Ó.6Ÿ¨·ã1qÄeD/sô¸Ù៦U¼¾uíãìÃrK© =½éá5Yÿœ—4¶±%«7çÒ™ÙqÓP÷éa¤þSE¢¥ö‘iéÃHs“ñá Á+Êzö+B²oýtØ^_Ûc/o‹Ë:ê‰9âèÙëÈ›³ï3{O6¹Ø2÷ƒÀ@)éöøm¦2÷ð—áö{kIo÷çPÕ>ç‘˜Þænµ¦"h(Ôôn—o&£ uvA€ôRÁsœº„# <%‹›¸›C9‰ìc>¶C‰m%ë Ÿö,Í¢eÚïUZÒ?…èco‹Âô?g  ¤:Ë·Qï ì%‰e•ÙÅѪ=¢r»¥”ÇÝh)rÊSóýªUt«Oül¹*qŒËÓ{B›£WIÍør°ôÉȉØuç…{Å2mÃS ÆŃNÂtˆe:w¥L+Ãÿækbc©µg6ÎáR·sQD=¤ûKšfÀÒN5tt¡Œ,®„ÂÆ•£“õRj˜šv^éÀw—W¸æM c¾ëb‚(H“SÛ 1w;ïàÌi~só‹%³}ÚY†Ìï ãj2Óven¥Ü.èÕ´>(·z3+ò›PÈÐÍôîìI¯À; ‚l³½ªÌ ”ÍtÌv3“¼8Çf¬Îj2’‹8rˆ°6ez]ŠÇ{µØø—³z;]L±Pãl¾wYbÆ{±Ë!ï°K ¯Û1}‘ÍÛP²óÜ‚,½žß~ª}L¶¦3yNj§x …B/Iâïq@<ÓU€Sª“NãJ‘–ô+ŸÆ»y Éžâ¦á¥…ë82µbÆØ;â~¿þÖ3`Ï[ÅššÏÄc0á ¿R­p¿[UŒÿc÷ÓûêOáP‹ˆÝ­Ñ´à¦qŽÔ°cü¹þüzÁ…â„M³jðÒ}´ÛÜš¡uÞÉ,çÍ@Å>u=5ɱ«ësw¿žI±ðzì<@`ëɬþ)¯vïÁÜçÐDˆdº×iÏý!¯ó[¡sK‡ÊúÔ¹%ü§] ScLPêZu*¨Ñ`xñÕPÎ÷6\ˆÞÁÉÉ=öœ?Ž\ªŽ å(@¹>¸ì8w|¹ZÃW[Þ² 踀qáo²£Žœ©o›Ý½3̵刷¹¶¨×ÛD“z¤Àñ®$è€|o<¥ð¨®P»ˆM|¬„RŠë1a«,Ç[p“ô—kÆEUˆ!÷ò1e:ŸzÙvÙvŽPl VmŠêÉfo˜ÐsÃÞÍ»J$ã‹.¹¤ÙNˆákUvœU0—r5ãö ñ=›‘« u=Â-6˜Û=p]”ŸPçÈ ûí©¬’A‚p¦ûžHÇzEÃ`èg®}Ñk.SUÚ3'žŒð÷1#žÞ‰ œÙQ…ª~´zºo‰ŒÌp)x]Z*^u¨ºLz¦Ù¹WèSmŒÏ'BíÛˇ$ßd¢ùØs„UN¼|M¡¡ìyûŽñ¹9¯ž‘Kzû¯ƒüv&?Њ|÷äY˜ÆU¾†^ñÇÎr «IceWl•ºìÍW!Ig7ïl.'vì­† “e³Šs ‹.„@E¥ç;oø}¶ÁPì÷NÒ6º¯Û"IÝx°‹³üèóÌÝBÙFáéå„uË:=É즟¤ºPlõtÛÙÝ óÅ;FUP™êR˜—è@×0»Ë©öç§â¿61ekf;§çÐSâÖ+Íc†µ ·/‹Bçõ$Å 3Šd¦\A¸dB¤¯!¼ÉA¹¾üc<=4Í©óSƒ‹®³çwr³Ù‡ntaÆJN¹ö¼—JËÞg²Ê.1Çe*BÈ}”]qrË„w…fÒb‡Ë±ËÈzõ¨TÛûâ;øl,ù×÷¾S²Ú„Í*­_ Ĩþ㟱٠endstream endobj 639 0 obj << /Type /FontDescriptor /FontName /XXBDFI+CMBX10 /Flags 4 /FontBBox [-301 -250 1164 946] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 114 /XHeight 444 /CharSet (/a/n/t/u/y) /FontFile 638 0 R >> endobj 640 0 obj << /Length1 1594 /Length2 9487 /Length3 0 /Length 10383 /Filter /FlateDecode >> stream xÚ­”e\Ôߺöé. iDbè–é.$††¡»A@ºCº¥»¤¥¤»¤ó™ÿÞçl<ç¼}>¼á»îº®û·fÑQ©¨³ˆ™‚AÒ`;' +P ¡(®äYÙÑèè$ #'K°¤‘HäçÄœÍì '—7@lï±4·p0J0ý“Ä ³A,MŒìŠFN [h#€:ØÄääÎ ³±¨ýSáP9‚ . SV4 `jiâ0™[Ú¡±ý£è½ÀûïcSgûÿ¹€ ŽPQF¨H&T¢)ØÎÆ` 2CcSCg JþˆúßÍ¥ml”Œlÿiÿ¯-ýŸ¸‘­¥ûe€mí@€"رûߩڠ‹ÛüŸ1ïŒl,MÄìÌm@öY:J[ºLU,L,fF6Ž ƒìLÿ·èÚþ%€MUO꽎,ó}ÏUŒ,íœ4ÜíÿÓöŸì1ð…¡ÛXº>°³²³¡‰Ð¿ÿþOÿ “²3›ZÚA/7À1rGƒÞ (q<K;SäUÌÆjv‚– +ñ˜!hÿ|Nn›Ø?Gÿ&^›Ä ñØ$_ˆÀ&õâe°I¿À&óB6Ùâ°½!håÿ´‹Ê AëÔ^Z§þB\6‚ªÖ|!›Ö A=hÿ‡ wŽÍè… ŽŒ_ªÅä?Ä ™€m wú¿O¸¸þ9±µ}©²C›þ…Pß —Pÿ¾R/ PKf/mhffùÂÿD_›ótù«á?q°3ä¯~Ðó¿ÚÐâE/t+îö »¿2 g d‡®Ãú/„z¶ù ¡ ±}A ÔìK+nh©¥è¯8Ô=øe:´ü?ÂPõö/aèrì¡?~ð_ëBÝ8ü…P7yB¥;¾Œÿ‡@.yㆦ;B%/Ð/»ç†ªs²€€þZ'Ô“+ø¯¨%翺 —¿jÈõ¯o­þk´½û_5ëñbÚÉù÷¨ÿû8ˆ‹ƒÝR¹ãňo`ÅÍÄ*ÕtL¶¢Î}µ)”wx³R­sW’‚‡µ¸Méú@êÑâ¥:"}âïûmúiÛåÓvŠG#©ÎyŠ¢û–=õuàvsýÔÅ!7¬òÄÊÐ÷¯ºy½é§}Ù*Œ’;ÈKT0\j;Sƒxxu¤Sl4Cƒ«é9©Ôp¾9|ã ]vÅù‡°<ècŠÒÀ¼xnqƽËEÉŠ2„7Ñút-œè޹¡w;|[å§_±áœ¥˜¬]ö`üa‰2 øÁæ<*uŠáÏ[§Éåmö åSyz·Ê(Ä\Å2ár¼˜–M­yTš0U±ô¾c?–sZ,>é)]Q çÎYÈË<×…y­ÕNbE7µ¾aÐ鉰*S™hŸå8åƒçcf‚¥Ëj}“)c«°v­¤ó+ÂÌ:p¨Uh§·BXÞ¯ÔÍ%Ì‹ö¢ñ[äÅ:Hjᜠm|B•zaÝQS,£}bû¢ädnPg}Î=yü¯êÿ”¾–â!½]£¬Ðd¸ÜvÇd2—¡g‹Às~ÔÔ§ÕÑŽßašåöΊ֔T1Œ‰cmoµC…³Né ¹òVX•Yô•¢Ñ%4Æ|¹HHEè];¿º(•éô_dœ¡H<Áag®ÎÃ|6ÃÜBOÍ)‚$·3ÌfýqHµ6$²Sã}H62ÙÑŸtÌNg z Ih' ŸäÒMùÊðšî¥Tá|öÿx^Zvg#m²Ë¬o.´ñ#Æ0 Ó7‡¾DûÔSÄ[ÉkkòÇ&;w/þç¢ù;.Y.üÇ¢¥ ™ ‘ã”WY¾?Q óLH~¥íñ¬éF“¾…ÍvšcÓ'òN–”DgZ2 5+þçõlGfœŒ<é!¬æõÿ‘Óp,VH½w°/ §—ó“=Eüt[‡ Æ’¯R„óõ–pkÐ^È'>ˆà–cл>£ô5Â[Ræ-|–ƒœàƘìaÓ‰²Fÿm&‡  Õ©å«bÁº½ÒhiöÊgŽ÷C†Ò²à>~¥‚kšúOÇa‘æ¼{y›ÌE@±ØäÝßOw#è9ñÝ]ÿèûR'¬ÂÒ~¥’³S¥íDu©q{ú-µ*{—®”R‹ëå[!3!Ø :”/çN#lT5ðpùÈèÓ†<+ûMgg ÙV¨ô⽚çwG†Hqe› *Z­ë"¸J:¤®ÁÍ`Ê6íîàðNË@LûæÓÉZ ;rm®5åI»ƒ&w”î1ƒrc«çn×±H³@°‚#ïr3¦ÿÓæRCFAg=‡XÉP`–´‹gä¶‚Î}ôe]Þm¢oî×îúëc%Ù“£ä±"—^9z܆ä.,•!¹—±8OÉ3öÆùÊûx ³ß!Üë¢&ßÖN™. ß¡}0F¦Æ<ÇÆ!ޘʤk«¡vÏ!3]é~ê¾;=yÛüîÜgÒ…沚hÅÒUiuu5ŽÔ±PãŠkþHï¶w¸¶øuviâpV ðÕC8­–œ~¨˜`m˜`Å/Ù¼ai‹/%…q3Ù7«QÒ@ö2Û©r‹e® ³FìE21öGì>þq·Ã±%- 6¼»(ïäwáL­ÙÍÜ*%7áÄ%€ú+mF¿µ.OSÎGíÆö—ø]ža`$ãgtaU@§Nß‘*¹].äT8 ž*"zΘ÷—e"œéùš9šއS®TOJìüÂ9‘çmHé¯sš0šÐ:Á¬2)o‡ÎPP!†°c#jgÝþj  õx¿Æìl‹§³Ê‰µwOàÔRú¿Æb)+«w›_×/±éÿeÖ¹cCµ%ŽwD¾ûíÔfZ¥uÜšiÉã^ïqö™ï`,9?‰VGìÐãùÄ®ä¸}ëИ‰pÐ'zñŠhã)¡Žpp=”m©ˆH!ªÈÞ³Y–…œiëSò1œ<éÏ9F]t’Òµyæàn¶l––ÕD­ï£¼Œ)ÖxÖ̵FúyW»Ìß[Œ ãWŽ€°©‰V 5I?Ž7ŒhD¶&»cFá/͂ݕ5Œ‹‰Œdu¯Q}$œƒåOÙÚ.vF-sC+Ý$\bjwÑÇŠ+¥øÛ­ZJ–×AWOw}T93¤ûñæÕAˆ³ã¿Ç½N”á!|!Ę”.ƒ©ñ…â¦ðä\r=n §ø‘k㢾¥‹Öo´/e-§Ò™+»WÝæ¦ÖYÙVÉ›àŠëænÒñ©#m»ÚïwŠ–.çÁô<Á¬¼Ú‚$~Ì)ú…ܯ˩†R¢äƹˆÚ´˜Î&L§î4&òæF0ëãà¢Zð]d53â93 ŠÞf·gûé6çŠfç\ø¬¹S©2ö•#ޝ¾uÉ‚eP'š&pÿ[E8.a¿p£ŒU>Z¯Àžß¾¬ Õwog…YC18H€._ĵwöLÆkBã¶aœ_íÔ;ÒÇûœû’RLœofõtš…žB°NH¹ñ²p»&H>½v~F~ƒ!“ÓJùë\ Ù^ø­Ä ñ÷«7$Õø9Îïƒ2c'_Í…\ÅשXUv~U.j>ÿ€ÇTÂÏñN¹F˜ˆe×aɺôºU°±5ìV•œÍ?žâ»¯ŽÝ@‘4m†ÏŸnxÙšŽÚRÄE_ç¥Ë1³ÅHßgÓ5Ên ãß2FßÔ!9õ Ï*Ñìa‘4Pp').q®y‘þî³-`ûæŸh§… ƒö|ü¡ÓJ»–y\;Ÿ.ñ³TÿJ8¹‚lÒû–Rˆòˆý  Ó&A¹¼9³Tl+aLœ>ÙHzn¯\mÀ…äÜ/ÌíA­F©Â*£]#:zz“Y´{“+µ)ö8ñþ‰58®­À8G¨eR­mUÓ”M·>Ç5•æG«üwÙ#/´ü´m Y®é¬ãHö4³ÂÓháö.O‚U3Ë;úÙuœÌH¯Òê|„¹óá$…¬AD&³ÚÕV\Ô:üÓ‘dÒÞ¾:¿À> „ø©lø©Gx7Z-þ1uLù-‚e[”\Ýßs¯‡w}"ùtÔÎ×v[§S¤LGæý=8ì¬ÐX*ŽA!ŸÊ²M ®¦SÜ]39¿Š§Ë±g”97/ÏÇ?Ž÷&û×¾Õüµ†Úˆ)H_¹l°n„Ä׊å¡Å0E4!Y€ë#‹÷YË/?kî7Oq¾}Ï×uô1eïâU„˜ÝT~e˜jAº8 ¡Ý°§:gá(´Xr®[òi\´>òt±éZO‹ÛÛ+žz²Ýg%»~>ÄíÐÆ YD„ÛU5/‘2~ã/8[4»ÿœ^¸s\æCíNÐì¹1º«XøÖ¢Òµ%9&“Éä=¬ Ìap“¬‹p0˜´ž1öŸàOv QžkÂûð9m×쌪¸ýªŠ¬HÓ—[£Ðå¢I99ó{/šÎ°r ©I©÷g×íØWò`†¢Î}D\/d[¥ú䟴6Ú²D}8ã½>Á\r G_o341?ÅÝ“Kü¸èg^516@3€M jĽg=©vy"R‹=`nèæÈ½Ä(‚5ìŽ;víÞ>˜e£“rŒW¶3¨/5¿í.ûñ\ÓÅa.w]¯#xi{hiÂjìÏæJ‡ B„”‚’*—þ!ý^Ü7+x`ùúRÔI·ô”qåa«bËù.R¹Û?hŸXañÇ/®úÃLÛõråŽÌ¡à3°î[±]ò_¿™h½†?Í¡‡œçK«{-ædíâ½-6Å´“·!ÞËu²Ê2½÷5$[£ÿð(]Yc†Iý…Y'(¦œ„øŠ'uÃ1èÍiúXKÉ‘Ùk2½&­‹™¯y *³xšC•xU‰?—Z>puSo:ÆúÍ”ôwÆ•ÞÀO„<‡#»Cö/Ò¦íŸÊ5=Ì‹¥!͹„rÀé£a‹r•©·ÀU†X4›µ6o:¥³v%ûuZè¤5é 2¡Ke¦Xc^¬~j«åÈËq}晿Žf:GcÁ é\xv³«Á`öwÅ+ÌJÖ ƒð=-º‚‹åÚ+æôXËýS›ë`Hàs•- \Yø1ºW3 ³`µ“TM`Wh°9­9%ÿý ÒÆn„~(J®ËçÉppàÂù§v¸dIÀ~ÍJÇ›z=) sµ[õ“wGÏ|qÖ[Nò‹eµ…æì"Dn^8ö¥…)‡MÇ€ {ÊtÊPCÙl ÿ5±0IvÖžõB&-úÝ)‡±‰‚ó|×râGW,ldeœtârÉ-:’ý¢Œh€)s0µõksүɿïT"ý³°Y³¹ˆx«‹K ™zÛöG}Ô©-IŒÆ%ì®,u\î# Awø÷µiñ¨u;"¿JãÏI°ê9N‰#\†Ÿ)ÞU%0»—.›Óê¶—`h¬aLÃôb/W_p1Û*ŠÇ:ð¥E×Ì…OCÞ𢚚ñæ‰à2ªbtRf¬ŽE€±´äñrsð+ÿZNsfÕÜ6Ó•!ã^¯‹f\nžxºüRƤ;ö2˜~%rµ®!äsÔ1Q$“#¿Ìº<ó_u¥.ð y¦ä7JÉ~†–·U/<ðœR`—ä41è¹ º@D‹ ­Ž§ôU±fQ ™F ‘ìdRžû‰÷E¡Úðu_ÿTÌè”õüž Qmh—ažà8êÜ$F@œ×ˆ9‡îÍÜxôé9QÂ0~úÑæ­ßrx÷}´ÙŒq|]-C%LZ­‰ 2ÊûÔ0#mXQýDW¢2)VT+ØN¬_á¼o,àÑ”1+r§Ño¿ÚÔ¨¿t{“câë±RŸ¼Ê›îº€, û,Ú®i}ùâúJßUÈ’Úžâõ’tUü/šª ~õz-\5t"/«Ž›,ì4š·Þo„ L$brKM|“?°í:À…W%?Ht Ï¾Š!ìos\DZmñy¥-ßé_þ”¡OKM¡PGãck8~*ù¡öKhEÊâsÌ®ƒ±Ö×»pK‘ OF4¿CÒüºJ´ØTL‘¥Qü¿ŸfÑÞf þÌh]>Â$ È0Cí¦ü˜Ð ¤OPÌ›Ìk€¬Ôä83¦™²ÑøÞ*Ÿ_8¦%4-Æ$›nÔê‘{t“Z:Ú‡l“}S1i¬œÒ)R]óèW.…*¨ÄýFÉ¥æ9rNtÌóŸ‘çCñ¼fÝG÷Ð|Î]“”Å–"îZ¶Bÿ2¾¾ÀUn¤Ï«m(®*ˆÂ,dë¿ÞÈKvµ–¡2í Iê,€-<ç8Iص?G!¡¢‰=àáT„ñøÞÒ,Iv–kz0[*Ó5Já|Uþd`¬1S-þç«°#¤J¡òKòGs'Ñ–ŸXÆò¸èo8l¼dÔÞÆ- d!7rùá÷VÅ‘—Õ€ ýfføÙØBXÙDÝz|§ÑÜú’Øî¯§ùŒ°¤ÈËNãà=2â(žpé ÈoÛ6'6$§Ë‹ *2`leQ%òwxùXí_ñ½öà=±‘ùt|öÓ›૎µð|Ú9·Ú¿A27Éõò’öÜJ\Ã%Ȧ´€Fàû‚QÜŒœ£dÞb’sÙº%s¾ŽçÚ<ýÎÁA¡á×_h©Dí° Ð¶XŽàÇÁrøÃ†ü6—ž Éj&‹ö· ìzI>c Ò£×eM$÷¼G F*üj@ ê¤LFOÄgZŽ'^™üáü­Õ݈uøÇkÁ×éHxoˆ $·6f:–äS@÷³ eŒnªE-Ÿ˜XÔä' —EW&ÌwTœ6^5˜Ê ÞX¶NN[Í=åUØO¼k¢"òsäfÊWkJ{hÙtÜ9:ñÎ3gÌôÀqƒW ¼v6Ø©zBò—.¨[U‘ƤzÕÙlÆj‡«þÚbÆÔƒ´vTx† qì‚=n¡Á¨•Ì]Æ£ÚF}þñ& •ºœ¥QÞÞa‚'á=XÂPŠ©I·–-D^ŸÅJtlÆ>þŸ°ãŸ‰ËÐöl"™Ð£}Òü¤4æ¼ð&ÎÃ,.k¢Y<Ú*ìµákÛÝÙŒ‘7™«ù¬5ntðⶉ€IÁ;‡´ÅdÄàÀÒ­=Õº”_âžeyùÌYlf¥»äs<ÿèU•?ÁBqqð݉öã ®£ª!5d2;Hœ7—ò=[¢¬ú1½ F5¡/°7<±`guõܯ<Í‚n˜úÇ£ø¦ů£hã)Õ¤Kü—ë fÌUµeÑ…!V=wýñ¾užþXf  ÷öCœ.º 1l)ƒú€ÒýÖ—‘”÷LˆvÞ¯ª(Ï=ÙûT²އò½JÍáÜü°Ö/,L¼Ð·±=0ݳi( Y¬ÇOgÂ:fŸ2K¤ sõå *hLݰꋮ¨º–¥ÛhØáá5ŽÚ0USQ?Š®VíÃÕžàÿLÕ˜‘…qHÒ^q1мæyNr>‡%2ȵͩ“:â8{Mçv¶ÚñÈð^p†3Vø)„ÎqåLßÎ1€ç6ÈÊ|B'öõ¨£f`DÐT-¯-xçˆôsì%·ì®xÞÏò³¯¼B$æ"M]‡N&d3½R&~ÞŠï!Döú#˜û0õèF’t™þxÓsÐXóûá²!˩ջÂͼ•kuTØa¯L‚AÅæPPö|À‘ðÌ×wäyNóD‰e•¦°½Ö%ÑB­ñ°CãI‘§å ïÀ…¢®v~°>E™L9T÷¹©jÙ)¼½‚L"&Õî ë˜z7enk©#¬Ý_ªRåÓ{P¯D›G¾ u£à5îÿãòš…,÷8¤ãªkñÒNYdÚºc£ÙkZÔè¼Ê+‹F²ÀO"–+äËÁ‰G²kL²ÿ¾$;‰.hæE“(÷!÷ƒ¯nay¹­F8­ Ú}EÐ8ƒ²xÝé“Zh¾îoúîçA›§öGüý}¶9=D Îg½µh-Ølýß'!KICc¦iÙ£¡î× F&Æ™ºh<îBõ9kó :ÆkuvpâcÌÇ¢œÛŽ^¦wWMxöwTnW+œ W½¨ X­F® eÕ¾o® vžb/4%\8 l± a[Ç"èÎ+K^ñ²‡Å繯o4`«$nM¿vøêbKÒgi„Ç:¸‰úmB\eÝëú5þq…ïw±ª¢T6®j®mý¸zeÙ·IŒ—òð­BÇÚê<¼€9FžµD¿£jôi Å”IB­KN¾×<¼Çáäåî‰ñ”T)g1‡I°0Ÿ0Õ_—ÂË+=„{#=Mf÷'‰p½¥|³eNtC(ý¦ãHm0$§SUæMK{ìšokÀzÐAõ›1ÒµP8mé%Û|ŽÉºÐi×cý<”.åöKű«NVwï.n´2]™9´ÀHø³>}¿ÅÅžM45œw£ôeß0ùôÈFÀ8öú¦ ‰ït}Þ@(Ã~)JðÂêI+~p•ëea Fô uk¸âŒ¿CÚ¾±­ Ú7Ì÷wüV|ŸÂ´/ô- ¹­j\üx¯«Ôbå§©hžËœ9¨À%}IèA—ËåxFĬ﫺»zôvÝÓÁ!þðˆ_DçÍ£ÑòÝ- õ°UÆà¶Ï}L¡v΀1"Ê[Ð&£ /@1í}È:ú¡òÚÇ·‚ë~»p™Š|­º”ûÜ óí&"*¯¨F0aŸ$¦ayjdÅút„ˆá)ª±…>›è4…óÜi_=aÑ¥[ûoª±hËãb_uÏßõð3­ŠwÀÎbpqOUm»1NëܨüÁ;G@³¯Tÿ0{—”µ|a3áÄôMŒòs[2YAÇ=üyr y¨Ù0WiôWÌÁȤ?y¡Å£át\ýÏÛ.oýa\'ÎÆYFq¹§õñ±qSÏ]NQõ $ûF”ôMŠ)@ð^TÊþ‚۞ÀØê×ËÏ;ÆõåüŸ_8c¬2ËT–0Þ¤1äõž`º*ï`ó•—}z ÙŽº‰=>Ž0ý{}+_>4‹ ¼œ2Ò"ˆÂÌfr¯`YÕoÿ•»%ú­‚·ì^Û?²"(Ûº°³˜ü³þ ®¿ÅX-Ó“bb-†ä¶­‘Tˆ蜊\SùSUéªøun3#ž/º £ë›8Í|°Kõ*©Æ7‘á)!¡¥ ý ¨j\Í r¥üLIWw½Aù󸩥ÎyŸ‘²•¸üš~›;£Üµ¢ªQb˜¬I+æ¥Ð_ƒìýÈ‘D‰ÎT±sÃÑÇ–ùô™ M3úWøU¦…àôÎ{îÓ·Å•õT õ1&Í¡)v”Ý^ÚiÛ—jT¦«óWûsÃMjž}o‹#Ôwrýçê*ÉÔÄÊÝXI¤ÐŽR4´ €léÈßy"Hú;(~nXi³çÛ»ýL> –ˆ´‡_¡´…!ê½·q-  ýîÙ££0‡•öÒNбùfëpL>Wé§M4Zݨ^²š¾k"º ß1g›6H>»ïÊþ‚š=8«”oñsƒÀüÇðªÓúyÆž­´t§/ì“õmÛj’½…1XðÔ3°z"öÓóš³nÎMÇåøæ›ºûõ%¦ H,ÇüuHøEÐ[µ¥u ¡ùÇgÁ¥Ý´‹õŸðeÁ@’?É<4@=‚Þ=-7Ó!ÿW}„ßã‚Ù‘‡6‹ ŒŠù>@n!þûI_Lr‘Ò öK Ñ„µ±Ö?)ORˆÉvÉòÌ=Ï–©NÖ{®1žþðšQ3÷2­øÒý‹N €…”‰û”AæÆ‘F­ùþµJÉÆ¥åá°Ò5•èh\¶r}ØÀ°¢ÀXY:èlHI'*ÁEÙ3Ù¥~Låûû'ªÒ;Îûïò• 1œ›¶-ѾÄQQŠ=z„‰¾y©)27¹wxöyrøO¾_,×âí¶]fßµ„ÀÜ$¦4¬t_W»Þç·'ŸÕΩ=™Ov ‘ÒK–#»ôÞÚfº»Ì Ëxo.0’ß,ŠÝ:ð ñvZùŒZØ'\F6-®óÔü9ù¤Kó‰>YÑ6ð"‹Ë„qN,Ò(ìÉ›ÔuŠ!Š'`bmK‡T¹çFÔõé,m¨‰tæÏITðIF’@%†6ØïHå©Jwd .ìÁü¹M]Ù¥OÙ_¬°qoв•HItW¢€‡;•x¨µ¿o —¯÷O&hÉ–£˜ö±ç‚¶Ã··Âk»A~êáÑ0H¾tÖí°Óu{©QB{ w}c6ˆðd–æ$Šï{okNPÖÝÇZЦ.ÆÎßnjÒÞŽbI8³YoÏ’5Þ:«³Èçb°ä,?p’ ‚ËYç|2ÒK€eT¨ó[cΊ\b=ïh:øJÿÄ|ª'/|¨1‘TÚZ¸@å¥û,g{î§jåç#Sx1Üf¹€=Ú3BrÏSt} ð°ìD¤!š3ì%ˆ®ˆp¥ã1Ø  ‘õ¼:±!ä,ä¾s"÷¶G´OD´Iu—ÓGUéäX—lO’vßlˆÊæ§-ò£ûýGô™—[k»1í‰Lñø;¿ñb ¤`c×?"òÇÉ~Aqk9d“Š_ÝYE²Æ}Ϭ,Þ;ÖÇØós¶¬ü‘òh¹&‹vŸñIhË¤ÈØîŠ_C“ ñ*Î$¨z¯ôzžF­|¼‰oíFI}g1¦ÉoúökÉùq3B®2¤+eÇáY×£®êó¿qZÒüºR%FÓé¼i¦úÛd!»Š†e3®aÞýåáUÀ´º›^N•Ù®ÒºÁ, ß3üÌjÈkétYÒ‹ˆi6£5Ò¶78Eff2ikþŒi2½×0CY'„WM"¿+#uKð…*@ Ø…Þž(È’ñ3µ8ù¸Óë?A¾ÓúÄRO ù# #€‰íæ¤kï ,…[K Žry™©¯`éæ:Wø|Ò¹zk…D\‡æ4‹ !+Rí'ì-/ÿϽ²þ“œŸŽæ—>ðWÇš}Αg„áWç‘Mn ЮÝ÷æªNÊû}}ì²ðîù› UæërGZišñ,§Ð¾»o˜ÒŒww°±“—…º¶í(›Ìžj¨šJ}Óa”€3ØE0±™èt?fV6šÖ C|/•„λ¬Ý™vZJkÉÒ: #ödBi¿ÈvlÝŒ;Ë8…:PoŽí×7vø×ö²ÃÖ¾3ùu&Ü8ìÓŽ¬6Í´–t àÔ½)>è[:¯v4ËÁbš¶KïJ—éážýí÷k›ò//gÒn:úyßÚEü¨jÓuíu+ÉI•ç#¦hÔ”u=ó"]‡¡Qg }Íü@®Š±.°±K:¯»ü‹:r¯)­4ƒ~¹–FôÖwz„ŠÎJêkåjVö j­/D ªûËGasbÙwí:ò´™}hUN;¨ïFчb\6í=ªü!¢1±4ßûáÉY{ú¶ûíøRò:QÝ­USäH¼'ÞŸÔ@[ڜׂ€uºm±6äêÈXTa}Î0Õ,—ïาOˆd]O X”ë0µiÝ7œ%§óc)N1¨Gû=ªãVrötÇ´íYºxóf{÷‰Èú®†ßƒ“³Øœx£ÞC2ŽÍ9 já£k# Õ³ú­?÷è’ Qu»a9NZO½ÑÐÖÞÜ7‘ª«Ì…ØíüödP¼Õ—#fÁT|&™9 §·¸!DÖBá|5Eʰ>ý§}>=Ò’Gú*Õ ¿mÛ}¹NÍc?µsg¨8…öé‹t"¡:xªJ—çÌÿš§Ý—ëô11•-}“<¯‚@¶Íîîʇ¦û’Ï› U„1•à[÷ ½Þ,ê{ò¼ò%íå%G:Q©È·p³cVÖ˜C‹‚(f{Pññ¨—/Í×_E‹È(Ùæ5äËÅ1§Tþ†Ãê[}ÁƒŸ"AâtèõÑ«¡ —ùxŸþô$0 <ºáça“ªºì~jÓ_ìýE~Û†‹À˜Mݾ™qúdù‡ê]üG[ºNC8¯¨Øž´˜'“ÖhÚ»ëAÐ|–e0éïæ®nlœŸ?09dŸkÞb#ÉÙHTFFY$BøÖ3uiØó;k¡3R’;&­'œ¯ª·ŒççÍÁ¥Œ«ŽÇÀ£l5%”¨Hóª7$ãÔßt,ávŽéŒþô;!ów.Ög­3|H.¶[—e†4_÷ 1‚õµ5ñjîB¾µ+Œ+ÏveqäYAÂ*^v6ïĈÂNõ½ÜÌ[X²¼1òYôAc/æx2…v“/än®çB“0žM:C¶qŸ·¿ˆxû,ãƒkC¬È€tv¥%ÄZâø­ƒ÷ªµòÛ!ΓÇ-*3ñÃ_<¶vyxë,AR.RùÕ °7‡X=dÂ[ÑŽJhgMƒGaÝ}nÆgÞí4vaS ¼<¼ÊÅT<ÿ¥°-L endstream endobj 641 0 obj << /Type /FontDescriptor /FontName /QZEIXH+CMBX12 /Flags 4 /FontBBox [-53 -251 1139 750] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 109 /XHeight 444 /CharSet (/A/C/D/E/F/G/H/I/O/P/R/S/T/U/V/W/a/b/c/colon/comma/d/e/eight/f/ffi/fi/five/four/g/h/hyphen/i/k/l/m/n/nine/o/one/p/period/q/r/s/seven/six/t/three/two/u/v/w/x/y/z/zero) /FontFile 640 0 R >> endobj 642 0 obj << /Length1 913 /Length2 3087 /Length3 0 /Length 3683 /Filter /FlateDecode >> stream xÚ­’y<”{ûLj²TöÜö†3›}MhˆìDH§Yn̘…1öPöˆdß—2)N¡ÉNö:²ïÉÒ ’$ùMçüNÏ9ÿ>¯ûŸû}}?×u}¾×õ••´²…êã(ЈB¦A‘0¤`hnpÞΉ0—¬¬!DÓðòi4 ÔššH@ßÇ @jHu-5-e¦0¤xPñnî4à„!ä»HÐ'T<MÌÑ4wĬE[ Ò`€>‘Ø|Ïðl@oê â`\H$€ÃcitÓ¹àß=™])€úŸaœç_G¾ Õ›i 8Á4 ˜q21À®\p ³Ètò¿0õÏâF>D¢šô½üæô/š„'üGC!yúÐ@*`NÁTò?¥àŸö (Ä52¡¡‰x¬>ÙP¤ ¡ògïm„÷qVxÖpE½ÁqŒû§æô~¸€9ÙØžVüÿÅþ8¶BãÉ4»O@ü­ÿÁÈ¿™9&*ÞpFÀ$SÈüþúsùG;KÁáÉn€’ª€¦RÑ\Ì'Ä$U  àÉ8Ðý™žá02…ÆL˜“ \)T®ï{e.ŽþúAH€ã~B$Beîöjpâßȼ!œü2s)?¡ §þ„ªÜû'Tà´ŸéÊçoTb– øÿµÅ?ª¤ @•T™WRWÔUU‚ÿKˆõ¡RA2íÇcf.ì/vÅ3w ‚þ –kx‚ÕŽ Ü®Žº‚*ì+ÛñK/èª|”® [žÐæM­éµ¯óEòðtÞTÆÙr8ÎUuJ¸Zÿr[-ëq7SqB%°—é| µ;4Þ;þ”,çȱ:DŽ{íDä\fÉ/9x’òZ•{ÁæÑ©æß””ùÐZ)5LDé¹3ˆ–®€ˆììPX@®ö¢ïº¢:´ÊÌѤͶZ à¬A/'š(tëÔT{D]7ž™Ç7¹Ë÷ KY•"¬û£S4ŒÓ_àü¨éI^c½G’ò;boZ¹¹ö ?"f´œ¹É±Ò˜ŽÉãP$º\ŒÙŒ‰ê–c׸ֵЕ±KY<¹Ä_¶ÃÎwÈ®¼ùtÛ;tª|Q¬‘aÊÛ öe#3ß‚½_X…žÎÅ©û¶Ë€­àQ¯ÐPXŠÎ¥eºô°‡ó®µ©˜EÀS]]èòMJb·}«"wkG¿ðñáÔ~Wó|ä¦q:%)ZPCîzÃa‰PAŒØ›/ôˆ6À&cY½í”jPNnLm€ŒµÔÒOæéÅ/³f·kMûjÑ#ü¿ö~Y\Z{>2'¸Pï•ý6².s³ÃÕJøØ…Y¸­É‚ƒ`pJ96ÕSi œ0×Û TN!vKrx›?,¶u@ÓÑÀ&˜ß—]•Sæh£%59¦²½S…1/™¹…0î[ÆÆK¯®%u¬WCï>Qs8•»)_Êg2a*ôǽ³r˜ë5ߺÁE+¹1¯>ÖuÛF™zá›U·MôjÁÚÃ×E{'ž^]Ê¿ÃB(4i윳\/‹Tä|˜méT׃ƒ·­Ý–uJ¹v¸|ùùç ¨zý•^TÔyü½º¯lûC„½wT?Ü=o!ë¯ó‹–·…½[XÒôAo¹’jq}¶3/Ñ#¡¯ÆàÖ­À, »¼=Ø'·$1I ðßkZ£¤„…I[ë3lUx,Y[Êò¦QýŒð7ÛS:§-z´îdI˜TâO–º|áuðÛ¿Ú›õò{R[I³r¼º|b䃘ö¶WW}GŸµîR*áÍÒ±}²Ÿ í{$2OQ¬%á(²wæ Äž‰=—ƒÍñ ¸^¯çàâÆÿ$·3ƪ%HÐ@æªó¬±ËaµçS¥˜‡•CQÓ#Po/œÉ‚V® ºÀh0L´’nV¢—úÍ3’3QbÞ“È )d¢Â¥íX§l­wþ›0ûÕ˜³;ô+"$¡m§™›–ˆ*¥ü÷ùnm¢Çø×›Øzªâv<Â<¾lwl‰‹ød m/,Øa*GÃ×’ëò GÜç‰ÎWî,r<†õÞÍ—C²B¯8ÐóKz¿|9> `0cκÚ'oäX!Î%ü+‰~›IǽÖsI N»¾yˆÄ±š'ƒÙ‚Ïxhdo\/?Ît7çÝ‹•Ä×W? Š,D%cß ©eÛèîs®ð0#ÊÎ…8¾¬7ó¼¸Uz¼dêÙÚqU ìá°l§Wݽ¤H÷³:Ë$h™ƒ•¬ôÌ:ÛØ!ޝ=¬óWÊ›¹pgG3¾W×µ”[^Os ?ÕýÉÄ¡:Øë¶PüIA'sˆ+nónÛE³lÓçv§w­ì§–ëFIMVŒós {£ëv¥j[â«óÇF” Þýö,qà\Ýl®u­¯#ôqq„h¯K$ïnqRWAäŒ$¦5lúé²9O“ ôRéÜÞïaM²¤,w»6‰ºªÓ +»ƒu,ðÈctBh"·…Û$ëÚÙîY”kÜ­B–„ÞÂTKÍ…‚ø¸#—G(1½A‚aØ„‡ä‘êçÒ9AF˜xwÖ°˜¬<]’q§¼~ïŠÎxØþ‘LOÆÄ‘ç‰6ìéÖi§IÅ·Dy­e͸#Ú¯ßHŽ*¬Çпáå}Í}Œ —/Úê¶97ÂPz¦ÉЦ2þžûÎIèwÛ,´¾¤ŽÍì³%pVjm¯šWõß0¸vºS¤dmTg<³täN‚úu¥ÃÕö°r—v¬ÎÙ?B ÂðyKÇ['¾]*ÖòbÓ¬h“ò׿˜-ò­QïLðJjµÓùEk|6üŒ7“#9õÔ½ò›{à›Ü° Eøt¤dù'«­z¿1F‡fZd‡+WÄŠ[èôS‚z8™£‹^·ckÃÖÓk&D¢‡¹9>/í›Á•? *nêì9j¦ƒSIgÅ‹Òm¶a­¿¬y Ü¾!©àN2—iœ#äÉNô“ø×B>(.s°|nöþoµãÈÃÑ®©\Õã­S–Î%îéç¤Z1œ¦‡».šÆVûå›7«ùt /lÝòÞ*-Nf˼Xnö°\zßÚh’Þv¹~k±?'B†âîzíï·tìI>ÛÙ¨î£< :÷[o—OUš„xò'N-âꛕ á7+Øm‹ÅÖüjÑ;]ÍlL9!ä²RîܺXêáüêeo7Á@fzŸŒº䑃÷µÞ‚ÝRpˆßŒËá-³k'¹%Sºk¹>w¥«ñày¬Ÿ”2f&ô»Ï ½-¼ädÏïÀ tuÏõp"K„xBßÂýžÂ—lâë9˜!õ*Žs¹ib~à `tàav|N÷x)î+,$ÁœÕµLN£/6ƒb\.ólt¥J@Ä‘µ™¢•«½•á—s_“sdtû¾Ã×o—e^ÒSt§…çTÇÕ¿ k õ×ùžusùƒK§cùWL5ø}ȼ²Z£ê¾ô‘êÏo~{=ϼâŠ\íËpÅ ·}.Ë…ÀkKÏ•úâK…`÷ _÷<ò16:bš‚oÞô‹™8:h¿®ê\¶Ýflm"—§·¾š¥«^¸Ym:µ…–LÉ:•6çíDjASEŸ˜=ÞU9ø%:F:ñÉF%»UªWV© SýÚ#-?Wø1û|'MîNJHôËvó$áöÚÔœ¨…ë§_v$BN-)É ßRÄ{ªõ±¼Õi™ÕCO+ÖÏs], ê«,¼¨LŽ5ŠîïBM-êYhgê–>¥•¯èXÆTäî.²]%L'XbîÔ¤ßÛ¢AUŠƒWx;ôã3L±´/ ½/úùµ].ÜS†£ÝÄèj)÷„1´Æí?M<…ª†%ѯ%’k1Êæ¯>-†öM=ž¥ÎLT6 zµdOˆïéñv+݆exù¾F1v·ËwŒ?d°ÑƒâÑíï»æËÆ&¶f&3g0Q†Q £ã#õæRö’À8/Yñ\ë}·úÉóNÇÑ" WÒ3ŒÍs=S·l…ÓLwðw°8“pf‘î¼­f:6Ê‚:˵ÀR9wåîÉK¡õüfX°Ñ·8ÏÛLOŽ u“±¢AQG5~«ŸA=Ÿµ þÕ§CRÀ4†³Ñq2×¾iœ;Ç¥»™ršwÆä9;?b/©ðÊ8A<«`|ñCAÌ‚T„¥KÉCOŒ¥&(ê[mp°¼u¯P Ú¿Ë·Ùm?êÞÔ½É.Ï%©yúdÿÇG܆*«únÝymCcDZ4±1•*lÇ‹y”•sèôLæà=m·Ì‘Ï«N«YÛZ»Q™¶-I>ñ¨€Ò+nWƒU†«»bPDÉq—;Z†RwŠmG ®j‘©PîæÚݸîñ´'ÍM 79á:ý:³ KÏê¤êc •ä‹0¾$ž½Q!×[eo7|­'¨ÉágE.ÊÞyh·Q†sxÁ»u©sãÁèÉ5aMjrIJH<žh\ý0=!ìF vËÅ:9.gô˜'äÒ´:úvÙMÅÓˆN·–ÿ&a. endstream endobj 643 0 obj << /Type /FontDescriptor /FontName /FZSBSD+CMBXTI10 /Flags 4 /FontBBox [-29 -250 1274 754] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle -14 /StemV 107 /XHeight 444 /CharSet (/a/d/e/g/l/n/o/r/s/t/u/y) /FontFile 642 0 R >> endobj 644 0 obj << /Length1 901 /Length2 1744 /Length3 0 /Length 2327 /Filter /FlateDecode >> stream xÚ­Ry<”íNÈÖBÊúJ$e3ÖðeÆ:IÈú%cæófÆØ·Död=–B¾Q–,I!$KÙJYš¢”Q©¬-–r†ê|Nß¿ç÷þóÞ×u=×}=÷ý(Ê[Ûªhî ÊP…©Áô”•©#L€©ih**¢è ŽѨ&8¨Àôô4´/Єš0}MM}„® "€¢yÒ!PFí_éÆáqTÀ Ç ŽGlixdªÆd2`³v°}@ºHP„Á„gî DT_‹dI%Ò0Á×ëåÒ}8¡åµ”ûNFJ QPKã49Qþ©~77ó%“±8ÊšýúœþÁã(9ð§‚Fñòe€tÀŠFéÔߥàpV ò¥üÎZ2pdoLõ ƒ€Æò1ƒ@‚5ÄÀ“"Žì®ã •ð{ÎäÖ#¨;£ŽØ8ø¹ÓuÒQv^ÿµ]S¯×°¿kÎ|èPà¢Á™/Œ#ä|¿þNüÖÌ”Š§ ª ©¥ àèt\  çõp*- @T€œÄêjTƒsà % Òè‚kÕFê^8:H%ƒD†;cükoÀ9¿p„îœáõ·^ë'¾¾òF:‰Nz‰ Vº€º/…²þð9'~xýsÄH$- XU¨jêisîŒÐB::š¡ÿ£ÄûÒ9-ë/˜³©_5âì@¼àÐþPÔ©Ìšè’0Sfo)¯ Ò£6[ݶ ‡acËnZ:Pãx°6ïšœ\ºÿ¢ä&¸ºÃ’ˆÍ ‘4”ˆ»ÎÝÁ+‰g½yÁ³Tf®%{¦{,]$ØâEWŠÊêJ \[ÞÉÛ+I¯†ñ6…¹P[ªk‚á _pïZä1Ï-ªRÊrÖÆ½$X¾¥o¤ßàt½Sì&,Ñ¥Ë>j.bÌIª¹ïz¡“Šhø<nÓîº2³ ªE£€ll’I )Òúm¹5㣅Å>é×emçÏV+‹Ž°ª+sˆ\Ê’õºèÌ„, }üÊ]ÇÞWìo‘Ûî=Ï òÄךé®äË_N$™çIžÝcïõôâÈD™ÿ§’ôn/¡“;fÃÛ¾)DhÍ s¶ÝYU*cD¿6w1ÉRfFÏ´ å˜˜ Ü œ[6βÌÌ~ø ³ô„¢ !3 hti¹u‹àÈÓú»Î?ö¬™'Aƒ˜<%ñ–2ˆyää¶mo>b_ä£G¹cH{YµF3ØòpÓÌârŸÇ#¦£»‰Ì:EiîhqŒ–ãé%Îíÿî»-êÄHÊúì-ƒÝ+©”Ç’›WF˜ôgÏ=ôy®~¨(lÑßôDaч%t®\ö qΝ¥÷uò¶ªêÔí0©pi¯uÖ¡/^FCìÙ,Z¾I ˜-j\¿-P®4_°¿ˆPL‰«Þú }}Tï’ wîƒTÕžüøïw-jMó—Ë0®äîQ¨¡Q_ÚòQsEª yÃ:™ÌdârºîDÅî┲AQ]•2¼güÖÚ$¹‹ôì¢që™èÚcû…‰n­ÈÈ_² » ãêyÝí×ã§1hoÁ6Ì¢^IÔ¥e\…»’ù¾2)i±¶AŽ$‡A]ÄÅãí°.K·G%õêá ªAÓuò[»21…Î;‡ùö”ŠÂWƧJu&'šöÁ¯¡‹w2ÒZGÜžu˜çÝ}²ÁÎ#2^Ùì))ä×Í·–^ų p ÈöĈŒ†Ê¯¢Í©Ï,ûÙè¾îlBu6ªóëÎ×ÏcŠ:‰¢&㪘†«§³´(ÍvñO,¹-¨µ—¡ ºã]7¡ôˆ–£²7ªH”œ>t~e¸è+»Ù–ÉçhðèÊ>îŠÕô¯J;XÌoªS´5Š/(J꼨Ì÷Πô÷ ñ¹•F¶.¥Sôy­> endobj 646 0 obj << /Length1 939 /Length2 3379 /Length3 0 /Length 3991 /Filter /FlateDecode >> stream xÚ­’y<”mûÆeß·Æ–í¶f‰1v“dß²eß*Ì &Ì0F¨ìK(”ìB¶,#KÙ÷ìRÈš5» ¿©ç÷|žÞÞßÏýÏý=¯ã:®ã:ÏK€ÇÈDLŽv@h¢QX1ˆ8 ¨é똚B$ˆ¸¥€€aE¢QêöX€((@/'"@ä ÒòP¼PC»ûbNÎX@HMø§HPqC`0{ ouF¸á=`ö®€ †D`}ÅWWÀøçOÀá‰ÀÜCÀÅ)!Ž„a„E þIåˆäþ.ýÜÿYº‡ÀxâCBøÂ>"rõàGJ°ŸäêOsM/WW{·Ÿö·é¿önHWßÿ— Ýܽ°  †#0¨?¥ˆ¿Óé#àH/·?Wu°ö®H˜ ÊɈA¤Å%¤ÿ®#=5‘>¸ s°/į2ÿ3¾{¿b€­­4,µ­Dÿ™ë¯U#{$ kêëŽ$þ•ÿbÈ¿ŒïéØHˆKH@ðBü÷Ïß­?NÓ@ÁÐp$Ê ”‘ì1{_Jü “ ð Qp„€ðÁ'‹£ÐXüß?À¡ü9V ûYúE ÿ !ñJ`§ßP»þ†x+·a0ê7Ä[¡CìùÊ`ìo(€½þEI¼•Ïoˆ·òý %ðý_øßsPUEû<À-&)%ÈÊ*² ²~ÿ!ƒya0ö×;ÇÏòvDâ§@ø `”ãhØÕлIoà ý5r†ŠH„=9RòCß5†ý•rU|}æ*ã¦jÐÁµÇÆp‰£Oܼñ w”™c{«ò°ë 8ì#C H8+Õ„l¶n{›°;³³•Î-=re‚{ѽJt{’ï`ö^#I©ÞD.›m3ЏðÃøéW—€þ¹ ªd8ßR"å­Ì:½„ùêìÓ¾“ -tz"¯›Å6õàâÙ[ëôˆË'š…Ç™úúvHÖ\ªè'Áìžó¬Äq¹óM)XºØ"­Eéd“nÐ ºÇ {Šh)Ñf9Åp?2¦Õ“sf¨]éÐÙ8â}p’B’í­yñ ò;}nø-ƒ‹R4Uð·ŸMa=W½ÀHîév„²—kKÑðdŠö©®)Kz;MéŒT åH(û˜‰KÊÆŠ(è‡,–Àñ™0=ï‘¡¡á¿>˜îb &*h®rŽò«á%3ÊûÏ¿6ètS:5'2‰ï‘°ÃIjØÕ”sÎ7è• þëˆQfûyâìáéBKgû§†‡çwcCÂÛ/Zëhc¾·yE##qÎíGี¤øʺÂCá›.—S¼eê¡ü;Z×O±µBââM}qãiAΣñ$·Å%ò?ïkû¢ ª/¤¶ÎyÉx{„4<:Ž_5ÃÈ”æKO•µ:©±3»k ?jQ1Drp¨b÷tµnDîURs÷0λ…^¬möCøm­÷#¤HF7w»‡—wÊWRI 7ÌÞÍ«dš•ª=ç‹_ŸŸMxíx‘·)%CÒf¸|k@y¨yξ:cûAÛÌã%Ö£Á§ý¬¶œ·QO—ÝãÞW¥¬\éoAì_¢¾I“}Ï4(šo9)ô5VdÍ6ôÒ“x8@âÖçñ†0nì{ß1.#-hr²†Ö®1ÆDœa³s@ÄäøQ\Ög†fÓäVÛ”f,fpŽÐeŽ+¶jªWcçý mÇYÝI?t]ZGšÊ«[gL/P‹ægCîWê<¹ÜL´ºM3/…»ÃOGãˆèfc‚röGÐòö„RdŒÀ F99ÅÜ(¨Ò½ò‹‹ú7?í?4y;ƒ>$äè“U!:»EÇ{¦tѧáí‚B‹½£%5‡¸æó®Áµ*o†Bw¦¼‘q²ŠÛÅWÉ…•GéDŽ|·É½ Ü¿6íÏÂK²çÉŠƒ” 17Þ'ÝyV³»ì®÷Ù#n93…dQ#Õw¢Záýú5ïltéʆQ{x_KpP‡1<Ö4{ÊA.æó.tÁ¼’˽j•uÄ©÷HÝŸlò‘ù&G#¹Š““|SåpHY^Õ>-/޲°Ïc‹J:©&äKóåogh®=‘ùÒg™Z‘Ƈ¤¥ö 8ºYúòƃg8è^1 äÕ¬Qö­rl8InÒ°ÂçnZÁÝaG¡î@2—çW¹(xHvY "<ü0;‹ï³Œ¦¤>Pš™x*:Ìm™6œ/…½!±6¼¾ì.·ÄÚëL8ב¥®”tŒ=çšbý¬G%â|Ö$i¦ XÝëü‹è\ÃQÛÖ[5—áÏò¨ú@Lð©áQÆw ’÷´•­ï‡žjÕsvJÛñ¨?Žu3u§'ÍaüDâƒIÀÎIõ”Fê µý•³„c³óÒ¡Ì;žËZ®™©&Í㕯ó#ÞÓ£ú & cs¨Œ!íšïç`Þ÷T^f-6UF”>èEÇ­ƒmûs€¿X}¥S¥ùè)ÄqcÉXWT麪®VÁŽ'ŒíûÒX醛”CQ†ïÏ– ;¡ùÆ’™ë´‘¯¬bß] P2² ^ÍH+¨ˆYúJjÚ½ø™YÔ4Y]­üåþHu‘œ§S3Ø[wˆ.hü2Ap‚4µðó™§`n ¯†ù¤Ìê)Î^ËH>=r.ȹùˆà;ì:JeÏô Ù‘7ÓÉÖ,ãÓ‰QíkÛj‚É­²^‹éÉzê©Ädooö#ãõtÌ^²mweŒ$ô_snÙOZWµ×<˜ºÜc–ÌeùâË©®æÛ]£pJ4þ–E†dyÐzGÐsl†£mÙn÷§µsn@#wò£ž¤Y›_.üV’ßHqÅŽ<±Ü’ïÐZ¼'U%§þb9Ï@T ¼gmiB÷®„ÃWõt]pËðÍlÕ¢.–7B¤ÏˆŸ°o8;}+-iEð‰MNy'j—Ù¨žñ5s¨ °œøPBƒû7q¬ˆÖÞx¼¨Ë§Yèímw2E#¸egcdéOVÕJ6¼LakBˆ ´nƒÂ1Ûy„y$v †ë=*ê+ôE­)oCÓ[¸kL¦gÄ4sæw嫦הeÒÈ$ÉÛoÕÈÄÔíÖËÆ¿éáʆmE¯B{ H&a_@Ž¢ù^Œ•¶´GEZ#(ºƒ…–CçÒ6éGƶãûz12•–.µó,'¤è 5ÞC¾rêÑŠâ/J¶Þ]o ‚y…cmÎPyÜ“~Bmêð7ð²¾Ë8Ëìn#¡(‚.šf‚z-¹tI±c‘\ñé™o¼ÝDÑ^UEF½é­@hq}N±ÿv=£<¼j!’ÇÞAÖN~˜v¿ÑÛÍo§wËú?+LÒmÔ¬tÅÁæäsª$õc«`æJ«Î4#zýË,óU>ÑÚYVgj²r»"/NugšG¶·lDÚÕhž ¯ECŸÜLy•ZŒ4 ¸žŠsÞvoŽ9Ë~Þj°òöH¢ä:°ãkmNPâÒt|§Æ2dÔ¸³lH÷Œ÷}}¥pt/&È×\Õë˜BwÁž9í }Q¹½{žZtëúü¼$¶aâœf3œnç¢0Ã’0KflMHc‡Y‰]l¨Žˆà«+é­£Ô¹/c–ê·²Aþ’Þ]ŸÜi€½%¿m™ ü[«Ô™FìJ¾ásÝ€Ó‘Ú²m+áH²aÖ\i=‡“m2Å ÕTÚêw!õ¶úé² 'âgg.½ö_dCš”’®˜ÙÖVË5×ßzüº=H÷‚–>·¸Æs0 £JtMÄëœýª„‹ÈÈa>CÌÎÇ> endobj 648 0 obj << /Length1 1394 /Length2 10074 /Length3 0 /Length 10899 /Filter /FlateDecode >> stream xÚ­—UX\ë²® ܃mÜÝ-¸»»Ó¸6»%¸÷àÜÝ]‚»Ü‚„Ük¯•¹×¾=Oߌ·ªFÕW5êÝMA¢¤Ê læ`”p°3°0²ðDåå¥YXo×ÌÌ¢  1ØÊÁ^Ì ä°ððpd\l¬\fn^.^ €¨ƒ£ÈÊ  ¥ù+ˆ lY™ÛäÁ–@»·¦Æ¶US+ ؃ lk Pùëg€ Ðrš1"°°Ì¬LÁ …•=Ó_š¤íÍ\ÿ2›¹8þÛå 9¿‰Pÿ-“ð&ÒÌÁÞÖ`4G`Rpx«|ÓòÿCÖ'—p±µU0¶û+ýß“ú?~c;+[ÿ‰p°stAy3 Èþ¿C5ÿ'4³r±ûo¯4ØØÖÊTØÞÂ``agdfÿ—ÝÊYÂÊh¦d6µ˜Û:ÿ¶íÍþ[ÉÛüþÖÁ¤ ª()+O÷?öo§’±•=XÍÃ`þý7³üá·!¬ÜºÌŒÌÌ,ooŸ_éÿW1q{S3+{ +'À2ö@`~KÅÊÁðbXÙ›Ý@÷7ÅLŒöà·[o“ñ˜;€þz®œ&á¿Lÿ"N“Èâ0‰þ!n“Øâ0‰ÿ‡¸XL’ÿ!æ70¶³3þã~+"û‡ÞŠÈý¡·DŠÿ!n6“êz‹ÔøCor4ÿCo;Åô§ÂÛ3Û:Zþ±ð¼å5ýqüEÿÔô¶¾&³?ÈþF@[ð?ÞrÿoÒ,þà_ô¿šäd}³üuhßÖîÏMoi-ÿoƒ°ú¾õgý|kÉæø6pÛ?éßäÚÿáëÉîx °ÿ²¾é³wùÓÿ[.Ç·èð§c¶·xGË?jXß´9þCÜ_ùG',oî?Å9ßfãlkìüÞXÞšÿß*ºþßĺýAÖ·âîÿÀ·tãÿ=I""î^ ojX9Þ6›™•ómŸ˜}þW © ´ÿý¶z;ÿfs«·# ºM–æLù‚­“>—øŠçM–ÂÐ8¤u„Ô¥ò1¯óaÌ‚'Ô€DWè!èÖVßÑ’NeË™ÌÌ96?6{z©2…,¢" ÉIS…=7=Ö3€ÊèAµË Û_"Þql¤;_&»Ýp퀩”;dáÊýx]²0ÿríkã7¾¹„˜bF¶›„ ŸÝ*—Ô8؈}<‘tÈsX*ÂÑK»Åü½ô±gmÚf9•'"[j¾øBW²2ñœº¤ßxe5¥ÏûVEéáÇCNû†,^4¤RŒŸsK<±Î~Q¬vì^¾«¢qÃb!MÏX™()³1ýî_Wûý< Ä²`ã;²,ø±z°øßÕ ß٢Í-x#¢o•©£–¸Ž•}·Š?›rhõ»F)ËŠmF¤½9ñ¦âÏcB/èq¸®Ë}bR°4Õ‹_ ÒäÒð« víRr_ÝA¡È½Ù­”èaŸÐ¦%8¸ÎÂÏ©)HàÐàÚcû–Ë'Ïá]§Ö‰~Ùz‰çeå})lð Õ9ê!`™y>]ïòv²"/Y¨š¦ïd0y䤄šž'{ù#eÖ×xz>5Y©: :£@‘¾zÕt/ù°½¸U·ÑUÓßûë=Çö7èºF°ø¥å¿ã}¤Íºö‘YI9YÍkÜ_ß.DL½šWÞ90—IƒÁ[šu:¡½—=5LXh±;ì“øŠEÁržL£Á%ùY?g¿«ÿÉÛ¡q¦Oð˜^GûéîŽàÄÎî þæuÙ6A:x2þ®Y2Av›UûîØŒYÀÄY›ónaIìÉcÙ0Z— (Œ£ˆ1ð‚­ÃÁr‡zîHÏ®~@]A ÔÕDÌMð`˜~vùA´ÚCÑ ©NØŽ¾÷åhà@Ÿ²'H;aÏÚÚ:Ôd'@WxÛŸEå±$GݘØÏR€Ãˆ'x±j#ª^âi5¶Í½ì‡´£™1Œrg6¾DëyÀòµ·ÏÖ°±ãh7ÀžeGSo÷#a4ågðõ^S(ñÖ«ÖOý Z#^pÄl ÿ= %l`Lj»¸ALX šÙæO'“éÏ7ÏÑ¥›6~@,ÉïhǤzɰt§‘alû´¹BVÙ¯ñîWj=F1ªˆžv’Œ£ 0«Ýz&|%ŸÜGˆÚ™on‘KØîSÈ82^ÁµD+}b ô@¶Uÿ¡Õ­¾F7G„‡ãÖç*ÌY¡dí ü½ø¾þe˜i þ,v·bØ+ìmˆìßšw£Ht=ö'kŒ?GJyí[‘¨îjgU56:ª.©Íjè¥ÔÕQÂ^M\UIQ?È™|ãÉÉÞTËä]`(-BƒØv†¥-<¹ýEc3´W1ä±ê,ê¢x˜y*Ú.ÃÄ9Ï8¨¸18‚DR{²5Ç½Ž†#nYÆjrZ<+CùŽ)?¸Ú–]ú`½x7bB=R|[r3¯ç%öð˜%ÁŒM̶þ ³DÂ'éé¨H¤÷Ø68ºE×}P æäŒ€a^œu?å_N(ühUÕ¾ââ9EÍîç}ÚQ©K«xb 9î<,Á1›00/ÇU‚÷=ÊìöÕhYo*Æ£€-Ü‹ 1jp·•i·aâ<B[ÛˆP†YUÒÏ« ‰ï’6‹T”SÜAŽÄ²±•zöïä£êÏ!äPQ<““%[OêbëªÈB8-GŸÄIþÕä*I9ùÎ>ÒEÿêc¤Æ zèÓ“iAMÆmK½ÂŽm²ªÀÑ_ö6@``PÐòs 6âÜ2kSû]ÈwÉ:sÄ{ÛЀ<©/°ð3ÔMù±v£¢ÎÈUºŸE-õ$ÌW’êCBӴ܃Wszêìl¡¦ñ5÷ªúƒ~l—iïÊ~víYs¢çå½Ä›Ús¿Üg¯¨ð¹\}Oí©+Ù³:ûýʦNç‘à÷=0{ö4Ñï†éÊÉeÇ/KM$˜¯[z¨î¶J€ÈLà†5ºé½‹˜Še[xPš•:KTú{^…\M£\lh,‰EXÙS]õDj»Ù®8N‘Ó1ÅÌÚ0?8'V¨OZxëÙU—ˆîtªU8ljÌþd‚Ãü:Émg ÚZs­ÁÀ](Uøú´aœ4K¢,ˆÌì•s*Æ%“nX,]ñ÷ÏG¸UŽ ¯Ë#xe ƒ½ßÙU̯? ¹y‡×9M\]1aºÄ¶J˜íV…iô!·pÛÉrç’\s$ c¢fJĽ²Øä+ðÏB»Ó`{œx&WeÈqr ~@q}ÃÒ½'Á[‹ T@–£ŒÃ¾$׿ôÄÛÔocïМà&á/U‡qË‘;àÏnâm¥"“¶’~á{ÓÐØTœ$î ËùbÄH׿ÌV”ÔÓ`ÈÃø©žiYþÂ?ÝD(…2Æ®ð[ÞÎÇÆ!ô䟙d+gœT™*ÕQq£¾v‘)ÎKÖ‰H\± ö¡«èBÂÒÉ+̆îòÐ7 ‹²Ë˜O{ ƒ=ç‡ uxrÆ{„h4¬&¸ ?”ªTgû‘Ì,Þ3ò_©HRżŸúm6ó±’©¶§àž¯ ®ë$ iñm‡Ÿ9yÇä#ÄÍ_$[¼…†]B2c ²˜Z…ƒO¹ÿ ’p_OžüŒUØŽÇ2ÙÜ^¯€‹Í3w­ö‘Z=Ç©‹ÇZ(BÙ|·?’…ŠKò. M™ž É™-0„ƒ®ôÔÞaдۖ²2€ÑLʾf-»|•|µ]_QõwZßo©¼"Wþ¸ ©!Ÿ«úsí­)óÆ|éUD• æ´Û“çY:à™Ú> aã5½3£›Å´¼ÍÛÝ‡Í A£¯øÐl.z21W^AªËý½!vlªEݵâçG}ÚwU6x<úú£÷öƒ'#¥¿+ë×å\â!G>~S±+ ì~¢»ý<¨}­§ŠžÒ+…‹±Rã½L­’ˆÌœó¯ø}ŠM÷,&ï”ë6“\¯óÙn'"|ÌC G(òËÀщ+âÈÍe7F^¬•‰Ã§N|Ÿßíb,\ËY/‘c:ká Dw²öU5쇧ÐO–Õ‚; d¼ÇNo·uo’ù„W»¾c ð²k뺪È^ÄÝ›.±YÕyó%¬ÄÓ ±¬—H`«]ÕQ}üb;vø¹m^e eÏ&Þw üîÓ¥´ë»U¦JS`õ6M’ÀšøWR‡|E€Ñ"jáO›üÞ€b£–JzPCT46}ž¬¯k/þ¡¬!‘ï9¹“ÚÌ¥2i,…$<¿ò,Ï󈢬cÆc‰ è®2J‰ ­6Ð*¸¯“Ò=ße{U>1„iPÈ¢X«u2/UOcV§›èÝ󣃵ü£FCßf&Œ'Šo}o^ª§‡ÈjGmÊlÙÓ7ÄAl¿UIüÞowœ'~rž `QÎ× É,Ž-bKÿ©RÈÙ~‡Y*`›]Oió‹¡Eôf¸RS."0ךs™(€Y}òÁ_ë+Jåð½j:(¶Xw+Á°rvÅ#:}dž9Å›#&$sX_œÈrn"–;ÙBÙˆ\/‰®8U¯fx`ù,’´Jnª¶ð}ôE1„Åñúzü| A¢"‚Σ¥¦‘Þ6r_7´RÅz–¸ùè“Ägyh#mSëÕ)‘x+,·Û‘œžß—›CŸù«¿>ŸrÁ‡œßƒ xp1¼íl³uŸ ],w ‘[é\HÖù¾°4M46ecDm ;*™±×Ê6óë§Ü«úmË…ˆ•¶nQÈV2X™¿d>Ñ€¡m´JæŸ7÷ÆQg»à7ýË iHAcÊå[¼ÏÝÖ"Lå«„.Q5ìûþÛ ¢Äû? ÄúàEǧ_D[œÂ9†¡±®á Ç8/êT¹3ðß Ã0µºTöåìØLðp•„О©}”f]Á¨y웈AnsÜ×G1j2s4 Í1xRh·p¸ô©ñ°±5¥Æ{ÄÞ óßmãÆÌwÒƒGWVàZ5'Ý áØçn¤RÎÞg$ÕçXtBËQæf›¡©,lUK^½ÌŹƒ®¡ÎÈÖi4›GÁ]eüE"³‡²ã¦4¶q.ƒ6 5³?2[wC FùüÓÍŸQlàÑÒpÇÃØjÎdMòV7Åüx^“ (¢f+ä˜å—ê‚@_plt¥~ß”Óù¡d™ãt$\Jåø³zbz(viÂ=¶§=vhk¢Ä i8æ¾55ð:GBÊ}1|Ôyÿ83ôí@‰|'O¨šølYŘ1É)Wçü£/¦A=´uÿ¥ñDH¿k:ÔlÙFvÚz“u-ÿÑ“qÉ~™€½™ R³?êiNåâ¡n“+RŽ!kCH~®Îe{¬Û:Éß2È"Mt;MûGJßé…’¸âæÈ棧Sȃ×c‹f¦^ïHÓóYTþús¤S~Ëjlaz†ƒfß’ÌS˜j¿ììz}gž?ÒdVF[R\²ÖgÞÙZ¼ ñÅSáGýÛQ›óðp¢—…WÂ1ÚûiTí Ü5àq{¸U)[1òòÕJO¾Q~·02‹VÀ¥lšü™ÁF2=}¿ ò'6Dze—. þï¡|™ R„1ô öUë6ç;Ì×¹Î&_—a¾ˆ†§$KϹÞOKÜÑñ6ùÞx‘>M" Ø¢\  Z®Ñ!QWÚ˜‘§ïS«âQ³sh\¶Úuª*à’Œ9¿®>°D} ¼‰ýN·DgHN° JcXûåý-ßhígØø-ÊLÑÎnÝkiÒá¯`è&Ò˜ÎwùÑÃÎðæ¨°ò®y8±­ ön¸ Þ/ùZ±ÃÛßåWﺈ¬Åè!ÙÛ8mhWF–O({e”!?ÞTõ°47¹Ã“ÌÂa¹Žɰ%‰Æ"šÅ†Ê »™’…rØÍgûôgÓQ@Npb"î ®£§)Nи_äS`¢ÌËÙPž$ÎêJBÓ£Ø_ #Ç0àÚ[¥)¹è §{N¥oC0á#T~ȸê•tÄ\P„±kX1–ƒi‡Ò#$¡:Ö)ª­ºê®¨›9;^ȃ}–ÊSöš-ce ÛóìZKV8Ë‘#H9³ÄZôIÉ6G¯3²Ä¢”¾d‡}hœ–š_9Ä¿tÉLÈëb83Y ‹kTFè!‡áb}°uøZŸ'ˆñ8=¼™]n’ÎFÉÓ°I¶š¥t?ǘYnIò}ï[«ËPÞ-õœrüƒï ùºû$_*iÂŒÙÌ‹ã6 ±$±<%¼½”7IÀXg6±´8UÚ#ØVË£û‚nÑ2°G;.{/cªòîÂŽ»¢Ö¢ˆæØ+ $-a‰ ù“nÐUO~ÞR #Ç+ÊÑ,áÞòÁ]ž3^ÁeÑÄìRŒ£”ê ‰x¾~”óôÌVîFo¯oiÜCKWl­ÿ¤ÆA6z"ëï׺ŸaÌì7F‰{Rõ%4ð¹Gfþüú¹f`]ñ,jeRü1°¼$õ Ÿ¬«´Ó®ÈzF§>á„à“Ô®ÐÆa;=G¾`CZ½'›Ûüò]ÜÈotÖVÌß øRy`Ó¦$ž:‚M£QgŸøb›×LM]·±Ý·øÉu±´±]Ã\³ýÙ ó‘$Lé b’b Éj";ÐvÏž>»æß°x—]r³[5 ñö箯PiðÞ;Ýu|å×ëùJôý»hÚ?îj>{]b;œ %ĉj~ocæùÃu'ÄY¢^ž¿’tãNÀB&æíuïÌ|Õ.Œ4>ã¾ V Bÿ*¯Ãp&Zzõ1ä5ù©êg’kEÔ(ýÀ õú®QD€z_Å•û¹-pÐ*k5:'ƒÊK¯"‰e¬(Ü–,ÿüöwMS8 O†VÓ%JP×ù˜ƒØK"EÉ›x!¾N 5²Y(­]}ppë>el)8<iÛ꼞 Ö”×Û 8Rÿj³\ïaÅH.çfrIbq·ŠK—¢ä?ß#}fC¤A÷#åœî®‡¹6xjP…Ìhý†‹(põµã»u"‹Jå ií¤= lüyàf÷¢ÙCiZÇ0T¡®Z³šÀˆ1pSïÉ3-aü, Ìû”¡éNªR{z’cªªy»c$ÜŸl{9Ý x ¥é:±ñö¸„"^NÀ%³¯„G"-ð¨^Žl¯¾r%¦Bé¾êC1ÂÛ›!¾Ü|†µ»îå2)èȼ€¨| Ø…Ãçv–_?ÉfQr: ¯üåíùP,aJ×<6ã6˜D`‹Õ©CÑÒ &Ýx»Åá\#ÍymR•* añ‹ì9­Ôé ­Ë‘Æ.s”´ýX5¯C˵1÷"^éŠ9>qkžJ_ëýTÅ%Ûsÿ@b)þô\ް¼%YEôÁRÏ¢p“–-;†‹ÈX— s | %(/7{÷¼«æàX¤^`~y!{ÇH 6ZÃeYâð>6á˜{ôRòº‘MVj˜®Ë2x_*Ž~;¯rxÈ!Ð<󨛜¯ïD‡:÷*$®Ì‘W¼› ¹Pe¥zh|߯ýa]¤çœL늌êè]èpØÎZódäöˆÛå¤LPíU*fVoë¦-^²‹U#3wçÆã?Îe9¸’¹ïšàíÙ;!í¿òÉ ö›"BûïþN:eydl"=PÁ×ê¹Í¢¨Þ¼üœA]^²:¿ =A2“5˜ÆuEÙ–%Ûö¿ÝA¿*Ãd§õ= ³4””Iͳ…W'$• ]Bœ©$ðxoÔ“’ ðbÁœWc³8ªŠGãSÛœª2×{<™CBœ¨êž¦ÙMŸ\S|kÒS•êbÍØÆ&ˆŽ ¤ƒ`ËL¬›w7Fó­{%u›³.g‡£ùc§3‚i5µa´_¥‘‘¯fúš½3è¿Ýë[þ˜(‹]v1з,þD­7òå¯&Ì—Ü&ë˜æõKœ‡“ãT Ñéㆠé_©]Pq¾CE3»@øUƒâÐYõYìÜÁû’¥âRé§2d˜p˜éFõ"ºRÒn³žYH ýówØÑÙ¹9Ý}AëNNÊ·ƒ?ÑXü‘Ul]l9pLfL–{˜Tflñ¿&J5¬VŽÉ«–>Ž,•oFÖâGÕr¨{k§¡ˆÇd3LY£ap.l@Xˆs/ÆÜ¥€E>Â$J Á/¾:,„(w½þ]pxvc¸M¡àyqð¼úE33e«Ýmʱ;¥Àá¥S„S/)vîÉN’Å èaqÜ1Ÿí<¹•Ö;”q“R‚ó˜UI ×én *a‘â§”ßÞ*Ñž“»ï£%þdvR sºc)´[ Ïrû‹røOÈämdç¹a´óž”쾞 wYÚçÍØùí5Å™ø§çX„‚cp‹6ðUîaµç\žUzÏ=—úPL ­[l—E¥Ùæîfû%ûøïwv™7F¬ âá,nÉ~×ët#cß¼kN-qþÍÏÔ–þyóÚªIÏ¢'0ð&Y&báq‹ÇÞý ‡îSR¶RˆsžòòS-½¸_èo™³v]FF¡ëLò Oõ'B;EñõF¹VÌîÎB‹aê¯ ï£}Í<Å/o½%k«J´»’5Ì£½Ê?| °dÁ°ê1Åãc„kʪkm™eDä21Rl+åk‹hiÀª£Eæê“q§HËãa9´|¸àVvØuóouH&‚zOf»xÀåÆ3¶,+f¶‰íñ€ lv…|».ÒS=·´µ^ävŒc’ÅÍàgE…Cçm@%0¾‡<ÁW[RT.þ‘>¢ÆêåAV­H€ÇÉôB|m[QÙ_ΰ A! Ðö9zäO´—ÕmëÈñ¬ü2i—µ.( œÎ‰Á`Ð xàÜ¡‘ÜÖ¤" îÇdóf×Ñ2 F4ø@Ù@äÒ‡ŠP7h×-ÏɯTwMí˜üf^/ËŒ†¶dÛ ›¦¥ýž ¥BL¢JZ÷ßõî8R5‡¦¼ÇþÌíÍ‚YïÀ't%wޮⷆcÙÊu9Þ½a Ä1HÑ Ò¼þ¬$D®Úëþ;DVÏ´zˆF²O¸Wt”<¨nmžŽm@ƒì÷„ŠâÖ õ¢Õiôå…[@³ˆîG€LÈ‘zË€7a«éá)6³m_MÆK{ ¶¦ú‡/:a!ûq18k×ëþ½úÊ":7n”u­¹×Ö9Æ5s6xÄ\’ÃÃ=®=­iåû1¼÷»ng¤ìã!ÁÃ-c\mnùÔ³_ÇÚ ¢œªÛ##æ¦ q #›Í1xG~¤|æÄj!ä@Cö¦ÀïÔ­å ¥èÝQ9&ñ‹>WÈ#¼/z… 0ß›ߺµùÚ ŽèIÂïÔ`hHK{þ:Á‡!úÊê¾æ¯÷{×’ƒ=ÐÁ¥ýwL>ƒ_8ÅÂ~{Aì'ä´kZ$ßB‡c⤧¸q2 ó•ågÒ´E#èæRÇïEÔÖ,*à#¨§87ȧDi9ƒ/NÔ6½`V±­ð°Nò(¸yÁÃàv®ëÏZ|M,X¹¸3¡š"¿&©0¢"à–?…Q)¾Êáבñ‘@ žôIJX*èm&èˆCYT÷?B„ÛøŽéH¿ƒŠ8L2ÞL¢¯.8FÙïqÞ÷-r¹ToýØ"œæR¾v½ØJíÖçkT Ûåö •“…Òôpý™{ð凴¬øQC»ŒÅ¯yr‚žî„¬^9‚ÇA2þòšZõ6Ú8ªÃø éÙõ³ŸrŽ¿7h¯ïž  ß~É…Èã!ì0À¨‡ô04ìu?¶J«Q͵c ÇFXÄÙžå­‹Ý2tµ–ªQyë²1©ë ò¢ ÈOCX|àå$ô¾Á¥²%œÙ–?¡j¥ßscËø8¹¡•#–ø¹ïwRÔ­Dº79[#/åXe›Çãu$íj¸Mj žàA*é;>ʪТ¨?3nH>Z¬ˆÛ^ô…‘ ÔúP:½ |_]Q>dDh¬XäJð‰Ð|Èhz²X4þ´qG¾ÁPfÑ®‰€åqø\X¤ˆKÞd–± 6yM©èAæb@؈} ˜zšéLçr­•Ôg§$_c¡ÐȶÁI>Å9')ÅDÉ@ú+Z¹sÔðÉÍ-+UM«+’®ä›·VÑc*Ò\þùÙÞÒÛ7¾:t÷6A "/FË(bVìZœegÀ#m3—{h˜Z°3° âY+mÐoi»£}›ÜÁ•×']=°¹DÜ¡­ñ~h¸Õ’²oƒO0VœŠ@²[”×zéC“X®hÓÒý2ί¹ïrÁeAYµÌ‘{D›ÑzG ¯‡ÄD”†?÷|›À|˜Ý.,¤—+¡?ðr‡¹ªß‡Úý¡`RØg†îælÿ¬}×£hÌ ÍflʦÄ&xqvÙ·Â\nÒ´ç¤cÞd˺ZÝþîa¥·’:fF9YúÂRÏ*8¯„J¹]üáÚ™¡=\-í‚3ìó½Þ<…÷ Äà ¬4gÎ'%à•¨ûó¥³…´¿IÄTjÕ/BUƒaϲe]©ñ‹£¸Îý.æ(rÁ/ªB‹/Å¡•É#m4UM&Y I¯H>‰"ub|’K7ö…¤]õ~2U jï[ ‘g –*bx d…Ó¨(Œe‚7]%¾› >ó=y ³ÐP…» f¨… ä¦44åç†À霔=´³;=þ, ÊÈ>ãµÚpŒcDB–Ó¶OŠƒÏÚMö÷͹›•lšq²nbwN:d'û£‰? %¼óæQsŒ+Rf´—…–?AãåôÑÁÁT~ºJèlZ íR\J7Ù2„§µ éŸ4y‚ yU4ƒ©ÎÙêÕ¿pûó”¥ÇMå!211¬_{¤«P™-X6`‰Ú$Z­HÓ "¹`Û¢GísG™Ü¡"ÅÅ«y.Ý(ùí¼‘¬o¬0ÌÇÖìò~>«´0÷’Wôó]¾È3;#ÝwƒééËwã<ý¸‡m«µo-Ná¼PŸ6Àã“Æ.'±‚Ñ¡WÄ »O*ò‡œÊ±Öw µÝ g=%7Ë+U£ü[j°•6N§ŽLÁ· $Ëb/W–Ú ä Ý2I‘ˆiªâ8¥¬A{ò{–dFÂØ?ž¥l#}+ …š'~5´]%7c„^uØ@ï_µ˜Ðyú—ŸésÞ¤ŠåA» å²?£´çX¿wÿpý ë3ÏRÔxÞ¢cÂÜßÑF1=GöÁÕ˜ CeÔgQæž žÎŒØò¹;*[“f¥B^ ¦Ö >¯ˆÂqX‘°–›¿#Tƒo^;åSA‚ÕÂDvmø[s¹´uSÄ1˯<â ¹›·I2®¾Ö­–m¬ðóé’ùsþ%þãÖø'[ ȳrÚÑ[Y|‘„¢?£¤–M¢[AŸôJó–q¬?¬`Ë7èöFåû,ˆ˜JíµÆtËoméH#ë–ø½®A‹{hŋܺõuÕë†Fm9H.ŠÒÎoAl}濳]t$ÁøªˆlzDÉ~~Q›7)¢†Û² ra¶@â[ ™(PºS>>.*¶ l±t¼ôGÔ vh])Š»7 þâˆ6ó¯…=÷®h¼[ö¼géDµ>Ñë©æ¥è~ÏW¢¦ŸÂf1wî«Õ.ÚÙÚ]ô.Hí´”Ëßc!Ãb#G[Y:â—A6.Ò«È|ÐOì"ö >*®®ÔŸ^#øž_‘ËÓŠbáö¢]™›æ|RqoB#cÜQí'<ÅÛÌÿÚ÷p£³¦ÈèŸ÷0ÃQ„iX(„H®©9¿NyuSêw¥‡v°-kåi€(¿°kY¥9CôÓãœ)Ï{g ÀfÍóOAër˜óÀ]ywa˜ùZDT„ª½°#2ˆ?˜;›#¢~%PùÚMFÛä÷&J©ªï¶PØŒØC5wÏ÷×Ê.‡ ¿õÛx¤Ã€GÆ'åç.,¿O·+^þVß•§Ž ¹b ÑÉÝ3:ÐÁ¤‰àyÁNã_ZtåÁ"hdž:_g®ÔãPæ†y¤?ÁE¾Bz¶Cd–‘Côˆ€`uDíHã³k|²¸LDÔÆ×Ä´al·j÷ |Ò?c‘oÙÒ1÷çŠnˆDaOÒf„íªûé$n:L»é£ö®ö#G5Tþ84ò þM?¦à"иڼçJUº#'"Bfг2.-*ˆ¾­·ù{燥{´½»=D8úr ö 6¯…a™fŠ »Ã-#¬n‰ýÊfh®ÞoË™Z¢z 3ª¬´Vª)“2Œ—uãig0[g(ZÔVí«PË9ö»#ȹ »j+â'4 Q‚5êGý—VpÍz€£¯oTcLI¨QLü,®lèXø)Ì,IÏZŠöÜNÀ…™Ä©)c Uœ¿±ÑS@XêtÈ—\~FhUO%‰’©ôÞŽ{fJ¤†YåWCŸøž¬ù+#J«,††¼âЖ†K›€žY»«ê%þ¶uÒª¾˜¯ßßCð‹E±©k2[‰áho_l•f¹ °Xß<:¦Ìϵ›uÔµE0X‹Sd˜ÂžÈK‰ØFÝŸ2—vjPÇU D†S. hYkFÊÆX6„ùuhHÏ'tºh鎠¯ˆŠn|¬ {â×¶r¢È_iü‰ƒ!¢èø CPy¾|Úçó#æ¥P…kÏÙ öX«xrè²ßvY œzÊä"Š„hÈYåe½9Ýh”’±µpÅä§tÍø4^ Ÿ6ÌÆX­fÖqµº†]03D¼G÷üÚ½Ä=Ÿ¯ò]Ê^|­˜Ý–DH1À ßëž?  !¸¬…Œ 4Ÿ}Ç¡Iž)«³œý+£ÕÏyÈþšÕ"; @¨77rýóyÕeºi­êŽ\÷­ñ»Gç§¯Ø bîX­K³½ïDw¿´ÙÿœÊ²lĽsh§²tÔ+X´ñŽ{ œŽ^ýDÝó¼a~³©´Ëù Lšµ–Ê{n–bÛ¿-Úp¢ ‹°¢ ;R‘P¤©]¬?ªÉy‡HkCc-²jbô;—uÍÇø…þ!Ë<³‘ºƒ®‚®›“&·½6Èøtp³qú›d/õ›¹Õ«R½r{|nFR§Fÿß<¢Þºè6?Êÿ:é endstream endobj 649 0 obj << /Type /FontDescriptor /FontName /NCOGKM+CMMI12 /Flags 4 /FontBBox [-30 -250 1026 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 65 /XHeight 431 /CharSet (/A/B/C/D/E/G/Gamma/K/L/O/S/V/W/a/alpha/c/comma/d/delta/e/g/gamma/greater/h/i/j/k/l/less/m/n/nu/period/phi/pi/r/s/slash/t/v/w/x/y) /FontFile 648 0 R >> endobj 650 0 obj << /Length1 775 /Length2 1538 /Length3 0 /Length 2085 /Filter /FlateDecode >> stream xÚ­’{” ÏÐöÚçiÿ}^çŸßçûýü¾¿÷ùü~£^NL8t…¹| –` i4·M€|‰Ç£02ÒùÌ¥Ðù -@°±Ùl‹`DKomK²´%Q€ ‡ (8„˜’ÍLÖ€D  Ðèü#ŸÁ ³/˜|!pb³Ï…<ÀäH$ÈÄ¢€ 1ø@ qQ¸$7. ¬¿–™aßZ‘ “C¦‹˜f€’ sÙB€ ²P8wX~(gù`}?Ü5‚Ív§sÆ/õ6±…`NXDÌî÷Ö_Á¯l4 Ep¾ïºñélˆáÄ fƒ€Á ‹·úZ‡x®dî„øŒ€EgóÀÅ:Èe~O"o‘GvÞåîLÙðõb{;é—ï- üßæEMø[Ë#B à‡Çâñ¹Qþ}[íùî,.fBÜ`€HÚЄ.Dá壈$E . @ŒÃra¾| æ7€#¨…[%àIZ¨ý%­ܾÿ’›{QþóaA”üáXIò‰VÀš„ÿí|Œ¹üÅ7$é›fAòdAP2PÒN˜aw8ôü­#y"—̶|e3žaZîᇕñ7Òì°Ã½vZHé#opí¤f¼f(tU#et{ŽÉ"õëßrŠnˆòÂÅwi6¨i›]{-g û(6Jîתs.{+]7Vºaüùú©¾ÈJåƒë ýÑãJyÏ:gß‹öÅ´ôKUS™ëߤ öHÊw$ƒ»Þõ%6¡Â™°4»í/žúaNª_ûâɾµ4›ÚÒÎ+2?jaò¸i^=½»'µ.zÊsç’5úƒ›¸·fu¶Øj¬ÌÒzýTj“È‹I r¬¢D=ä3M}Åø²/:W¥v`N× Î¾Ym¼¬²œ|)R%ùPhçg‹º‡å1hARäÀaE!7ÄcyáÞ‡¢^EÖSÿ‰T§ß9çæî.êî&:s>W³ØÐð]ƒñû†r Jù“Câ¬à_©}ô—øì³èl™ž¹ƒÖŒŠïäÔÒ­áˆãþ¼Í"“£â·‚@=Ør§úµÓ1,«»­ZF#«Ú^û¼  ³<ááÄ{jø’»5¸ Aãcu‡\tU”òS§Ûò½K³bßê8³<ŽøŸ¢¸w OŠ4•P¾ÉÕû´çTС° i5ã–Ý®µ`•íĺSëû³q‘ñ¼‹¯êNøöŽ–?SêðXS••®Ëñ¶ŸMoᣕ÷‹ñè?Úbfr狈ýù™ªú 4xYÓ­½ƒæ¼Ñ2ÌmO^²Áâ•%±M¢4¶œÙÝå„6“Ĭ'Î͸s»*äË4ºP;iÒnç×xÓî—gærrËé¤âÕ%¿)KºÂMZ?nñs¨’œ¹Z ¸{Öñn2f876yHµóørúQØÌ4nè)ý¢ë“¥èL)áüûõ ÝÚ0Js6æõmtk†¯R àÊÞ~î ²jßâ%ö”n«,%ÁMÅwø ¹Î€w,GæÿzJ¨P£•ùPtzZ£¬æRºò‡”ê‰áL«¬ò½È¦ÓP5;¼ª:ãýµ4GåÚö¬Ï‡gêFMúÂŽœóì\ýô¥ŽÊòóeÑûÉÞSzáF5Êñƒé†fÅþo˜ä`“ÒÙ”×k3šÝ†½$'µÛâfSÍvgs…ª± ›Eõ­¼?:㦢K\Öð±£³-—C '³ªs|V(d§¦e ÕJ•âÍhàÙ”ó°Vsuoz™Nk e‰RÏÝrÓxß{Á{E?ßZ3¿©ò† öiåpÁÌ–„±xøaN—LEW¿hvoTæËWƒ‚Ÿ×†#'ŽÌm°:c¸¯°G5pÚ÷xK¸¸²úxOøÇú¢Uoy½r¼ó£=Ö_ó_°qÉŒ´05-|$\Ýöx³5Ôå ö<·×èkÔ! ¶ŸÜp©qÌ`uÀÌ0ñv¶½Ë¦V<‰éšeÛÆ¿­Ý–¡$œhPˆã”—Zµˆ Èç¢z»·'f×6n›J7Ú¨‚(Lþ1¤÷(OB÷íPpÏoOÉo ŠbµZ Ænï&Î,Ê\œDs~^P–çVÍkIšîR{L¹f#^ÓçypsX^b)%*ýÓ€º¹.úAýGüÜ“.CÀ4âìÉjmå©ÏIçËI¡ÒN÷ kN‰ûMk–¤Ûnçí9Ýhtä§¹çäÕ1ëÍÌ™8· /GŸ ‡#žEoçt4™l­0.V=tþÕJqõ‹ó5ª–ùiÖ6§ò|«‹-cg|ÈóñúÚ¾ŸÄK*!µî•"Ú\MíÁîûÌ+uÌ‘ºjmêÜHGmÚ7n§ã§Âon;äd­g«*-¸‰Þh¹í]®µ10wP€–©©ŸÆPïdž´®ÈtÛ˜D…/»ÊÚÛG›ÿôx†Õ8}ŠC3¨ÿbÖ‰—…Ò1e1W¯]ø)Pñ¢ÉŸ… >Ý›³F7f¥&•Qš°ÑõZZ5ý/¥?öOv»MtìÝa±nÂ#ËÞü˜ùÝ~Ë÷ Ž÷‹ÐW»vì']_uOñßï½Ú‰ÑmÔð–£Ò¢êÿB V endstream endobj 651 0 obj << /Type /FontDescriptor /FontName /CBVNBD+CMMI6 /Flags 4 /FontBBox [11 -250 1241 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 85 /XHeight 431 /CharSet (/i/k/l) /FontFile 650 0 R >> endobj 652 0 obj << /Length1 953 /Length2 3550 /Length3 0 /Length 4178 /Filter /FlateDecode >> stream xÚ­’y<Ôí×ÇK!#!dkùÚ•e;•²S–ì1fÃ,Œ±eIvERÈX²¯!ƾg,…¬ÙoYÊnB(ž©û¹Ÿ»ßýû÷y]ÿ\Ÿs>×9ï×9—ˆÀ )5Á}€'IA¥¡ÊÜÀ@G ]!ˆœˆF0¼‚„V JJò€®'€Ée9e9Y'¸ù1NÎ$@~ñ§IPá‰$ HÎh­LH šä+ ¨a±€ñÏ€1ÚMôB£¤AP(€Â I€Ú ƒ"éà €Â_a”§Ûß)/4уˆÿ¼Ð Q<Ö@¡A`C­šÆòÿõïâ×=±XCîgùŸƒú¯4‡Áúþ¯€só$¡‰€…&âÿm5GÿÅf€FaO?êÞ[Ñ"dFs;¸m’·8Fy[&û]'XÈJÒ Ž ¬[k½HX/|ƒŸHjóß2¾qôï¢<¾ò×e¶“E§g‡F•yÜádý'àqÓtaUß¹ÒN% ŠÄ¾ñy<¹c‚’-téS|b_ö¥s>_À½/–”Pi?x“æ@P÷*M5¥îÄ:´t^·Ì/\Ú¿5±¡auºP½Ywçý?{aozÑÂÏ2zž>‚k ró£øÍv­„œ¯¶¡Õĸºø¾¯‘\dë™?ÐÓ¿äôµñ¹îx§1EéàÉWeL“HIÒlÃí7fœuµ.¯ùƒÃGÜ¥O=&„'†0« Sl¯5»Lƒ~hµ=‰UólÃEN /Oµé™/Ýÿfh>xë:#ìÆI½ݵÌòd"äèæ ƒ7›ŠÉëÎ…qõá×G¹¶ýÒƒ!OQ' ðúݽ^gÃŽÙ4ýí—õôú0ºÛÔgç¸,å`£‚p“¬œÅšÁõUöñšã†ù6 f3—µ•¯¦5þµù&~ÝlË-lZ2ÊQQòjiaþ£[Ïj€²ìÑ]™Wý1½èÈ…„â—[r¬ìÌ5^0g»GV`/Ÿ/Ÿ&[ŠÏí /ùh!áÊO?ëå’܉Óàãk®gÐ'3ˆZQÍšàÌ3GðQ"jò“¬²ÍUŒ_t«á/tŸ†^H%?Cªì[ߪ>=`yz×›]C²qsôÇ}ƒämÞ7ÅVœt2~º_ï+Ù¬( êÆUM0%o#€e Q~ÖöÄYƒ+V}›GJ{Jì„°\ö[ºdxj¡)A¡š¯¨Ã©ñšž>ºw^S›£.š,•*|Ó:ëŒ;¢·häý*6BõÖ\1¶|"J¨á’\úÓù™9É\kªQX-Àü ­ê³ŽmÛS¶y#Ais.‘í¢R«Y8E¥—»<§n&Žì¿w]°ÝÊHx8 br¤ó+³ %Ká3ŸÆâ"ƒ]ïŒ ª”Wj®ãD©šiz÷ Ÿ pFѵÞ:¾*ª9êR«:žŒS}Am4‹1œÔ,Ô7èjºesÍ“ŽzŠžcÀÉ[S­¸OÉ‘¥F® ÇÄW­€ôEÙ¾\¦›ÂêÖ²vêw-Z7‡ ‡äço‘T¥Iû™ÆiÙW X®àEÌ`*U‹¦lîÚ/™ ?hY0„ºgø±)àú^qëruzÂÜ–yš ÍÉûÈy8n³‰»ˆ,ìž{?‰ªš:Vìé¿^\èA‚¬[s iÖ Ü-ü†nf_þìu2Ô!ö³EÏC7ú¥AËaF±  ûžT¬{<¼éÊOU×6‰ˆ•\Ðh‹¨.P¿,Ü¢Y™Îó±Ö÷Ò®EVkWïàîícN.«¦jÚÈ¡¡çff÷¢âØîuæ$ô¯:ÜQç9Ána°·¹—:g,C‰„÷Q²¹k0äÖ Är:úÖ×^Nçe*·ÿ˜zÓ£Eódµ]L—e‡ºg NÀ§FŽ[ä΋%ý©›?šòå;~0×Ð:Zu±/t‰ ª/Z9UÆá·kF†œUú(€ïmκ«-ðòȉùÇ YéM¶,tÂùH8íñÄuó ©'d$縰¸ ª}™Ì(÷02¯šéA¸çåb.†a½©UúÛgSñAÏ먴—Fœ;};"gèvÝkT‘‰¾VL凯¿ú³Ý Lßû&K>dªè|l칎møä|ˆ‹4»ŽºŠ-R°WÎÜÍ^EÄ"ÄÔ—õº€¤•Ê ­ç3Yy27¾f•6ˆÈ<'¯rÎù!Êtg¤ù‡lMRm,×TŠÏÚ£§G.ßk"…-Œö¿±”ÌÛk‘ŠzØÓJa[Ü$Žë“?€—;ãío»=¨hˆ¿º—’”eÙ"Tv1l#8!ez7Gå†aɱ1wÊ¡6>ˆ™Ëº+ÂÇŸpú¢G˧Ю¨Á¸-)®šËÌ¿ZÌ>¦£}h¼PþâƒÍ‘Ó/“,†!’ÚžH|Ó&ýfÌ;Ò‚=ˆCr@0ÚÆp?y&qÛéºÉW°”•©àä÷æÒ5ÕV£‡Àà•6î¬ß¥)!÷¯ÊëÁ€Þº'Ž7*¢…zVë‹¿Ê7~#°<|rйú™ ÝtÕ6 3-qéÖJEiËŒ·>iuÔÖxGôð_ä‹”ãè·þüä{G›:tœì$Õ/Î%ø3…xò.-ë3ùÞ7k{ŸíæÑ¯ÆÙe(A:¢ä6ÿpi]´üÔºxn0]RVMzÚ£c5ÛÌ,Öí©ÊõHüu~©¢nÑAô¾Ý³í`ã«^ +Å.ãø” Žª½I§ªTÿW“çZÜ9Vº–œÆT°Âu˜úœ@ï÷ÃŽºíƒ‘•jKjÄl‡.Á¢)tÈXrgë]Ê™í¨g.aJêžœzqÊ猶›¸ªÒ;Q«æ¬¢ K“EÀÌ»øH±kIŠVèR£ïô€×ölËì €Eºi Ù’sŸ=ó9Úæ8Z279~‡”â©H<ðzÓzð‰¹µ„ÓÐ}ãïÖìÕyÇzOÎï¾ßÛžÄì"=ªbwCrÿè$CígSçÆ#)ZÇ3``´«ÆÑ°W™~ýü³ª^ܽ¦eõÚÕmyV=sÞ(ÿ¾;ôù‘/¿"&‰û*;oÌæ Ë.D‹Í4})—s2 S|hú¡îº”ûª>wϵ]û{\mÍ„,äkÿŒ*;Ü2\ÜEö&GF·¤è…ª6|J‡ísÅÏ-ƒ‡g¼{uNÏø\å³Îšy·¢˜Nù’r¾dgçörÆ£4Å›½ìÙTÉMdÖGê FˆË¹Âîç_·Ÿ6Ö_Kß-ñ}kF¡Š³J$ßú¸Ü^}góðA"ööt‘Sil·‹>¨/dñÐâ¡ä‡kokv˜Í?…ô/‰BÊÆË…øwÜdr# l‡…ίפ~[¨¶§sÖ Ò« ?“×­¯rϱ)êÇë[½3e‰‡©¡IóÆE)K<¶^}H±ºP–÷?¥ š endstream endobj 653 0 obj << /Type /FontDescriptor /FontName /WXDJCM+CMMI8 /Flags 4 /FontBBox [-24 -250 1110 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 78 /XHeight 431 /CharSet (/b/comma/d/delta/gamma/i/j/k/l/m/n/period/t/v) /FontFile 652 0 R >> endobj 654 0 obj << /Length1 1414 /Length2 9228 /Length3 0 /Length 10052 /Filter /FlateDecode >> stream xÚ­•eT›ÝÖ®q(PÜ¡Ü îîÜ¡xpîîîîE‹•⎴…RÜݵ8Þ½¿o·gŸ¿g$#㹦­{εÖjruf1sˆ)XâàÊÌÆÂÆ©±±ØXXYÅ‘©©%œÁ&®ÖIW0?€ 6}}xýòsqòs±#S$ Ž^ÎÖ–V®: ú‚xbö`gk3ÈÄÕ lÿZÃÌÄ 1³»z±Äììjÿd¸ÔÀ.`gw°9 2ÀÜÚÌ` ¶´v@þ#IÎÁàù·ÙÜÍñ]î`g—WQºɤ¼Š4‡8ØyÌÁÈ@%ÈëjàW-ÿ?dýwqi7;;%ûÊÿ3¨ÿÇmbomçõ?{G7W°31;;üw¨6øßÚ@`sk7ûÿöʹšØY›‰9XÚ¬ÿ6Y»H[{‚ÍU¬]ͬ&v.àÙÁæÿ-âurÿ’”–“–“Ñaü÷žþ˧bbíàªáåøŸªÿÿ‹Ùþðëtœ­=ú¬¯ãe{ |ýüïÓûÿZKÊÁ bní` `çâ˜8;›x!¿žžWâø°¬ÌÁž°ç«` ‹Äõ5ð:?€ÄùŸ åæÅþ1ý›x@‰?Ä Jþ‡x^Ié?Ä˪ý!Pýq€èuÍÿÐëšü¡×š¦ˆ4ûq¾V1ƒØÛÿ‰fceÍÿB6ü|møïýð*Ò⾆[ü…ÿ8­ÿ¤süƒî࿲_-–á««¿ðµ-ë¿ðµ/Û¿ðµ1»¿ðµ3û¿„¼öáð¾ ƒüéû5âð—Ž„:þq¿æ:š8ƒìÀZådû«óÿ5Î×™8¾Þ8È_Sc{mËé/|mËù/|mËåÏP^µ¸€í­Í v¿¿–ý³׫"WÈ_î×Y¸ý…¯³pÿ _kzüµ ¯Ùžák#^ô¿¦zƒÿ]ûÿ½cââOfv.6Àëë?çƒÀÇÍç÷Eš¹9¿ÎÅõ_¯°×«ú¿laýz±Á`O°òü,ÄL Ô&£9¼Â_ªø[%<´¸eK¢R×é.”¹$h»²1'†•zûªll´ø2Gb—èN_ÕIéÓ §ÄÌŸÏ;îÆ;ÙÞmÄ:Ù ¯mGŠ›CôŽæ™«#.hå+㩺%ƒygC‡Tè$5v—È¡zõÝ{sB¹yt¤³í4#Âêi8ÈÕ02*"9#–=0R“á–§Büm"ZÏ!nX÷ÅH…)Ï7¸ ˜fdj 8j»"GK"0Ðë^FjEs–ê΀ø$µ1¹|ìðÚä#3„£ú˜h†;± í|Bøˆ¦$…†àî¾ÓÑÈMUÝ)üyÌÇ[àù£ò1ßă½†~}ç@¾!^†9bU^ª¦ÝÌÕ©vŽTóm(ŠÈP03w¼€¸ë2Âwm‚™t/±Ä°óP€œIátœÓ‡rÅìÔc¨”Ò°öÕš†Lí/@æQ1të'+LôLžôí s9ÕU}78ö"Ö§â&7=Þ¦Ý †ª^J„B¢¬Ç[‚<§ÖÅ«4•öƒÜó6ßžá‰t¹ø‰”"|ŒfG°ß>e™îb„6޲,‚ Ýîæ]¿Ad}h¢´êZ'îÉÔVì¤Yäå£ÀéÜü´>¨n«ES÷‚lý‹}øCˆ½™ëÛc ZGúívÖ¶½hQª~v›—Ê2M2|‘Ô5Y7ßñå$E{ì+¡²VžØM¹Ò Ì̽ȃc.¬F¼Ibkì<›·M>#ft3±7ª‹ºý–#Þ×ýþ›KZØÉ2_-@Y â¡Àpû|97$ŒÉzFwi—l˜Â-Ö!-þ0é)$ÜH&ÿuà–c£(i±1‡v3n[ƒ°ñ½–yýÉæÉhÞ¿²'Í*£¼ÓS)üm¯1')>ÒXîü*%ö`¡•ËÁBA^›‘—ÓP!i.£‰…8&QÁ*ÌjНÊtú´ÏZ’îÔ&EldŽ{W•Æ‹45ïYàõ~d-©àéOÐ}>NÌxg]Šl¢ï$¢Î¾6?¬ñäž9ÚZ¤CäPä\ßKx!–¤/5¯ ¥äðuÛ¥7×;Vk"a+  @ÿ5òóÚa÷=­2¹é5a.œÞ» ÑÒài¸”T¾å™W¶CN Z¯U¤oãÎÙ%!çD«Áq+ý~‚E„„Pôˆ@Õ ÐnuÍú¡ƒ!º?U³ ñ¥ÛV©ü-‘Z)½…u]ìñ T2ñø„#sÓIÓLÕjößqð%Ä3Ã+ȼˆH¥yf<.¶E B“ßU4„…KzùN¬'·تh‹ï®âbxŠÍ•¾DÌÿº~C)g•d`SP%è]Nþ5cý)í9Å]k8Nø”—'ˆÁkÒ>Ħj.OšLòΆ¤Ï²õL䜾l©úÉ›ru‡$’ï¡"ZM˜RÑ`D‰« †}´Ü Ò&Äý›7I{"¾;V (lª‘¶GïÙv%"ÊáBâ9wvƒ ÔЃ:?%£ õ’ˆf…§oL’>çfþ®HN†O§ÕxžèÝ ÂrFÇsïõÖÄfÌÅGƒN<•)@•uÚ.Ê _楧²úŠ®£@RìFJ÷‘àÙ¡|&‹îñ é—µožæ ‘Ö>Ú¤>bIšå::ùÙQªë>Ï@p•àìÔÓ³ñ9ò}zk»Eµ’ýgˆÓw‚hëIÒÄ-SÈ ÍòËai­±à"“Ã.8·zòÝPbfç+È%MóGÙÒ@Ûo%ݤ)öλ›çÈ[DÂF1KùË]Ó—eéÝ ¥ï\yEñéôTÓ…eRÌDŠ>X ÁŽ825\Ñlm-ªµæ8–sšÀ1¶m_3…e¡ð‹'à/”¹µ`ìœùÉj‡ ÿQpp’œÕÀ„r{ WGO…J»®TŒ˜ZÇâ¸Ñ郜÷t™“¸ª¿ãÕ7¹®åßINàØŽâ¯q̯´KT®Y{kôN*‰iî`HL²$k U‡z½ÜŒh‹ô^Cä·* o/‘ht_fO|“²ÓJU”¯*&§V/FÑ[ ¿Ü´ŸmYêìI4ëf]¨?ö‚)u^ÇC:Q}G·ï˜'½48ÏEP}¬àaStÞÕ»ôme”âTþÞ¯“ß ¯N{nÓlSo¡¾ßí…{}ÚMOÂøh+/HëMú@&•øÆì´ü%šc·õÚ«#¥“I–÷ LQD™§w…‡úªEn ã^ˆ±6HÈ7É kjœP)ƨ8™5ÿZkõkúþ~&ž£S=mÿš½öÛG©ãRÜq úÛU ž$ž‚ŠòÇŒá›üL:žÝÍkó€>kBBmΦq$¥ªx¬‘d'*ü¾»Ÿ9¡ut£™¼ßfù(é´Âò@M‹+¤S}tí¬gö¬÷Û%,Y£%ÃLë'×±5/çF¼*P¼ î=?ÔÇ}èÕ ›x8ø8CêÃrÐÆ"à?çzƒTb6E¼¶FgÙTQ î[‚ÃKRL¦4l*tç7EŽO2Ÿ…¼°ãœ¾\Á•ˆ´Û¨°}Ëu†.7î€ Q‘Hï œ¼wÐB$-É’aÄÒ­ûfëëò²ÝŒ?¿6r§Dá}Êc‚1–zˆ«7£¾À±¹ÎíË~Æ£þE"7ܦý<Ðã\ñ-Ômd…©kÞw= ð¼4‡{” ™_Ùúj|†ß¢¢äGÂ{FÌñp:³,m‹b›p<Â\³ºœ0çˆ6•=2ù[‘cî%H+OBOdí±6yˆ ñ´Î ƒ(MÊkÞìR„)ör)W¬ôM ²“{«<»£¢ô<³ê†Ñ1¬É¥J×›ê`٭ɼûŽ7×5㉵_e=:P鰫Ħ›‡Ù_ µªg_FUs™ak¤JP6ðÈ 1dÑO=Ž8RBWl5 ¥ÖÑ3Q›,wOš}òw÷1Ú!þÞQ ÖFy“ çŸæÜÖŒÞöÑÒàÅq%ĬRÕo]»…GE1ÇKîR‘™÷YKGüÿ)èïÿ!² [ñ´¥'õIHˆ¶Zàí¢j¬dšÊ/gbœÑjz'B£™«sr ‡ôRw"z¤r®ó&U¦¡Ël­W÷µŸ!§Ÿâ)Ï=ŽÞl[=írœ~Ob4^ù^K…ÔvØÒ»Dضɦ‡c-<4<ñ^¯ò‰jAöÂû€ÁÇÊ¡v´pé~ÄGÏ îÁ Z»JÏÓüýÒ‚òP“Ébg¼ÜeÊ•’Ú3>}(øêp7æÀóä•>­X1BZŸ¦¼aØ2@±Œ0æ ÍŒ¾µ; Å…th´V ¯«–Ö‰n™8…Š‚ê{T°iú]ÑŮܻ3¼‚‘´€Ö=Ùoê Š¥¤f±AL[œ¶]Ë_θ=a¨üåy/ƒ¾Z稥ªœº0NäÔ4_X‰3;SV—]pT;?- „Í%<¨cGLƒÐ7ŽŸ&7¶I]Þ«]4tè*¡wõlˆˆŠgûƒßœž=Tá,/­áØGìyc]n¼Ç@ýæ7Q‡\¢VŽÊE“«‰‰H9±‚N ó[$ÄòZ#:Ε„eý}n$ól™ŽMË\\zÁâ´<¯Å§¥:ŒFE‚oÀ d‰P™)Q¼÷`{lîkOu¶`=sOØs±E«ôOòfÁ”jމJµLv©Ã{;dA§…KJGD}PýV±Xíæz¸ÙωÈÝÈÌý¬}Y-{÷·×’s€}š› º8u‹–w˜¯YÈ}¡(-þÓú´hyËÚ‡1ÊBD·#K—áÑ8~ÿ½¡*†J5SH­ªôsóÕ;îEMÒÝ{É M:íÛLéW)ø1!=°Ý ŒH{s+ †¿.Æb^¡\t¡¨Øä—! KÞkqJ˧_Gw•!Ü–L¹B‚z£¤xÍmÚ:WÁHöæM8ãr“lHÕi¸ Þ‹iè-k{ÊÈî„Þ{“SK%‹†H•¸_ W×®i{ˆ,ßXf:4Ò¡d¤^¦ ìšÌ_~éÉÁ_qµ‡€Y‚éxÃã Ó)Tse?É“~´Ï sN©'ÔÇ“½1\ߤý6Õ]ÑPÐ'[Ÿàáb›êl¸`ŠÑ%"›Ñ¼ ".ô®F>‡ILî±`e]ª³ùKX­ Ï_mž‹„¥´0–ÀÍÎ J ¯eþŒŸhA;?×a«ë>Üs"iO)>Õ–ÍŽûF:}ŸFíHÿ^ƾ]ôL¾{¾{~üô16˜Át]“tQ‘™ƒIÿ^5©„¹µð È+˜à‡=ìµÙî ý†p ©é‚uþÍI?uVDIîíi`{üøÑÜò¸‚a"^5hUg­À ÆXÒÇ»ôÆ‘M„wH#ÂzÍ{¥zò'³#ãëùd¡ü-œäÞyÚk˜—òtß{”S5â©îŸ‰sAA¿ý©„͵Ž}ü~¿–þØ oÍoŠèˆk E‹/ã‹ÂZh|Ÿ~ýÅÚ¡‡kœrI¾AV­ÚæQ9±ø€£ýÀmÏÅþyWtáH‹xZ“Ñå¶s ±LÕÆÕªªw¦?Z»S­k)|Çÿ¸±e=VžÁ$UjžSâxž z ºëè9òët÷Õ:-ÚãÎíÏÏOBdp¥Ü ½úš§÷ºí3b^’õÂjdÏ©X¤)2 JF]„?† ‹¬þvW?m?£Ž ¦Ãsr¡®‡¯"¼»îŸi½»ŒBÍš¥súÂ=…†(Üd¯Y¶äÇKV¸µô³Ï:À…—´÷ËÐ"Ã)zµMŠ·Ë$)ÁÈ Þ<çx[ÍõOYF ß ÞÐæe‡XkÆXy¶Õc+Väã"9o§)Š1èL3͈õ h÷vçÅ÷ƒúBRÇ—"uNO«á¼4EíN‹bêU Ûµ5õÚGN§ÒàHo%:£ðú®ÄãÇš¼Ð7ÜŠ!|_U;ÓÜ­ê±)9¿›8oæ®ÇëБ€ ÉcÜýØrzP9ÅýEôhFÙSS’ñßõ´y¼5¡|ÓÈd2¯ï7«ºX‹!íå¬_%–¤,í…Ŭ[¥À9ï`äTË€§¬0_Ž(iúP¼¤<7îŸpðŸ@ó¸þýÔRê*• …+ÁCb#‚Jߢ€ñeT '¿#sAÔHrœX÷¾0®wÞÂÂ?D\âÏÚ½ŒW sBDÂ-­oý“T©:¢..‡Û_¸Ä˜öÆ1÷°ª ››úú™ï4ë~>Ô»?Ýt6ŘîT\‹.WO5Þr É«yˆ" é”ÎòPÏ ­/OŠ/ñæøTÉÔ¹£¹-ïöme¨o¼ÝzEºÌúÂ:ïÇ£ !Tü„lÔaýd ŸÇ– ‡–‡áyÒ/º¾Ê`ÞsÉ ¢Ù-µ"Eo; ¡“¨þ‚®S( 7gjÿ ðûT–àÝŒQΜ™{jÔÍRÑ…#ª™ÎùvÜÜXô£Ø F©D—>ç^†ÞK÷^Íxm¤ÅgódDá—VHS÷÷Tå•l-½rqÌÎÖ7:fÐM¬”‰Â\•.ùRµk@ö‘+Ư54ì§=ïðÖÎÒ†Ûð@{56û}RH£?év³u"À"QóµI$Òû»:‚y«áèr;©ô²ãwº|š´ìs—÷ûÒ¾Ûj×Y uo¾½Yòùî•Õ§v‘³òDr-‰‡Orxðæò¹*Èÿ9¶ƒ>;ƒ’¡Ÿº& l»¿LÜ‹µQHÔIÄ+—VŽmˆjf«Ð‡ô}%òn±šI¬T£o^àþÖP”åÏ'ýOOaPÝóX'|Þ0eñ‡ôcúÂ" Ecšª}±LöëbÓ —Üê§^¨‡dCýãaç'š…¸²Da5}ˆQü¶3“wØqþåìu¸ƒîÙáOvyZ¤ p¸IÚæ)2VïHxzyÙ(<0"µídÒŘÈêjq9œ®Àí@‹àTÂÂ2º`cÕÂSoŒEÛ̉ûìy8Ð'»v/¾¹gnŸÖu4U¹è«]dÛõÓǘŸH†bÞÁG6%üñ±€Ú²Àwg©é8Å †GBô}¦³Í‘¿CCÐt`r¯s¹-²ÃAü{1,js—¬§,æ0ا5B8lY’/XuÍ[Ío~ÙUò–^·O¼§cÎAîª`rlÙDî~Ï]±(~ŽQÁ¶Õ³ãËH-CP"B‹µ£Âq_¨B’@WJ^&ñBu]Qz‰^CಠƒÓ‰+Çg&ŠW³Å2Ë!@ Ι ¸´·2öñRVˆú𩵦áœ, þ ºNœ.QƒvS¾r¸šrÝ¡ïC•WøA3VËw^ÖóåS¡4ÿ»À¶vR2ªÈmL)¥5rÍiöiªôy›© ]éLêK¢Ö°œ´TØw a,~ü³ž ”ÒÜî •¼ø›é'Û’ói¸ðÚgðâðoPŠòŠS<¨è)B77ê®òô?ÛBa¤TLC—Z©Üߊ?ƒ$ph鼿K£Õx¤Ðßj0/(Âíºí»î<Ž°ã•¿)¬Älê?®ÄÞ7ˆd«Šå†YÁÃŽúDÚïXƒY–1hNÐ7Þb•Ðg#ÛX wëbX§3ö`AŽ{·¢9—×½ªCF\c¯Ps/¸Ù}¦­Xɘ’u²óÖÌc5†¤ÙGVðÇVüÎ ›œ¾Ë,К}÷ågõÓ¾ŒŸ¸U"]ô©_‹Ý|踬ÕÅ~ÛX¬åÞzŠg¿~$ûöÕ” Â×…cܽÝMÿÌÝŸùÏúeRæ.Œyzwˆ_Í>„ÇA· Ê‹0BÙE,›!u4gì(îJ=«áñ_BßÛ pÄå”N¾âàÐîôæ ®¿ cmÊ (жYE„w’ɰžÎøNÇ®(h”Šèp O³KÒ½ªw’Z'%8xÜ2&& üûäý†ß:óÈ–ë#+µ!½­µÊ}öéßìÏrzèªk~ø¢ryZ‹#ªë©eƒÏ†à%a«p©¨YÏnöÚ í *å=g·ÊÎáâ¶Ê„úÂf}r ­Ë2>ßVÓÊÉÅ«Ô/sXSùÿò!í]OEçè…S !lv÷B)ó‡”%™_œªî™7MXSÊÑö‹¯3ÅOq扸ÛêÁ‡>¹L¢ ³‡c^w­8¨¹{+Ÿ‹[À‰ Ñ3ziˆP'äv†›2¥m©‹Üå49˜O’6áV«•/Àé`¸káäš³¦r½:†9ü¾…1ýh5Ÿ¦Ð®q£öé¶²·äHSAÕϸ9œMÓ :…4Yü®“9T‡ÓC©ýÙ·ÝTZu2¯ÿ„; ŸŠïÓÖÎBì9?~náÉ!?ĉȠ—=…ƒÙ7]·™-È”]V:ùŠ,i³æ1"ΛŸYO+’²zcP¸l‚$¬—$W:±HxÇšcŽ£}ž^À´–ÿ¨cªÍ!ï VÊ÷Î?Ú»–:é£j!yí(ªÏÖò“Bÿé}Õ[ŠŽ t].¯,XlçhMÖp^._RùÕd  ±i®Ï›B™/`ù¹ZAÏ~Cvל¼êgëw¥÷í× æcÌ ÌÐk1Lf·ê—3Ê2 ‹¿…`ÇÎz±]0sŸz…átñp¥‡¦¸èÕ TUÚ}`ãf%p–SZiÜÁ tÕ ÌPÄ_… j‡¾5G'„FDŒ£YbÃi&r2£°¥¨—¥AK-bOÐê”AY:ܱC¼"ÍÿMÕ¼Ýo>(T´Ó(`cØé~ý@"ª çpúîI” å|'‡Ë’ÉsqåMÍib{[®2ioâ‚âÎ$«›œ$îUèZ9‚–’û›Uðãò¶Ë=ŠÀ dÅšRõ»éøÌÏþH® Sk¶;¶4p¾›M:B¡Á7# P7ä„=°Ö¡_q\]¥Stg ZË‘ú1§.‚ÿD—D‡ó\P!Ý!Îñº³¡'¸@K:çQ ›¶b‰Lé. ‹õy'‰¸9Öm_8@ÌÓAc )òÌê>ä· µ=I>Kª_u]*‹J:hÊñ QÓ¦½øgñ¡fëòƒ¦z–mðíB ÍÎ{âúÎ{z”Ï2Î-¾Ýµ]Ü8 ÂE¾i¨üÃàÇ·ŽÐSß²$Yà%ö©ò¶µÓƒá³ÖÖúY‘ŒކŘû¥.üú©Š"\^eÉqkÄaÛ%øÀÊîdÝN¿Iq£œ%Eּ⺛#è¢,?£Cf¸&Xç|Y%5>}·Y+Ö&8ºtÍ´Ìè²´Ë<“Ò-O4éï´"ßmèÊ¥`ÕòÖÐÙ4:ÁÏÄ;¼ÒÃÃ<ÑMD¯~6åðmˤզî/oݧ–®`àðåmÖhw¤«Ýà.V!Lwlà`äz„™ÃcÌ+¶Û]’â·FüâÉØQ{Ä\!,uÖPæq`–Û©‚ 4Õ¬yˆ¹ðàŒÔ˜‚%“døžˆñPÍ »’H„v ‹ö{ýdÙ.IrñÛÚ¡yô,y/à™0‡Øý(ë©Uʼn·ÈáDUxÃH ‡8ùÆÖ¯¡?ÛóÙ‡X0Ž”#õF»/éÚ$ªÌÇ@pM´Å4†¿»&ŠÅŒ‰Ç×V…±J¸© (èví.Í·J0ªÇ¸R6ˆW°³›lx¶šfácJ-{ýŽ„âࣉ§–tF/i¡ôãÕ-„÷ÖˆûÓig°G)ÝÕÄÞ´çüTv8<šãñJ¢Çíð£Ì!ìÕà žyû {¢³Ê„'« XËcn Ãh2¯ÇEø‘ ˜nA“íu&r0´Vèµâ]þýùk¡oã ‰ÂÁ´~méKž¥'Îàše2cu™=ÙKæ¬'„ýðhNu[°¼™áçÜĵz%ò³iVìM<ÜŠÁ‡€·í[¶FâXhÙ6žx4€{ÔzHÕO Ô’¼fgºytÓ¨xl%óÞ€¦_ Mýû\Z—­Fi°ÇŒÅ¾‹»qÃ?‰Ïû¡‡dÍBYƒÚ~ꢑþƒ,µ5Ñ[ݨËTñIâÏãŒÒð2¤HÉ äˆO´›žúaÍ,Ði9=¨äK?˜Tœ>l²Ïïã‰ùT@ë„ ñÛgâ(£6òBÉS $.ÏKs†g¤b\=h  ÌØ°¡8ït_ gù¸†ïi†ðð}ã¯;Uyô\u–8;’Â<Ì/ŒFò“ÑÿÕ•¹W ¤È? þ'Á5òýš¿=ï+«ÊxY,âì‚3Áƒàçí1ó‡´QAgvmxz,}"ÆôÜg¿Uáߟ1Éw¾—Žoù]¾€óU¼É†Rpb5ãÈ=¥k‰ñ”t¦vw!®òŒÑ+e’¢(ÌœzòÀ¹©*bR÷6?J£ÐLcº*\&Ci¾–Cö¹s›fëäö›œ<Íya p6Ak,£PC-k¶È{cöíhÎÍH ÁcÔ,N‡¸qÉÞxhy¬X; ’yýk®t,Lä–›…è^N³\Ñýæ¥ßjð·è·Ú9)Ú†¤býLGüðúä²¥=âš<¦\­9[éÝcü¸3AÉ„Óc¿þ ¤›_ç­žFøV k#{:ñ%pÎ14yé¥Wñ„ nÚÿ»ûˆX¯ÙÛ哼¡jA“:q¦þJ}FÌFÕx?’cë[ «øÊñ÷LWÊ|,îI« á[ªÄœI×JÜ÷=åªA”H0uâd=o êkæ½Sè ø¼ØßŠEb“àVŽEÔpUH ‡ MØõý.¥=ÙÕÓñ7Ó^~¶éqEh{pêä¼u_Q¥2ïŸÖ lK­Óz£Œ<©«y!ñrÓyY¹B„Ó·ú$ÜZæÞmÊs¹õi%o´„.0H|n$wæóS]á>Ó¿)v™7ÎVîUDi[zY›ô}Äæ5DòÆ Â‚Úïò¨A*ÏǶQ–¾g¶^âÄå{޹:2{›ïO;Í7‘yÕžFˆ²9_x®¡ç­¶Šƒ«±ïŠ<¢`ÞP·‰ö`Æá±$§Ïajl®½ž @k3h:{äJAÈAw¹Qæ]ñ™CØ`¥·X¢·Y Y#†“>##* Á\¡ž·^Ihúšâvÿ4®.8pÉZ&Ïlá¹’1aÖ¦c™ñÙá&SË;ø\¢~–cÀ¨º’}†ž36.}T´&ƒ{¢&Zí{‹=‡q[9Èž•fMEö,ÂpÅv~›Š‡P²?˜Xm:!ØFMYrü@<ÆnÆì¨¤7Úwëš]‹ø¼â´ÃÀÜ:üQ¤ÆàíâÁ9ÜðÈK_ýy‡EV¯‚9êlÍ"zm;vÁêa6Z"’|¾È¢Ò4(_V3¸Õ^O§(1~7ÂO;zTãgøZ§4j źÿõѪN™ÁvŒoú¸¦º‹ FÄeSºÆ³íôâ3âÏ#*êøblµûz‡_aª˜o¼W m ñ·¸é–šO±3¹óèÄâøZ—¶©]*è°:J}¿j÷’Ùчã›2@ýõN!¥jæWžp+½Yys­1» 5Ûdö=[ß\×+gb_4$ˆ# B(Îàe“[Vu®5l¾Ã?ssT¡?¿p÷aMûFã"Uà›ðŽZÕþt!]z&GZ³…þ®ý†uy ܽÆ×–¼>Èõf7ÿáxãòú1aNVÆÑBöé¤aäX<Í£\½SЩ¥—é»×ä´ÚCfÛ“Y…( fØj|±1sË# ÑHCÂ÷ &¥bÁ§:”gp/£Þ²bghÂaÎlÎ1yàé/~­'Çòfyô/øüýžbÝëï‰ÙÌýdÓýò)¹ÏO$<·_`ù0·°`ã’à¡zY6ꢉUBKüuÄ’ÓSfjàœ„”…_μ'ÓRBd¦`ýýâì]r§˜Ï"¿ƒròæQ[nï—PE’ãÍÃüÑúŒ,ó(±TIÏHñhdõºÛ‡“„vße×zêˆï?Gdï¡K¨›d‰®ñ‰=EÆ ù1rZMÿz45Î… ‰°çAŸø©œµ"“!ø“ ý­Ý²Zà{zÎÌ þg&[I7cãuèB]»r¶åòƒˆSâL¾ýÕuO/ Si;›S† G¹ ™ LjB"•ÌÖ\˜Y>àC)Œ¢»¯fNþŸ ákÜf‘™¸A¢ˆ¾½ uW9Ü0D- Ù›HP5¿²¤¦šVË[×~ÝfÚƒoÔ-*ç(-¸Éï©eÖ†–7}‡F'”K÷Þ¡iz÷ %Êb;¾¾;}Ëž€[mÝæV=‘fJƒ2išìÓ#ß.Çê’• ŒAøkŒ­/D>ß›]×£‚Rähž}8Í¡ŽÏvóI{?ø7þ ½H½q®éW¾K»G#¦›Ñ8ýXöPá¡ûýiž iùYµ¥ñ†yÙd¹ÂpÀ"ÜùÂgš«QjßA‡%æ ï*Î7§:ßÔßa\æ·Jw÷g”IÈPøUè-héR¬ð  -Æ£ýÄ÷*%>ƒ—K¢Î—3ÓšmÆû¦Ñ ‡Êާ\¬rñ³÷»&I£fXV˜ ²¬6Í‹þöÂËdÏ…l< %3}_p·—œhcÑÒg˜ÁÆ]o$3ÃMâÞÇØLÉ2V&¦TÒMk$Žáé¨7Owv‡îý0ãW¿nì.FÕûâó(0FmïÍÙÍ[F2ŠEuÞV-¦òÜàãÞJyfQòó¨/pá6°äz<þ¾µ˜‹ endstream endobj 655 0 obj << /Type /FontDescriptor /FontName /FIFIGX+CMR10 /Flags 4 /FontBBox [-251 -250 1009 969] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/A/C/D/N/R/S/T/U/a/b/c/comma/d/e/eight/f/ff/fi/five/g/h/i/k/l/m/n/o/one/p/parenleft/parenright/period/q/r/s/semicolon/t/two/u/v/w/x/y/zero) /FontFile 654 0 R >> endobj 656 0 obj << /Length1 2145 /Length2 14522 /Length3 0 /Length 15665 /Filter /FlateDecode >> stream xÚ­¶UX\ݲ¶îÖ¸KãÜÝ-¸»»»»· Á=wÁÝ îþ~÷Ú{‘µ¾Óÿ꓾k”<£ªfϦ QTa2±72··sa2y"rÊ@‘ž‚BÄÉÔÐÅÒÞNÔÐŔ俄\Í,Ì +3;<@ÄÞÁÓÉÒÜÂ@-Bó'@ÈÖÔÉÒØÐ gèbaj ÊalhP±7¶4uñdÙØ”ÿ‰p(›:›:¹™š0ÂKc€‘©¹¥<Ó?‚¤ìÌìœÿ2›¸:üß‘›©“3H€$’’hbogã 015ƒg’·Õ2)ùÿCÔ'wµ±‘7´ý'ý?MúŽ m-m<ÿ×ÁÞÖÁÕÅÔ gobêd÷ß®¦ÿÒ&gjbéjûß§R.†6–ÆBvæ6¦æ™,Å-=LM-]Œ-f†6Φÿc7µ3ùo ¾ý&!eU1IiºÍóÎ -í\T=þõçÿaà;ƒºãdéÐafdf‚AŸÿû¦û_µÄìŒíM,í@ ÁÎ0tr2ô„mˆØÞ@€¥‰©ÀÔ$˜‰ÑÎÞõÄ`fïÿÏ89ØA"ÿ1ý‹8LÂïÄ `y'.“è;q˜ÄþMœÌ&ñw˜$Þ‰À$ùN¬&©wb0I¿H‹Ì;´È¾H‹Ü;´È¿H‹Â¿‰ ¤Eñ@Z”Þ ¤Eù@ZTÞ ¤Eõ@ZÔÞ ¤Eý@Z4Þ ¤Eó@Z´þMÜ -ÚïŠ3ü7±´:ƒÖÓÒÙúÝ”Ìè@✠­M]lLÍ\Þí¬ÿ¶ÿëùú÷¨ºñ¿‰”ÌØÞô”þ»&Û?[Ûw@fD“wdi4±4u2u¶tþË $Äô=/¨¦ÿQÈRz -Þ7äŸGWÐãýÖœ<Œm mÿÊ ê‚Ù;‚bÌþB¶Ðò¯2 ~GvÖÐí]ðÃ{=öÜí]þªr0ÿ Aùß³Fnáé`aj÷—ÈöW}fÐÍ­þBP³¬ÿBP¿mþBÐ0þº)Ôè÷Ìì P;K»¿´ÿswûw1 `ûÿ8]Æáý”ÌÁÐÉÔî?ö‚ ø¿ÖÿÜ 6jОٿϙ Ô׿FüOï߇÷¹š:ÿóâyß.–Œö.¦&F6ÿQ—•íýà¿’ãOþÓŸû­ÿé ügÞM jþ»BvP³©­ån4û?>¦nÍŒ”Äôãùï«‚:íló÷f UïeÙA]s±p2ýkÁAÝuq·ÿ+”Ãõ/ Úí/)sÿkIAÑ!(½ç_j¢×»8P&/S§•ú_"ÂÂöÞ  ö2°€Trƒ~j8Ù™}ÿÃÏØÕ 4p—ÿy?ƒžÀÿc3KÐ{ËÔÔÃÔ~iÞÞ˜7Ä*½9¬ÜO¬h²š\ؼ%A¾¡{¦!x1ܦdTÆ‘v½^ó±2ýãô±û3¾sÔ¥qñó@Ç„Œ¹×=7ƒ½L¯6|Í«L9Ï]Ò»àcäöæÙ›vp…éõŸå)ZÅ9ƒÇŠÔ¢ªû0«$`=:n=Y!œšâ™6já¡õ”¬$Ê(Žålákî()IPkÁ~Vá°­t+—ö?\Ñ‹`ó“_?ßN ê`eÏqèÚýš[°˜·µ±0ŒŽ‘¤c#Ž)ŠËjûþüX•Í$0ÉÚL™a7ËŸlÈ!ÖJ–47º…çÓ˜ãÇ´:ú3_Ö…±~¯4ÇyW^«P¸ÜžuÇH¥¾f×$ò]3¼r‰µÉç (ÊšZiAJÁÎö–wÕ¬ý>­)|#Mè«oˆ¸Ÿ!…fO¶¶É|Wï¾öús4jvuǫ̈þ-Åñgz³Ó¤ãÆ18Ú ˜˜-#‰Ví–årÅiÈÔR.YÖ7§£"j¯õùh×ÎéËlXˆ@ÔžÖjàwòÃ2Eì¨Ì¬/òÔWáÓÊ(.%íŸbbóš‰.æ‘GT"ÙñŒ(gã»Þ½MæZ)ñHt¬ž—Šm8Œ¹îŠøeü×n¡’aS7.V2þn±_+".!2פ“àÖ£¨5̺íÊ´Œ³’ÆÆGo³èZç"F]åÐ4ºî¬U2än’’+Î=ÁrX 3e±ž }ÍÑ%é%„‘ÁªìÌ!PÔ›!ÕØöó §ä¯äc£[6C ý\ô2ÕЇ“µdTqŸí·»ëyz`9ܶ“(,(¸¨hÚhIÈyû~×ö†­G$²ý•­Èõì?‹~TГO¿…Ëáⵌ—¼˜í*?U z¸²ë¸Õĉ¤wá9GÔ$¹$FÛÝ5T œ$þ& ‘¬=¤Þý’ðÀaåi”F°Â• Þ™š]©žì1Âá;ˆ»GH#"1Ö}Á4Ò0ë¨ç‰Ã›Ð.Õ&nH†ÒUJ_u¨C%«.©“!Ã`TƒŸEk©çã…å šÃé»±¹!®–ºDÄì‚$ÎU~ù^ìs¿ÏK繈Êï BˆÐXÜÑVé[Ú’ Ôz$s寏DŸL’'ž@Ñð<Ï”™Ï¯p8Ç­näÚó…ø`‡+aýnÕαú@o´Ï$ûÝE¡Qr5ÿCæQ.ñT£'ºÕR‚¢ÊäùžjíiÈŽ™7:•IæJÒfù³–ŠZ~;“;ý¡á(¡"r9Ù}ÏþnPCþoëAHÇÀΤ5QÍ5š3Æàïm|ÔÛgÊ.ß«–öêÊÄ“ñ‡¥ }â3ë·À“‘¦¼Ð3È`Ûº£ØYa9©Q¿z‡BGXb\òÃñáVÔA vÝu2Ib}4\'$Ò’(n:Þ»Ñ~æ­UtÙHµÓãsîÁ†ø1§ØYýM™ð¨' Ej1‹°¸Á^û°D—®žpO8•ä’ öbùÛS…rÅ8’Ò-B ÷ •vë4 {(X\ I×J““âÆ’7zÓ% ·¤¼ÇBùw×Z7†`r#q‚¨ô†Ox–îš¾üýCóõTLòZÅç:hôqv˜²bwѲveÆÙ´£%ü” æÀ[Q¬%àiŸrÐ>” îÙúNÐò#  [qèc"Ã~ÈçVW¥ò![éäÁŒ×a5rZœ.‘‡(m#ÜgBÕÍÃóïÃ^š¼N(Ô3&ÞpN£ö2Ý‚9<~UcTÔ¼(ô[ŽÀGbj"ÄÏáÊyËÄ õ.ÁiNâ Âò¶•ù;2/U´ÁÊÌKZ^6òi v~•ÑwuËÌëÇT BSAÕúäíƒ4Ôó"ÕÕféCŠN1K>Iæ©-#=¨{&%­H[t8­Z®Ñ„!O jéäâRff(® ªìÜ^Ö%Ž/4Cñ)t÷Lš9ä{nkŠK´…Öæã”gÉ‹v¬|=3HTØf¼8d\)Àкt ²™ ,ãÇÖ`Wø©q‹5ư±‘ãäæÑ.äN…s`²³¾­pbÿdN ëjx{^þÞJ)ïKÝJá *P^ô2AŽ’ Á¬”öD‹úÈ`OÛ€yb×}Œß¥ N œ}Ƽ›öýÎ2Gå¼­”ZÇ|:«8=и®×ýœv…ž™i¦¬º§,“c«Ô.eél Þ/scû'Êõ‘">djb¾’Q5¦ Î F±ôéÌÅýã–k'Ó{0tÃ$Ížë)¨Ñ:9ìÊgþÁaO1c¯M’öÝÊOu*•m­Ó‰úJ;+™‚öˆ,ît_:€,:¸3[êYᬻU6Y|‡«u÷ª—ªÍ\4èÛû­Õë3õÖ¦Ùô)yØJ—¦s:,Ùëv‚yÿ‘\Ò–ýJ4GáF޲(µ?˜N¼’/d¦1£“t'ø@+µD÷èëéÎ4r«Ê¦e¿DI— ¾œ‰ÝÑ[ˆX›¾zÿŒ §i¼¤Ü5¸ÌÞº‰g¢¸Q‘XUÃ!4דݭ%%™4Qׯýqé7Ä8 x]ýM£¥FfÑDÒß2[8åÛ:!ðôÌåŸFï¢kO’ ÜŽ™¦ê,ÉGx€ª…õ£= ‡KÙþ¬ƒp0‰ÚZ{©çÐ}QØÔ‡ìoxýä$¦}”êLb·ÐÎY¹—ýÆ“¨·R‰‘÷½!Os^—o;ÂF̯>4¤Ýê „7‡xŽ[¿UDXª:N”€?xÆæ© ifÔ›D%Œ¸êe’š„™×+ÔR@FƒÅ|»ø^ ’%Je{ðÒùVmX8Ξš¤tïF*×zfbñ*~ëÉ5yAÇ–\7ڱ߾é/y%MºswèÓ­´ã¤ž~%~èY¨˜WÔÒ ×­„–m]èZ…†yÕUÿ©mnç1ô¸ äWtèf‹óÍ‚B ²,h”a¡çX ‘›»\¢»­K¶Â?øú…ÛŒÜm“÷®‘Ë0Ñ??Ií¦Vªf¯ë<Ý?Û#·0¨Š¶E@wm'ØÄ{1Ð×¶tIÝAûœ¤´w^¶À_IBؼ°ð®¢%oh,ç°‰o¡#²q}`@L+-(_¸­Š˜|3Kþ%oX"jƒÜ"³PEøHa/š›ÓuÝœ(Ÿ84³ _Ó;ñ Q§î@ðl¿>ÉUá Ôc!Ë~Ž 6&dž‡‡‰p-E8øR@#Ç$a’Ö‘—¬ÿÈ·ˆš0Ä“Ã`ßj3µ>ndÜ2K\ÐnZãÚü‰›ÍõK„Kõ&^¹¤ú6Á´Í÷k´sÙ“ë̱µ@Gɺ€æ¥cðrØ[;]˰C-y$\õi /jê.»ÈÆü _š†:Ç[/³· ¯‡Xã.Aë|°FTËŸQÍ$ó—»üÝä2‹ 1 ÕV¹ÓQHäkP^¸¿¦›CI&·P^ÇEy¸9VM‰££xm§¹ªØh‚ϵô&E‰óôÅeh‘”˜Î³ŒôØšÚ•³­UùŒ†ß²Á´9„!?S”ö›«ú›ù®«ðîN ²C¶]ãÛ<Ñëçõ¯Æý¤ë¤$´Ü†E'T™‚kûV,3ÿ‡×¿3J»_¦^±06è!cƒ§åšO–ûâ `Œ5i¾9»"²=SHÛÔnÓjåj†¸‚˜ xÁ©êEØ,Ž_ìÛ[º&!ªÏºÁXS‹f“Â?î·xF‘ó(t«™â&9© ÝlØ\ï;ØuGófKTä îð…^“”­ ô`]¼¡.÷þÚ¹£`Sö‡“ –¢†Dy±£œ[^>kÁÈñôI P&Ì;ÝÞ´°49"_ÂB…òQý*³‚üuËy<ëÏÒÍâ$UÿíÀsC¹ÌA'(oÅ×'ïžGN™¤q!ëS¨$žæÇ(Y'µÖä Z¹íye]7ŠÇÓ sÔ…êTbØ6ˆß-×Ï?i¦]IÝnR?@pïð›Ë)®XéIE¦7½Î¤4VWÖŸp¹hèÖHP‡8¿-ûXEçÆÂñŸpGPeÂìo}Có!“iå0ä¿VÿÂ\WÈ„/bÛUá?ûâÒ ™»×þòPÒꔤUvš~_ëÎÑ«¼ÃÃÆž[L‡€bõ‡l´f5-Sù˜ø)ç<¸DO¬Ùè[í 9;Œ¾šE <¶#{ΞðÛQØóåÇ^YG+öJúªòôñ—åq=.z±=ŒÕÀ?,_—EÎÑdÆàœ:{~ÑËF”îÀ=è7¥ÉÓ/+Œ…d‡h_„Y~ÆØ@o«ÙC¹ ŒÍ(´]ž¾)7„ElLœØíú)(Ëtþj52%),›‰£†ãg£˜úÈ—ÙÁùQß áÔªÔUWœÒ$€‘|-siÔoºøË˜¿«a犴 öŒ*dGè)é¶' Õ”•×q»hCe<›‹XçÊÙ‘BJ¡ýžLÝâ ÂŃ( ?ò˜ ¿Í“Ñ(ÆPí¡öQ§lßÁ0V#ïý§9FV¶T ¿r³ø†\0)Bã­‚ÅÄ¥E›šlWAlù?Lóé´^–¥D©,X¶¥ œmWÕp(üà _qÃsÊè*¶S°ßä_x}Ó4—îÇyµ?ovQž¹^áwÄì$ÕÉ/å‡ZŒ†Ú.ïp±ý<öŽËÔ”RųMëœy…[õ‡²Ïl½C篽S–ÐÙ+-M5!iÀ]­éü™{®¶‹ap#¨ÙZ»õúÚƒuUgoÌú¢¿—Ihøƒ^þ‘‘Œ«Øšx8à\UüÑŠàz“uY^ù³'|‰+÷)¸«úEQÅÄ–×2ìÞtH{Á agmoä[þÐfõ3~îTðïA³N“ßýíu낱u¾Üy7ª¡m¢’µÜ _¾Wû·j&¼I¾Âè`}À¼t*0ø:p¹·ç-h§O,›‘“øk,[C¾ú™¼|B:€N¨`°¦+¹…:Ÿ_­ÂŸhzÑQ"Y­íÓ0!ýwƒà7­hÀà‡7U•`mí‚õÂðFcSe™Öq—Ùu[áÅÇû\ÿ•pÖ%¼”6Žît½Bi-öá`''_-¨g0-qÏ€ÿa‹¼eLÝÁ:ºrÊÎ2¢Qô*ǀŤž’E4È‚YzÏhM`bU¾bui`òaôEòs¶×’ÆåT±¬ƒªÉWNô£H·ŠQ½þFš¶»?ƒ9¡ N¤„—û™’¯å¼à ñ—âH¢½LÇ©ë”˶J£áh}+§¤ØI{ôêÝÿ®gßpFs¦£ê>ü3)hûL{¡‘i§ûaó?°öy¼fWháþ çe„œ7€l=Ž'–ŠZÈS •«€'/÷ÜØJzj²u2ÒbT©X7m³í²Vv‡£?Gäo:K†UCÔ\9öI±ú`“+eôïþkäªGì]%SnךzyíˆËdÈ0B·”‰QÆqÀ!Ïp„)ÏçkB½£)Gfò1«©ö‰ÞttñʺŠí½ž‡hÁ5 }Øtܳßz盜Äõ£Eñê›ÙݬM+¤æ]ë®-A¯´Xßh¨…ÏŸ!.©3zî¤ÔÂuéÃñé'ÖY/(LÚÁò€¥'XG©¥« #[<JÂ‡æŸæ¡×ÂL~ìŸå Ö¬ E[×|%J^˜ŠC“ÄR(ܬª”XL/…ž–¶éjžH³&úZe€HÚ!¼Ç\ç§³0¤UŸ«tà•Ì•$ÿЄx=Ým‘fÉ&ã'ñ›[w9&vÉèmIƨp„߃Ã`Êõ›†¹pÜy¹+Mäx QŠÜW®ÍÅæ çtñƒ¥å¬¨J–Üá%õðFr‹|² B$ËfTuÅÌó$Ad¤#¸rŽÀ¦º§ ùÉkšW¾¸ÈÆ×µîíQ].³‘¼2 ÏphLÀ•áúÉß|Oe­%…·Øk—àŠÔw97¢-•ÀÛÅg‰ ¥YÎÛ©–+ŽcߘQ‡ô{fÇvT×5ìRÚÙÆ¶5¶8àNå¨1/h¼Q04®5\©–ÓI]Š[Bň¶ õm­Ì¯ ì¾|o3iü•F„ˆ/9„ v1| ²Ò'üœEw_“;-«­TšAšÿë&½ ý¨G¨R±ZfKG¬ôÜJî}dòyXÃÕǶ`»FÊËêåBÃÃn]ì(û\¬‘M•:ÆÉõÊù¾Ë?DdS*Ii¢škã¥;æîïLµ‡q³Fœ†x˜G¹q?v.òd^•$Lºlm÷MÒ ~GyQØhÜ#­Á—}WÜ 2¹¾·Â>³òëgBV ›MÖbO‰¹öoÆ[ûΊÜkÎ9rÇ«$^woÜ5>Í%1 JÌô3.ùØÃþqoBHl»D÷÷±Ô`rQ¨nÏ€Tç!×˧–õ‰ù„C…A©‡Txxu É"Áö<¯)S“ジÇ<]µŸâ‹ó(Ǹ1±î6}+àüCÐjy{(ËãÆ`!X£—1&7Ú5-~Îá§ÛUøƒ]ÍBžîÜ©/ž±q03PçÍï݆%–È}Q:»£ Ì‰Mû ¼#p ¦u€éNnù}“S½‡JøëÇ×êiÎhÜÚ%m>ŠdJÞíGÓÑ_Ü™UVtíª LÕ|LÁh¼÷³ËX¡éQr¾çà0Z-ÎÊ Óñ¤D&ì¨G×xPòm/(´—ã2ª|Ôh…7ŸÖÀþžÙ°³µl’\^ÚÒC†wÓb¯7BdI@ûzì^a+˜"øy795D'Qϧ¹>*‹Iáaâ0(e¡ºNŠENŸ^Ø@Vú©Aç¡éMBOÁ‡Ö¶¯§Ü+“æÃ¨–œ¾-9;u®½~R §F‰ AðÝ5Öøî{K)2-ü5«ËJÕ5-§Q´>Îø?¢5™Î…U«ªmö‡ ¯’«4…To”%»òUƒá†àšÌfSŠ}‘¡‰)WÌø“4¤_Er+­yô ^½¨J44Fc[X)|èrJï1B;·éå¶„ûÍCVIJÕ²œ¨<M¸Æ d¡(åù)ȨÂr¨”ǦëfiSw*K N—KBR’ç‘úd£ŽèÚNBñ·&Mó(%5…o¨ øš>OH·ˆOÆ Øp×s´5´K²>xè½}HDig×p‡Kˆ›Öù<C¢_x'í˰ÁRÐï að2+[{ýA³NZ„í¢Øµˆ¸ý‘cõD®±¶´r8~À·ÐQïÐÌŠFZœQµ Š”‹Si≭åÓ¾•I,fXäÒLr€-]Þ÷Âß—ýýñÜMÍÑ;tÈ`ŠCÉÓ(í°—Å½Jp:Œ,òçü"ˆ‰ëö¿ÇÖ†è7y¦Ôâ^ð>Žžò|6ˆÐ‚?´0N¿9™]SAŸˆù–’ó›¶=‹‘/•ܽw‚ÆŒƒ†¨m7– î{e×0=Ìì×ÅÛQì$½aˆÎãÓ´ æ0ŸøšŠKC'²é¶0ùøyÅ ÇH#Úöèdp¿ ]k÷[ÿ(L]ßÀØ_añ9îhN9ž¿¦3 osÕBG$Žiw aq3¦qDâ7ØÜO]ÅÂùž`Ñ”±„_i_få“í%ɹ/ñm*£–„ðö¢ÇÒ˜p¿¥ k©…¼yb;á y¶Òë?E/Ôµ7ä¹ãöÎ?Á Ô8^ùMN]?j»À–¬!g Sâ œ¬ƒ8c 4›íh Ÿ%ÀÊ0\‹Ãüy– ÁûK=ôOÒhþ–µŒ˜Sž”É)ÚW8-ò7—ŒÑ‚Í8 æ+Ý0Pz˜#erÑ &iŽ\òüQì¨lÿ–xÏÕÎt0®eA/¥vÀRþ~Þþ`qÔÊ#ÄëÁq­tˆ ­iiáÔðÂÂÞÍxI^aâ}£‰Ã…‘Çyåk¥.O<®T%üÁBá R/SdíïùéÕcø4œæŽG_gù¡ôz’ÁìzC×QÕ{„ɛ˲‰B˯iúGi&`m,‹2ÚªüžoAr÷_9Üg¬ÙqT¾È{ø×tÔK´×àEK}ƒîføº”!tmŒðb ¤7›ónÐñÞÐj¦©&À3ÍNÊÏê^€F‹®*ª~1.«œùòñ:+¡…Š“êõF­éÅJBüÃG†¬m%HU.|á‰Ò…ŒVóX;${’ø_gdl{>îsúàåíM¯Tƒ3Y­£YwXšÂ÷¦{74¼N–¤dY*›×5ž™‰=/õª¿* È.ö•hw¼(‰Ù†{Q«üêøÐcµU£¦áé¶§a°éì¯àìZ¦iÆÛFMÊKkŠÎhÀ&.¥þˆDâÈ»<(]~˜XÜ©mT=9ëèVgŠQ Ölªå‡šáKÌ©z`¿gñ }ò:Å \傯¦í»æÙ;'7Òi{%5j3’´v»¾/döÚF-ê‹bÆ_v%Õ‹7{ã'¤$c:MŽºÓ<Än9ÿ%ºä’l.`è&´è÷L§áÄg1œ»VÊE/zïõ]‚Ţ󞥩>¤iI#˜?§3ÆGêm‰V%‹ ÅCYJ§rx³XC:µMèl›kÎ*òçjk{Û¬Þ~8]„‹x6w«Âf‘ ¢6]¸irVØk¹¤êC³§öävîn3€]ƒÑ.çQ»=w†p»2‚Ì· "…}{bAd¢7CÕµ—¤šÉ~BSÚ“+¥j`4ÕnÚbDêÛGr¿Í½Ï¨ªÂE¸èt(UvH¼!íš+ª2²v5²H|ù_¼š1UĵI…rÑò¾¾¥Å<q]ÀésŠˆÉq3}y¡{éÆðº»×ºMVSt;Z{ª‡¾ B×Sìùа€Éb^ÌÀZÏ$D¦™ŠÆŒ«+ÌHõ z"òÞuÆo??tÜ÷‡’ßÏy ¶§] T‰”»e« P|ºòºs×™šY=f[ؘX~©«¶‘Ð*ûÍ0Ùóò¦¿d9qׇeW+¡,D”•çUA½ØíëIŽtȶÛfížzC/'ˆsxÕâ¯6Á.q¤¸/°CÙßaä´Ú*ðmÛE¢…ú²_aßʇêó¶e <µŸ 1¾y×€í=&s%˜ßGa¥å­qï_ƒ¾d¾*¹¿L¿âxIé‚ !n¨´g=‹¢~”GÈ-¯»ÝtÒ1§NŸrQôEJ•³ç•âÆIFwE²_eÑœ¬Cm':²óç„H> ØN³,ðÀàŽXÉõˆò %ë˾éÇ ŠTc³pbbn1K°¢M|Ì^ð&dë Þ¬þÍí•%ðaâ¼L¥F%íÏfvR£)½±®ñ-T¶-^¢8»~§Õ /YŒÙZž!ê*1$͸i?6?ìgB£ø h©“-ÜùIí–eŸS£Nà-ßq6i9òõ ºûªHƒ¬ÆT[ FC3ß“–d³×3;æÜ‰Ñ┆:Rc…ß”[Á>BP…|Câ0nï2,ò¾*Y· CÚWE\&»þSwÿæ"Ò&Xu\‹ U¶³Õ}!¡o1œÍ«ÿ…ÄÊC­$ýQ0â€Å¡½³š2ß®‹Û•Ê;t;—&zÀ^ùdµò'£Ô›'Ϊ‡Üç¬ò‹fŠˆâŠ–c[ßí\üý5ˆþ´`)l¹€M5šœöSÛã$îJ££)¯îe~JØ€ü üo(e©ÂžžöKÎ ô¼í H$|Í ÕDt¹Þª;J<ó%9åÙmÂÍvx×8šÐsŸp’áA–ÙŽ§l‹økÖß8mùl‘œÁ†u¤ÒX“ºì¥3yw]~Ø»´×¿Ì•.³)púïÑ2ïNÀß N¼åÏ‹ùš˜¯‰DÊX5ÚÑÕÌë‘Yc-ëq†dUu™Î )«8ñÁ³ÊEý­Ñ¿-ì©t^å}©È¿7—?ÉŠ­>²`åÚl§DrØ„®sw@bøeðz6í¬d­eé“ʸ "ªLíqÆõRaÁÑhÓÙr«ŽR]ý3C²&@s:_Iäàg¶[#$'›°ÃÀ’Â…®9Þùý•QL%5v¿¹÷"œ/÷0!0í—Y§œáટêr€è¤uáix%8^0C.ánÁ$IgŠõå†}«]’òÏŸºzÊ´3EµÖRÁQ@bŠáz¶ëéFÊ \ ,uËHm)—eT³ ÍOm¢2£û«Ò<®Ä™rÂö#Áõ]òÍI¨ráwa`#.†ðs¨j—BÐá–Äs À+eìïÁ"¸} 9ù"êŸò¬åãåëxI1%ˆRȼF‚E·xceø*6¥ÔÛ ¸°*^ª‰ÃéÞ¼x}ÕÛÉSpáåöÌ.‘Uê[(›­¨}*£a#Ñ['Òd{¼ÆP~/Œ…ºÒlv«×á0c/GbÅW9/öÃîHîtxôöì±=?ÞM>üi¢µ-ù<…_´'œFò(&×Û!Š“wÝm %3Ú‘æ-Þžk&{ÕÿIMl´²K¥ÍÔÇêçozCk¨RIº,Óä‰^\_C©žRMH¥ NŠ’*:I~l—î:ôÀüŒ?³Aœ<†b‘3§û’AD:—æûóÙ³W­—oÈ|ÝcìãÅ·y¼RECHLÛ„¯ë>½ŸZæ\Û*`ž°Zl|Å”ª{ÀòYÏÁ¹Ž\ÞþØsºTM„Pj“opg²›1&…ÿj5ÙIJâ¡Þ3oÕkÉSŸPÝÞrß/£òKÝìê«Dóßo÷V‰šC—ö„¦aÓd©6»š>Ö úÜ£w¼1Ò2+ó†˜Ü p%K.´å®‘´”ÐLp01èõíUÝ‚%9‹g6ðõ.s“‡Ð=#ºX]ªУ¶|¯4‚ªÎïgǶU¥áèf½ ë óÛ~j(þáÂC»„Zo¸úæà—sŒÛ”µ|²¹Ôa¨Lœëý¬“B\¢/‡Ü“·ÅËL r’EÙÓvÕO°6Ϩê¬ö€…wÞ)¨âxíÝnCë²:Üߨª“–­];Á–þyµ~(Ql½ßØþe2lªÿL/Y˜•Ãã¸n9,1ñs¼r.4_TQó²\¯ÿF@”–ÍYŒíƒ„ŒMŒ âsÉGeÿ¥4³/!tõf&âìNòG¹Çü‰;P>_?b“D=d¨2a4].ýÆëè:‡–žî5€Å²EÚ6ñ’z5‘ܺRk -6o×;Ajžæ`õWouí£çšƒ¿;8ð$5~¥µêð<×¹Ñ^½…@C:Z”UQÚ-°¾³¤Øi rúùç¼éª°(ÍwÂ6ˆ–¡>î¨Ä^õ æH¾0«ÊѨð`ËejòxcÉláëÝÄÂÎЋc/1·&kåîªV§Ž´íqã- 7먵ÐIœ÷U NòÈ¢](jñ"™~½ DˆGXœ_WE7at"ûþœ’–T†ÆýTè“‘ßE±4éT /°0ä·WgÖ}Ç¢œ¤H`,C‹–¥dÁáb¸Ÿ¾>‰zem>Cò_B{„ùSÕvrgÐí<ôePxjŽ„Ù:ÖTá3¥pjBŸ„-@‰Ûµ>iÑ”4æn6$VôŻْìw7žx‰·K!ØâòW®IÌÉÏÎ݃õ¸yîˆé€ Ï %Ï+Û#ÉQ‰}|4;Vk&´e$Ï¡G5«ºqìÀD§ Âß+LýÀµ4ª'Ùþ™2?lÁÛƒþŠÒV=ë‰fŸþY;£r¦Nrmü­…krÊ}Æâ3™m‚Qò·Øc†vm//‡OŸlê-ovX<×33Ùz‹ˆB ÎÁ:R.\5ê£ýÝ¿ð… øõ‰ðcKÃYNË>ç‚§`VŒ·ZôÂå¾ ”šUþ8Â>C€„vZXìÎGìŠ_X„‰A×™“<7•Š—7柔K $™½VsNÖ¥ƒÏ]³*Éu°¼OÕW½<ºÿ£`Z‚ÁÿB¹$tàã-Ã$Ή06xÑÜ na /¼àGî§ßS´Å©wØÓoâG¯×ôgŸV^´SuR3@F Åi$£ü<38#:jÂB9PyFè YŒ@Å$±ú³91=˜&]zZÉœèá*zš7ÑŠÇd¦a¢ÔÉÂK¯¼Ä‰c¸b8Ö&CƒÉ À1àˆ¼¬¹{Ì&ªŠ×ܧ³6þt¶ØqXa‚}ߎ¹FiÁà9Ù -„×¹‰96^h)ruþ Ó{Ú®˜ë­!xíMŠÜ${lÇ“’A›ÿ«õ5;½‚? m覟è¼ ñwšä¨“êËcÿƳ²úMLèÓw¿ÚÖ½pÚ^ŽÆ `Ô¶øbÖP²ÞÞî–eålT³ØÓÓ^P;Š?ë3bVuì0|+,¸ ·o\Ù±«!&k 6:éÇv{¾‘èÌÐÎnø¼4)^Bbb+ªÐ˜ÇÔSäö…–nŸ§`uF·ìÆžìÆ¯×@Z.†?o2¿\†ð•C9Z[öìÀ½Ã |¾6“ØJ;Cf %ü¿œI±}¤7i®}ȧ[mΕ§œÌ0gkËÊÇ7–'HrŒ&ѧƉ5°3»`j¯•;ñHÄÁ%ßkQÐa‰Y;€é1uU;æf ‰ pMj^`¶‰Nù!hUþ¸Ø†¬Ä”ˆrÆÑ΢}©ôªîÉÓ½æÏ5q¦P Éâ]™ÔÊIü9h®ìá…‰ ›¿1úX~Ä*ÿ«¦p£©ÍìbV§²ð ¦üÅOgÉŽ;£èwÉpçm éð†íA—;_<4 –0íØVbÞø#rñŽùU×m¾LóÖhYM‰R“ÓByüžÑŠ,…Uâs#Ÿ!:ÙÃJL}<÷j®¬Þ0…Ö,€bÔžäR¿½Ì,’'’…ÛÕ¶ej«Ï¸("3½íë┎]m^ô²å)ËOËeëjÇë9 ¯¶O«¡”Ÿ©T “›’˱6æºüüsS„wœÍ3¯/7(dW<“æÝ`è±ègjÆïËøÕh§#“ÙàÊ3WR`a™ÂšfK|º0{C–Ý5oÁ[XUGÀýàîhi¦¨Žvû2ÍÄËÔY-ŸßØ`Kj¨„Ìytº£6É•è=P}ôµòùPÛjTÂ…[C†”21Œô‰ÚeØèºUÐ32»;:ÏT‰´Q“lùkŽ#$OǬÎ-©,ªÂ´ô{ù$ÕTôIÆ ½à'ºZ59U¯¡FÑg€9 øc&K®Š+/Mé‡çKmù:¤ ¢ëhœ|e<ÅR˜@ksÊ*CLWkócÇÖ€ClŠ#“vðï‘âÖ„¢Ý |`†ë|î•~Ní©&–ro›¸Éßöd¼}×j`nùÚ­^n (VÓ} ’)ž wS˜Q¦SÉqÉ…‹†£{MúªI937+õBIL{â&õ0Î-‰ÞŠ%Õº^fíy¹ø”IK8‚‰cW2¡+ÌKyZk7VY€VÒYáT|Ð¥4üi‰WïÁoàØ5,\Z<–˜æ|?¢á ûyÖ¬†G÷Û[3»Î!™ó^@¡|E„Í ]q«ŒÄ¯'k`lßS‰‚yBSé(œÚãŸrk\ÁšŸ’·S±·x¦²gxd“Fç‹–M7);°U?TgùšÛ»d“Âû …v›½j©‰_IóüXlçt,‚Á©)à-Üsk™ZøRom•#íL€–oyú\®lÆÕ,cá‹5Ñ_ß!%*ÔÎÊ`6†5çÞÂn°SêE²Ö°:rC]•}cl/ÙÇ,îÇ“ unªOý¼è¦óPÑ»jÝ”©¨8œ$±[öDSé:‡ø¼mhN@Sk Üøzå)…Nõ; ·•ÂåùÛóÕÝ÷¬Ø®0S™Fô{E»}˜ `OôHhÆnÓõ¡<ÊM&; aM‹Ñ?¥ôn5Ii#ŠJ^MŽM:0×äz‡f"î¶Œ?½`×jõfüŸê…Ôµ¬óØ¥b·éw_V\ÇÊi?cm»É‘ÓÀ× %ÃÀd\mZ1‘J^Ù±R]«}ŠÉ>ý¹É7Nb!uâÌ”$+‰uÌ0¦T‹øÓÏ9;%W)KTÒOUƒ„À½á›¡ jˆå¡¾Ó½ÆÑË µÅ~8`WÚèh CÕæ$V5 ÚögS¨a£…×IšóÀ†ôF~!8L” 9[piÉ\QÿCÏh©…jMªøývƒìX_9Ôê-ã-_Nî‚KæFU~¤Ÿ­›ð·{øÒ’‚†è ³&åãTÔ£ÈU‰Ûéú6#ÌÀ·õí¹*9(Â>(mge÷áb`Î+äÝóÂ’Ž bnöÔ|¤åyßšL­DÓ&a”}Í¢ªmÐÜ[¸~lôD‡@G¨ç›74»ÓæŸ:íõ@?†ï¨×(†»ÿ|Ô)juÓ^øÞ›ÿp/ăišã;ޫЛMâŽO+·QþìpYßz±®Ÿ_£Ë&@Ri@¬¶ØûËK±cZÚvLk÷#ÚùPú8ÍB¹aê‘™Ëë!Þ«Qð4¿Û’-Rõ oëÚª•z2ìè0°Œ vÙ9ýí{HÇ/Ž¢¡âÚãÑù¹HÑ·Åïiì>¤VHÔ"+›@—>|:±LÀ¦ žFXçò5¸’Ž.ªãÇpÊ¥s áôÇ™¹÷«[­PÕõ2ú[é-ükþàŽF´iÖÉð‡ î.Sò_ðIH´xNYDM§û¾O  -r*ipÈ·,WèÚ aîK ª!!,-5GøàI¢ôV±æûUɤ/B“3&‰)¾3E=A%|Òðj£rÝâË_1ɤâm@Åkêev^.„ŽO^cs0Àò+ò¶ý¸ysêß´i:¸£Å¶)ù.Öt_;œÐÊ*c:÷ËãKŠ(çÂeZs5Z÷¸óÒ4²P“Óí¯Þ:ä|¬áoé½?W è&çö$—Éó-Ä”ÈÜ/\%{´ð`U&)‹µ ‰ o™k•–*[ì2Wƒ"W`?Ú¥lÝÀrc–ótćÒi‚e.]³M mBçHR˜`Þïåê/^„ã¨ëصٛt„ž6Özêûw­ Áº£ ¯Ö*X%ÜáÅŒ ÜÞ%@ûxðQO†9ˆ`‡Hr¿¿•S a”½Jt(Îö6dÉÉ|§Âȸ™%ÉiÀ¨/û½#–©[îQ—Dl;ýí SlÃñ“Õq]¹béçÊøÜtHŠ•¢–JO{Å “.ÎÒ&ú « NQAíÙ nEªkei™ÜRM² ½…)ü³[ßöjÍ‹îðò(b¶M¯P òó«îÈ’÷3ÜŠ#tŸ_üËý˜¾ßjr꫊ü&Ø€_Á»\5LnK´ÊÑwW™÷S3±°"ƒOaàh‰–tÈ&Þ4JÐäùU›¿FF¶àË9®ð|³ÓÐaó@Ïk‚絩DZ«E'^+yúÙ¡¤«naSÆñêºN¾OíEã³p¡íñ-ÍÕÅJKãY.õAÁ¹vïècNCù* ¡vV=Ų‘!'†‰fˤUÉ1%4ö(%úɨ1Š´í~"Ã~ôb¼ˆú‹ÁÀ™…`œ€6mÍæïíá:¥-2!C¢o"ñ•Z$³U¡+ÑQþ„LÀ¨ ?a³(jâ× ºáoSH‹å)f.é´ã?\„ãfª·ˆ\áú[Ïþ?ö6Ä endstream endobj 657 0 obj << /Type /FontDescriptor /FontName /ARTEHJ+CMR12 /Flags 4 /FontBBox [-34 -251 988 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 65 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/a/asterisk/b/bracketleft/bracketright/c/colon/comma/d/dieresis/e/eight/endash/equal/exclam/f/ff/ffi/fi/five/fl/four/g/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/period/plus/q/question/quotedblleft/quotedblright/quoteleft/quoteright/r/s/semicolon/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 656 0 R >> endobj 658 0 obj << /Length1 1003 /Length2 3301 /Length3 0 /Length 3954 /Filter /FlateDecode >> stream xÚ­“y<Ôû÷Ç-¹1BYBŠÏcËÌØÆR²Çµ&4ˆf0ŒÆØ÷ì‰ìdZlER‘¥„ #Ù%ûVö²ä7Õ÷Þî÷~ÿý=æŸÏë¼Î9ïçãœ3P°éi ,ɧK"R¤‘2H@ËÈ ‰2ªEÆa(xQCÁ©Hee$ áåÈ"¤¢Šœ’Ь< h‘ÜýÈx'g ®%ñ# h¸áÈx 0ÂPœqn´pä€ÇQüd 0ûQá ˜á{xL×lã]Ûœ¡ˆBëf,¢#«EåÀfGÓ=Êbä£G}ަ$}ìÍ\/9¼JjôâÜ)dλùýòa»¼|Oå2S?cN‘€lñVá›4h‘DÍ=?<çžl‚Šø7Òë! 8}òœ—]pÈWú§•ìYYÌ®Ã3Ëo#N¨=hß7Y>í Ù`<±çÂ@LMí·ðÒ  øvºÈlå¬Ç‡³å5ƒc£°©mì÷m¦Gn Ï:°ƒ²-*9‹nwì~«}qI6|ýM©ÁUßüÊœÒùû&  Ë›…AÊJ¶f<çZÊ+ê˜ô½ˆ :þÔ,¹Ûu¦_‡” ¬˜âb³j,s+ýÖv‡‰>Ùò™îŸ¨ˆ~±dˆ~ácɇ{•êRȽe BY.$¥ èVÒðDèòÚož¡ bϹ4–]Ôàã/†‹*ï¡çÇò‰÷Õ¯GF`Ð/²3[ô ñÒ= üø*Úr+äCë6ï 6 ˜øÅV‰—¬ÕÂíÏ!£º„9!3]p<+PÔp«'<çÉÀ5u ‡[ |âöNºð£u?T7#|¥·½¢j‘E°ñX1*‹óÉYu;±ZÙ{ eZ0mî°äQ0Õd <Æy Ãû *ýh—»{ÁÀ Û2NÄ­^.]R©{V4î9åQeshÒǪ¯A²ïIFï =«l0Ų+Û°&!O•c J²Ýλö1Åi>ZÛa`£eM-Û¡t\`ª²Ç¶ø~îtà÷ ¤äú襵*SSgÑS­t±AâÀO7å¼xK9d¡æžyðŽh bêð§‹š"ÞÈ=±«‡B •²ŽGIß¼­‚ÚN0S¦vWe/d×]ü2¢¶ §*ó_;˜›î¯lçV¹EžUݨå!y^~Pa¥Cl®€¯CžuÌ&4 RÙ|.ƒúb¢åœ"sAP-o†ÌÇ|Š‚à¸ ¯?žûº¤œœTI´1Þ_^v43rÙ¶ÈéŽû(éÙý2ZC/tT÷©h¼é6öšRèNZ×qºØ_¬a?ùTÐàÿæÅwF„±þ ˆÙ¿ý†¡à ï=é¼õë¡J·t¤!Té²XW,™Z\KÙ©í=:Ñ™¬ïñ‰:¸ìï/¾§|"Ì“køðûæ H%Ÿí^–K«gn¶ÁüÓœ‰emž”)O¡ÉÁ‹–ø^qNÖ…ÄyO…s[0éÉýçbkú'÷|£”v+©ÙɆŸ¼Ç eMº÷ÖœeÙæ·#°*UJuÝ¿;¬À7¿*4™¬–ýãõmŠË]D¨´ÛŠÊ‹8ê‚s&ƒê ,kß@ªŽ=¦âYÝR˜Êƒ7Þƒ[[«+åœ|µnY¸’ü ºNØ{‘wÚ:“·×{r¤©OÇpw³u;M9øâÿìe©bkŠYHq6uÝP~¤Å&üÕ7éì;«øÞ„{#Â…Ö|%LË2*´°óbÞG[3Âr7ÑZئӽŸëý(µ÷ÓÙ3 :ÒªDj|ZTS3˜xÚêÕóCckßOݬXl&˜ÕåîgÙuRíE5ÂãG‚uÃÙ—„6ø³R/w¬ìçi†QBÅcÏôˆÄ6¸ÒΙ•6ÔõKÁßó®(ÿ¸¸[xʉÂìz<¶òÉña:ψ´¡|°¹M”ÔU×SSvV'{½`ÑhG Ãe‡ëWSÚ‚ ²¾ |º½SՇ̄+WWC¹íòÔ+,vb¯LÄ´È-ót\š:^ï²¢âǰX>ˆ´®a•yøÙ¯ò’(I)bÄMËrðXñq,”¤ÆÁLFkÜ|™¼ŽáYµƒgç‰H»Ð—¹ht*CH§äËÚÂàóC9î»ææó!J\’ÁA>šô/“— Æ;BXãDµ+wGÑ>Dà‚Û^5œ »Ezš~Ê s¸];2j•å9ï²Õ"{y…‚ër#š{ 5µ¹HÇÒŒ*mMSivR÷9WRÆT< kżrè_U®ÑgKÒëä|Úîýn4£œ"|÷uQ 8À0qSRd!ÇFjw¶:êØ¼¡·êÍc ·][Ùhýež‹u}tgÇ1{bÊØ’Ÿi~ÑéZFy7Þ;žYÅRã­:ôBLøóÒ¡žoö'ºS•lΓzÌ`óý~Žö' .zŒÈ·êÅïG¶ÝTá]AZu«ÉA­“ÃÞZT”IY7—¦c³ÇOŠg%f‡ÅÞ_p¶ ÁÕ²¸@/!Ô]ÿLíÏme9§G ýàù§¦> 7t,÷;™Gîú~[-?äÉ<÷Ú#óÎàC±Á/i»]‹™Õ†lž}P²I¾ýöjß.Ÿ‰ð_ߨÉ0º\$0þYxløU’qÅ¢ÖvXžëÐR•éCìGú—igó‰å cøÕ]nSNˆ¡µ¶˜a¼iv4+žíˆåÈl='UöñË1Øq¼g’mî…ÝÖPOÂ8—îÌU{(ùøP1ß”~½Ä,×"ÙÎ7$?‹ß”¤íUŸj¬¸bk•~¨µ*áŽb“e™¹£6\ŽÔÙßÁÍ¿4ªõˆônœe^øcú›bsœTÁ]¡U¸”TL FŠ£'l:$f‘%ü •öŸëJµÚÆ…Ðcâó:êÚs‡EBÕšùÁŽLAQ¬°ÈIƒ ¹å“Ü =tã4”4MÌÍn2Iã¼"M‘ÇÞK¤EV½µ^[¸:Ê"¯¹,pùAöÈÜaSÑx« ]†á»Ï3ÔY¥²7¯$õïê’Ûô š+Û ¤§¬6Û—p¬›7þù¹A¿0;?òEË(ôi)j‹ÓÝmÝ}m ÜY»‘°#ÂÒrX¬?Œ=¦«(oy"Ç6Z­ŽÓ H×p”®p¨èc90ÅPå‹îŒ¾›£?±a'„Íãúš··æçéŒðet`ÖC~ï{1Sð9–h)ñ­^Ç¢þcñŽä“;ïÍ`ËٷËmû/ñ>1ô8ˆúVžášÍï²ZÝ•Ì qöÔŠÔ†®cÑr dáȼ‡‹ò#;áGKÙ#8HÝš,ˆäsˆH¯¢bWšŸV‡¥ïzëP×lßÕMM^ÃÆ›Œ*û“…eðoŒÉÕ†€tÜfÚ§Éq'¿#wÞ1ëO k@>BŠìî‰e¿wÒ°ž=ÛOãÄz¨IÛ5n«4Oü¸s§^asS¸úPÆ\ÐHæÆã¥6ó£3t§E*ÙÐÌ×C¿DÈdò|~¼-'kEþW·}ƒ–Cº«ñ mÉœùÔ\Û„½ëuì–ô+ÒLU]ŠTÿ5»ûpBÎè5Ùv mýÍã÷@Ô.ó‡Ýé#<& ›¢Þi¯7#4ŽÄö•–¿¸Â`ŒŽ|újôȤòÀóZ‡ ]ö8V\ø<$ÿLS›…y÷±õõQb—wóvT ýY¨“ûúŠŸ[ƒ/»]¼%Õ6›¸ß•¤«žÃ%&BÉ×5ÿ^¸ûüàz;eöŠAh섧רÝ0£Î_4èÆ•Oª¬bŽ·»mî~ÌÉúåŠêî}Ÿûß/µó$Ÿa]+3È•Ì÷Ü$;²i+Û°›}“¾~„÷ÞxR•¤÷T(žS’ ž×Sir8T™ÎÁ\l5&|ºY¯Y:ñ{»÷µÊE‚§³Í^£ƒâºÇ…V™qV 7yA”Īôp­Øù¶0˪ü=bÓ~vµ³w”Ñ¿1›^(ìk¬9B©y=íÒ|¶,ÑpÕêù"몕}._œ¸¬| [«îƒ6h§('l}2 O;µ~,§¤$ endstream endobj 659 0 obj << /Type /FontDescriptor /FontName /JROVXD+CMR17 /Flags 4 /FontBBox [-33 -250 945 749] /Ascent 694 /CapHeight 683 /Descent -195 /ItalicAngle 0 /StemV 53 /XHeight 430 /CharSet (/G/U/V/d/e/four/i/n/o/parenleft/parenright/period/quoteright/r/s/two/u) /FontFile 658 0 R >> endobj 660 0 obj << /Length1 751 /Length2 1212 /Length3 0 /Length 1744 /Filter /FlateDecode >> stream xÚ­R{<”i^›ùÒÈG|k·PODdy1ãÔiœ6+ QH›1óÎÌËÌûÎ 3NYt”-§%ÆOr(tZÛRR”¤MdZÕ°hÛbWdVìKÛ~¿Ïþûýžžë¾®ç~®çznãô=4 »a¨Ä"AÀÙÓ— ™hlì,‚C]Ø@öö Ep€@Tk{²Ñ8c™áp%ÀÔÙlQd h|X„0(ðdH¸0ïÁdðÀŒ‰À Ðx<à»xB |a1,Š„Y$"”€P˜ƒ DËE?î(¶ïʬÁ{*‰qSÀ7ip‹, åÉ f-½0ü.wòÿ0µ¼¹[çÅà/¶Ç3úËà#<Ù_<ÆDH`ðÄX°].Ý¿³æ ³þrÖ]Âà!LÊáÁ€ü®„ˆÝ)Ì¢#&°<1¼T‡QÖrxlK,ü>Úëo¾ô›K ?™à曆Ú% ýãÙˆ)ØO&‘É.Ä×ûÝeW¹¢LŒ… ø8P¨€!1dD|.pD1@P,°÷kIB1 ~à‘Ä6&".~¦=°ÄPx±¸„)d`)‰Â–ð?ßää„Ic,ðÁ³°Â…do l)ä¸ÿ2#D"•, žÌ{ÌFðaX 3‰=ÝÓ19,»êHY¼kQ[9a‹Š§ú´×·õ·Ô“~LSá•>ôné­ PVäêü{ˆ0´!jNO|¢6Ö§ÅmüKá霮ù¡È¡Üèz¿åzÊ~Î$iÞ¬êœú…¢âÝÞÛ\–Xܘ?q¬nêâ7¼òùÆîì¼v'/™jà–Ëó?z¸ÒÄz£¯Vްì˜ÍQE”VfºªâqR|ØQµëæÏ&±Úme‘ÚÙŒùà©—í;÷ëÊ»¨ÐÖ®'Ün>ËH9¹ËÜfÃÉ¢¯ònÔÌ)/É-w´YW™œÎA;·É3T×ëFé]û×Å^Ë'%>ï<Ü\·naö Ó¦Çñ­/‚ëª4ÅžÕ·¡KÛS·7¿Qm¹;O7Vj5Ž×ß{ßüJGÑwÊæ…ê”ð¾‚älm É«×+Ííú^a›>a5MÝ-HÛåÓzf²ü ¹.ÍW’ϯáç¨m0Òð»´‹'¹wnßœÀáqZâÚ¶’ì’鄪½ϼô¦.­dUX¿Êë{6µ,)»}‹$ƒTm&÷øâåžæ­ åL9ÓòŒ“§©÷~ ø<š7ßœ|;åµë‡ceW:ódF1ò½^K~©•r½q ¬xèØøÀÙòoùZÔôäU·Î*ÌŠÖˆUqÙû é­¬o8izúîêÓšµÝvT>xQl<þñ/5óñˆ~"Ô¤¢¯©Ïeb endstream endobj 661 0 obj << /Type /FontDescriptor /FontName /XTJZVU+CMR6 /Flags 4 /FontBBox [-20 -250 1193 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 83 /XHeight 431 /CharSet (/one/two) /FontFile 660 0 R >> endobj 662 0 obj << /Length1 901 /Length2 2413 /Length3 0 /Length 3019 /Filter /FlateDecode >> stream xÚ­Ry<Ô{NÌÅ”=YËO¢„Yl353’-! ÆÌof3Æž‘´H‘ìÙJö¬)KERY³g©H Y[Ü$Þ©î½½o÷ß÷óýç{žóœç<Ÿs޲¢ÕQ ‰á3èl $ ©àÛ $ UVƱ@›Â Ø €Ü» `ü<M€ÔÕÓÚ«§Í%83ˆEñðd»qªßI(CY"&°=AWƒH GD È‚*°ù^á Ø€¾ Ë$Á H$@¢Ù€;èA¡Cáßý˜ÒÉ õ&ù1ÿNùƒ,_®)`7פ*ÀµHbЩA $Cá– n/ëäÿaêwqc?*Õ’@û.ÏÑ¿²…ôWžAcú±Ap˜AYôß©öàOk‡AÅö{Ö”M Rˆº?!Н1%$YQØDO€L ú‚?pNúÝwl?,Àñ¦ö‡ðfj?¶ù#eE ÐÙ¶AÌD¿sÄÈ_1w6,J à„€!H.‘ûþþ¹üÖê È QèÜsÐÑ,!ʽ n¤„  ` ×/Fg°¹%w$¡™Á‚~_¦.€ƒ>~Üpሎ'SüÁ_€&`ø±þ´÷pýAÀ™H§‚dö/ùúóþQÓྠ?Hÿ…p‰lOø_¹‚ìÆ/)4Y?O‹e†hhéšÜJ$…P:ˆÐÿ!ýX\+ìGÌÝ×ß1™ÂÝ.‚Dèó~Q?Òëjõé|ÎÁœ®È¬Çí8ËŠû=õ›"/ñPo<5÷Ùó¢Üa¥0EBx2©°*ç{¶î„u»ñ|¸O\RßÚ¤¿ÛdJð9‡¥”ÃAo˜;–#fDj«{?¾×á9Òý¢5?Á1·9}áÑL–Õn#Û·ü#Š8ùW>HÔE9§Pí¢£ÊU´mD“|òÏhGˆ&\æíŒàxE Ô¨ /2êüÄWr2ãל?NupÚšÖ§ëBïèðì§Q= çΛ¨i+œÏ‰M½swu¥8 ¾¿K«Z%.‰ÞkOÐ=X£t¹ïé˜ì‰ÊtìÔHoTkV€úÄŽÚm¬ˆb'Ð$ozåfÄûm† ~§û;¡âçûì[Þ æsîö$Ê<»×iF#ùGcf§¡NÂ_ïiŸi€ñK ÞZ-1,òÐ5; Ûl|ý¹Pð„ÃúÜÃ?xjö· p® Ÿ­ÒBŠÝîl”ÛjŽo·—•uKÜ$9a•pöøô–Q-‘ià28+«ðX¨í¦¹¿›*¦Ï'{æñYEÐ!ÐjD^=`°³öªäÓ샓ÝOz/*vÙjĹ#·FlÊIÞXѼ´4ʃÓb&ß­÷ìZŸµ¦Ôu˜”/8»zœw§µä|°‘TO¾›høÅõì³m5·z¬¡RÍøÁŒj +Þe“ôan®IÒ:Ñ‹žß?‡U§YB´ü¾¢–*µÙ$ó•bÝùt€}Ò21#^µVîf­ î÷Ÿ]ÿS±¥Á†æ àÛœ«Æ\¹´½¥†YÔ[³›ÙèûéT„dt|M›ª÷…±‘Nq«oö­Â¼Îœ!ý —g„P™¶ñ°fKÁ;‘«¹…¡°¬Su‹*zÙF·8÷§ãäùƒ!ט׸ÈV×<“%È‘â”`\ï46HºsÄDJx»5:AÖlXC_­:/³Ë !£ÒX²äç­ë+ ž È›V>×¹©·!Q]’;ôðS…U(S³€-˪ïĤñå)¢Ï”ã?ŽÇt<¿QßK’ÇZ€¼mÒQËîwG­^Fgž£ÉåSJÚ§Oe{œþri0Ì ²"¶2ã(Û;Ûûõ¬^o˜ÿŽ”‚£õ²Åu(T”Û¡¯nqÅßPçd£Eó¾ˆÉ«˜vg ÁŒ¿yA®7b‰N÷ñ·íîú»¶<%~‡àá”#ć³ðòѸháìŽÏZ²®¿¥Ôâ&•Í[g |ÕkœJ’hÜ(½sÏð@îxÛn>økÿ+¾Œ¦æÓZh¦ÐånÕû+†)n/ÃZ{Jî„·>³CV Kó¿ºÑ!´³!W->žÙA4 dœ÷e¯Æ¬&d¾a0„†N Go’õèܤ*¶­"Lá†@õ˜®ãì+NßìÁ·ãÑ¡.Ø^)½¡Vþ0wƒ±ëÆKˆŸ>4ékH´¢­w¿B¿}™q²³Ôôë¾f5»Ò¾7"JÔ¬ä´o2c.é‡ \Ž–"‡Ò†¢j+T^ _ S”È ”‡Ô•U”@…´®fä\OŠ *¢Cg×·Dv/ñ[0_÷+ë º@çœ3ïÎ-nt<‚;•ñîó*yObª‘ÍXŸÏ´¨ý2Âbú‘´é‹öSh•è}%MµéHüì#õ~vyònả-Ý9¢ïž»¶Û,Þ²k½­ýçõN"c¶ F+Ö&£¾<·zj~pü¥û€.j¦Zú ¤ fòÀ?|ù&¯QÓ¬ç.jÅ«kƒZ ˜ã¾éäň§`©—røËÑvÿ%ì[keÇ5 NÇQ–õΨD²åÂú¸  ùèJ,£×nêš‚‰+qÁQËâ ›ø’%ªÆ² סnËÈm·ãyÑÉ1–»Žºrb¾òÎs ꚦïÔèºÄÞ¤ÌQZeS¸w“fáÆ‹Â>Ç£8¦Fo6ù(¥d¼u®ÞÞ‡’Y7@çŽÚöÞ,­I˜}&P€=”¥è¥¡ä\Rgº@kÑ.»òGLGÐÈ»ÀRÏõasçn™’­»ÈOƒ¸ki–wÂð­Q™bVw̆Öž6iޓؘaÓG±;„ÉhÏQ‘é~3Áï!Ånç¶ ßTRëÜzõYæÌ f_¯ÛÔ°W u¤¾;Qΰü NÜr|;ÌöÓc)¢Ó1ååz(Þ)£[7Ž©JÃCnWN~|6öOIçØ½8u!Îø­cßµäñ×Ê+Ønÿí9ïÖ~—ïý“tå4j;ðL;Öµ2•¡áèëq®½ëŠ‚üCÂqrx«°ÉÖmþÒW‡*õAÃUä¶Q}³lÃÝ'Ž÷޽±¦¶5WÖ|‘„‹ìAÔ?W¨¢º.#Íš-áFqøÐYJ‘óõG~!MYUÀS>›~‡ügZæõOŸôOUK9NY–¬å=T-r ÃÄEè–è×~Œ.ús>NÃÂv¤XÜC*¯òŽæ°gtcÃgìÜ֮ųòõ KF1»(äY#‰x©O)i]¡›WšLD“lE‰¯Ò ^7ˆ"²s¾Ò¢n§Bz8ÕA–«ˆª²Þê‰F·Ñã5SUv'ç•’W6«S<É)?ü5°å±ÚHŸ(ذòû^­¾§j·ï™*V *æØÎLÿÔ±ÖQ—âíç} 7áÉÆø @að©œùЍk&÷¿Ê uœêæËë[º[ðEІ‰=ôÛ|Ú^ªŠ÷U­)⻼˜M_pÆûÕ–ˆ©Ñ†á²ÃfwªäÍÑÝöY,\E:sóØg¼@1•Ú·C»±“Û3‘j²e¼N½ˆ ™QA_Ô‹ÍÕ‰¯ØÓŸ¿í†B•™ïëÉäÉvµOŽQÙLþ¯ßß„À î<ù.Vö’®y<óÔ|àQ4ÉnÅørä×+wjİJù¶G˸\ç±Ü½ºàðnGú“1ˆ—°ÛÚŸœÃ0jŸzc 'V ÿøÎ endstream endobj 663 0 obj << /Type /FontDescriptor /FontName /ZIWGZJ+CMR8 /Flags 4 /FontBBox [-36 -250 1070 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 76 /XHeight 431 /CharSet (/equal/five/four/one/parenleft/parenright/seven/three/two/zero) /FontFile 662 0 R >> endobj 664 0 obj << /Length1 939 /Length2 3528 /Length3 0 /Length 4148 /Filter /FlateDecode >> stream xÚ­’y<ÔýÇíY"BŒ¤_Ù×1d0d_’} É2f~˜23Cö%"”í±Ž-ÙÉ’‘¤¢¬ÙJ"[ÊRTÈšîÔsŸûtŸûï}ýþù½Ïù|Ïù¼Î9â'¬låuÑxÐ#ÊÃ`@ßÜÖ ¦ÀÙÅÅõ ’ˆÁã DÀÔÕa€®¿ ¤ÀàˆSŠˆS0vq@ïDÀxy)}éŸ"U@ 0($0G½A,­ éØâQ¤èúø6?_ø6 HÑ ì0€Æ ˆ€è…Á±C:2ÁyâÕ?Ãhß¿R Áf ¢™”hÑxœO€=Ù¡xZ/æäÿaêŸÅü}|,ØŸåMéòH,Æ'èß <Öןs<$àþ)uÿ4g¢1þØfMˆH Jçåòê §à†1~F˜@m…!¢¼O¤ø+âÐÿ4BÞ/P K˳&²ÿÞꯤƒ#Úù‚€âßê_ û›i3"`gEEEMHûþúsùG3C Æàhg¡2ˆv4RB`‡0檀ÃiOÚ`ÂO<ýçRáªTÿg詪Ñ<ÿ‡h[ƒ"ÿC§NP‹ý;£9‚‚¿¡2õú U(æ7T Ø¿¦@q¿!­þ7¤5#ü†´R~¿!€CšOÿ_ø¿{ÐÓÆÈÓF#¯¤ûÙU PUQ û/!ÊŸ@qÄ_‡NÛæ_쉡íAûÄk%0U޽þ¾~)bpv‚#-ú.“Ý¥ð¡Yxna&¥ç£1¾?QúLàiƒwÒ>=|é gŽzb¡9ãëŠÏÎÆu«R•]È©7Ù¡ö»/o>ßT[m^¼dŠœxzÛÒímCÁVA‰Gÿ±#T®“Õi¸–É;ß»u²eÞdBÚfTb·ž*àqމ'±ýq”=åÁž›\êÏõÖÕy8Mz‰·Íî]|Π–qÏŸ½½u"·Oñž' ·ždÙ!û¨£/´½ér§çò»Â7-Šk& ­ë/¦¸ˆ>^éÆÛl£®…¤Ënйßh¹Y¡ÚŸVBhN?1ÒÂïqfd}³*eÒb¥‘<l=¤{ÿ=†Tn^h¬Ç›]¤(ñ\ÈãÙ¥§Aú­¯÷„:CR$g¾8ò:é2°JdÁÒ &îI¦Â+ Md¸FnŸ?©fýH`vùåäÂt!þŠ9aG`.h£N]ÍŽe·ÒÏÏ´ïù«ÓKŠwU¥˜¸4Õ]›¡º#:Hl ¥2ÓÛ*ûÜKåNÖ.kׇ©>]\?ÏcH8ÊšXMDµ…¬~Úïœ'Ðá½n¸BqȺ‚ó.ØæstïÔmã¿up#KH>ð<‰Èþ’½Îh™˜ô䊅ÌFÖѧòuªäÉeÏ–téìÁiÔ ‚Ú)Ô¡Ï‚XÚž{(Úi0â%”qöQ» ÃÛÁÝÒ«î Íäçr[’ýkÉÈŽ âg='*Õ9c:¹¾ÕÝc~ÐÞxP›Â›"·íM ÛÇ_Q|¥- ©Çá¡9§¼˜?á××C³Dˆee•7èTÀ¥NrîŸkón—-\â™gæI”¹a¼Wvé„ÐkX0¨éü1rLß|¾÷ƒL:‰ÞÏ- .:âíèU«Y|<ÞYü½Ég›"Ã/àPôÇ+=ɉëƒîU]}޲–ä´ëÆ”wÊ­ô&¶‡”ҥΩùpàwõ%ÏsB]^™Uí—.ſŻÌÈÄeV_h/¢²?J]Îá<¤QûIM2盤Uã%ñ…_oõk]>x뛤¥òu.ùË—È€ÕàŒ½g•[\ùÝlÇÇVê æ‡÷Ú´Kùju6ך¦øÆôvÙ-`Ê”~Qf5d‘ìy2wŒù‚øwÒÖFÜî,ŽôR¢üHþåÒÍ“¸ Œîƒš«ç·GcX¬Û|½7mL½æfÒBø¶–9ï2Á÷®X¼¹ˆ=Þ©·)•Ð-VL˜aôàæ÷«å÷&*þÚ©`IJÛ¦L>«›Kd dåY['í²¥$D[h5dìwKvÔê!,JF2-,ã5»Kúpænz­‘²ös`mZ÷¬|g¶ËÒRħ~†fŠô~“nÓw×[,#7¨„gn[ƒ–WJ"D¬ƒ‚’EŽh+=q>a{OEw@!QÒ`4‚"|¢%¼å&¤(шA33ìѦ$ú5 BR“ÎÇÆI-©·?:bõ…:•(ÔÎØ|ß’µ÷ØÄœP~ýu\¶òør"&Ž [°l³Ú'³^–ù Û4‰¨Y l·O>¡ðF?Yª‚,Ȳ£U…§HëW+£HÚ0ͬbîä­7ì©fç’Ï?ªÕx`èádÒæ©³qU¶œÒó.¡_ÞH«Žç{ €Î¯(Ie´ŽñLóøwRÑÑêRù8ÀÁ~3¿™ó G×ÀX徫[zîPVR×·;%ßÃ!MÌwé/ˆÃ&Ô"èù¥¿õÇi 8ÓòÇà¶i„tbêçÆÑ½&íˆYÄáË;²’ݱ\–ò‰ÂÃKò6‚ª,cåÁBÁŒjV[¡Èu¾ˆå’ÓKËÓ½ÖnÃV }Š9ZõW³{uù¢&uÏòŽVvÇq í/0óZ}íp@ £Êôs;á½…Çv’ßü:ó¤Z*¤H EyÜ•ýŒJ+x(Ð>v­A®ÆPóíž²l¸¬³E¹…rœ¢˜ y"Ʊ¹¢õùõž;¢­Õ‘±4ë’a~¢9»T{èlºaUì5…˜Ærk\aË9'S@ïߘöö±Iðe<+açR.Éhu^ïÉç?ާS½¹»§æÁR/õ:h:½(Ww2ŸŒ¨îÝ6‹³ot•àO· R~¿TÅ銊 ϸØÉ¬j“ÇqëtÿŠŸ‘‰ŒØˆ‘©(ÛÍùêdwÂS–A_Ú9ÁXr»7ý“ÑÇšÃç)/sURrX»¹bZá/ú©–‰rÑ X~ÏZE¦§“§•+gïž³ÞÙ÷?—¢ëÓš…gu/Ƴ0iPOÄ Zg}ÈÔ7î-í<&up—1ZV¹AŸÚH©ÕzþÙDLÆÀ©aÓôÞ3Ÿ ÞØ3f]PŸgôå‘3Ì-nÊ d3«/¾$IB¦³*ö>§ ^í\l‚0f?9i’®¸Œ ¯„¡N¶ª´ß¼õåxþ´D-§Šör„ìôAL[:©æz¯ªy^À’ó`·K9Ѷ춤£d³)¹²€]' ì¾xܼ¿àËj~¨“ {wJÆr‘ ]j"ÍV\¤w±÷ÕöhTÁCÁ½óyô! Ó­‡séj¹Ôe^.ç|êÚ½¿U(h‘Êaç_«¨Û½¢pÊRÆ-ìÊ!;ä…ü–F{í¨^·. c¼¥ל‰’ðd°mÝ0Öb4txkÝ/{ÚO«€;}ˆoèÝV&ĸ÷ùìFãZ•ða·‹Õ}z…±EÜrê«S&Š':ü[nô55Z•ÉPíï8ì»â…y¯ö);+=]È”–_)´…"4}G/ê 0–²xWý*-`¼Dj^¶È÷c³"ÌþÈ»(Aã¡Ôš`ñ„½¾)ï oû¯¦“½¹¦“]Õ=$ŒDf{.0eÿ`äl9É)x“v/‡›Í’…Þk7 êëù¢«—ÔUQü@P‹ a•žÅÓÃrè÷€Y÷ÛQTAMMGZJ;Ùrs)"Éoæþ5wªPëî+íª#7ˆ>ÿ.>ý~¡7óªÂ5ÃaCPûšñÛ{‘¼†…ròX˜BeªËzȦag´ üHJ2Ϻ½´¯Ž}ŽW¼\#L¾ÀV?Yÿ8T]åGa&c‹Õýl·t²gSnYDD4ýn˜2Y6¢€—²åÓàå(ˆÚä ÁånD;Ôµ ÖNº|È<âÏ<µ?BÎß®¸îiÀÐQǨzj,[çpž†yn#¢µw³ŠC7N˜zÛz]ËŸ5X’þ­ë;5}+ïMÄv~“ÚêYÇ’[gÐP÷ð£ö¹¾µÚìŸÂT˜nô;‹·¬ÖŽ‹úñŠ« 97Ë4r_;5w·úø:¸ ÑØW[›ï ø¬¬óz¤º¥3ÈQN(xèµöZÈ Õ°žW–šø•߯ÏÖD›~)-»Úõ*Ôqo¼ÅÑ4C^úUiûÅ5¸ÈéNëkœL3ˆ úù¹ÅðÕx‚”õ“vé¡ÐØÌýHó¦äO ¤ì1g9æs‹ŽÃ­FŠݱ#J,™êÙar¦®Þ³ÑÙ©Ú .(®\gÌF¶ž îϾBñí%+n_$ìf ëcœ„¦_Þãÿ1o’= eô"ËëëÛcÝ.àK@´‘Âû\š/Ë÷‡>ÙI=kôÑï!CÛ¸t½g3½CF}2]wµ^rÜ8tï˳ü9ûîÕŒÿÎ endstream endobj 665 0 obj << /Type /FontDescriptor /FontName /NODOJI+CMSL12 /Flags 4 /FontBBox [-56 -251 1102 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -9 /StemV 72 /XHeight 431 /CharSet (/C/N/a/comma/e/g/i/m/n/o/r/s/t/u) /FontFile 664 0 R >> endobj 666 0 obj << /Length1 1302 /Length2 4408 /Length3 0 /Length 5224 /Filter /FlateDecode >> stream xÚ­WgTSkÓ¤w¥£bé5´P¤#E)B( RBr"!$ô^¤ˆT)"MA¢‚ M@AšiRDºÒ…/z‹^ß¿ß:ÎÌÞ3³ŸyfÎZGàܨ„&çèâ°D °$X¤m½–%¥é´ñŒˆÆau`D@VRƒ4ÝQ °¥ÜˆŸIâÙälg¸‡ø¬e×°=1DRÔìŽ(d¤zœŒƒÓ{|¾ÿì×êÀÔ6Uøjר¡ÁN‚n´PRÞq¶5Kg‹ôèë3ý¤Ù4ðyÚ“ qÀbÓhãµ|&’ï¦Àú+è¯oѧ|ßw¸Rs¾‹\ŠÍùægBK×xF«u¼·%¬mZ*>H¯áŒáéöY§}žv1ã6”ô„,ù“OÕÜ7f-*ÊÀ7>Sóì<€9g>O:£³ìãö°VuÛ‚3Ö_òrUÚµµüÚú¡Zv0«úÀˆvün6­ñ[ªh#÷Ê­”j§¸%)ι¹·C½zù3A.Ǹ³üLmŸÓÅšÀt©b›æ&nµºB¨Ž¶SÊ€è¸ÇïÞè¾b\(˜L3}Úþ-IG¹¦Á­ÅǬEWí;éa‚ 9×Wù°¶¬N¡–êŽô³Ë ޶''?GõŒ xèÿÜy¦ÔÀ²Ôã%QŽHÒRüBÚTyfîîâÃyzÌÕ¦?õ±þÃeonfrª-Ey ÈêK¹ ˆ¸g]”›FFƒ˜Û£Ê[n6èj¬_cu@¶Od¿L˸äCÍÙÝ(Äüt¼ˆ±öÑ#¯Éíl Qòȱ^qd×ÖôµÄŵûoçÖÆNÑm\ÿè˜D òÒJTóàÞÂ?[âÞö·u…úÉù_›©¹è©VÜ¥± ×bešŒîzÙ©,Fvç‚õ}p„ÈÎò‹.ßUÌËîâbÌñ‚CÊt¡_„òçŠ,³eãY+2Aù⺎§ù õ'C<‚ÖܰE|š%qù™³ì[û kÑ‘ Þ|—–|X5ú–;L†x &  ¨¦â@þYQ«‰®ëÎaw"}ôc”wç=ݪÑê\Žõ‰¼~“k=š0Ë{ #P‹šØleZ\‘»-¹¼íu™ZóÙU?úæïéi4_oç ¹´N¬;È3ª;0(—\‘›Ø˜_Î9AC—~ô89äò˳W•G˜}¯í¶‡~«M˜þLþÅ„âȰ’(‚èwз±™™ûÐ!ôe5ª áÛ;Ì^x–\Ë]|›ìÒÜ®WÉ’{Óq!žð½G"+Ü®y%1c‘õô¯â­ßU*¢Ä¾ßÙrdzœþµ×,}þ`Åê­}tìçÞµ«½YìõGi{5ËÒOÕÕí73ÙÓ¾v+Ì"C:1yÒËàæ±Úß`CÂÇŽ×£Þ ]=öØ#¾y©¤¯"Ïç—-ho¤ï8¯ñ6$¨p~t„¹mS‚ÐÖ‡å&£3^ï3 u\R«®‚ý-¯¯+õ5º§’aŠ}$TØQR.Z&µ%ȯ=gÚ–^îŸk¿cë¾köêý•ûÅmcrj©¼pGÁå€QG)D*´^u“U9+5Ê}RisafÇU³% `¯^|íÉ?±EoΕW¼\AÀtWÝî~o7`æ›ø(5CÐk€5ØÕ°Wz¿Ð!ÿÄ¢0Tõ¦±rgèÁü³YN!»Î}Ÿ#«8hS¼9­e7gíta&Ã%œ³ÿU„I´¢–:2è½E«êÌͤ¡Ï#Ç¿Ÿœ~Öú{ÞûåO‘ZØéq= >|Áæ«\dVÏ&U´Ï êÞX4>;XWau’×Å(,î´Y餿„Yz[´t÷tB4xƒ¿JÑI!P5ª$‡s)9ˆÞ:VšÙWk0§Q½TÏ­¡¨ÇÒ¨æe‹jç}« i®íM5Ph·"©MŒw‚$¤^ ¿HoºTu NƒÛ˜ël7Í9ŒXi-;ŽLhEx§û½*Rß…¼¨Œâ87Ã’5 Iú_8d{®{”êåcW yéllx»i—žÈrš°Vœa`zk'ï6^[$†ÍN|;„«yIõ¶áROØI®åA¬}ŽñHŽZrZl‹/+ >9•s…×Z…qÐËÊõû7)ýÊ(ØÐ‹sÉSŠ|ÉYVËÜçä%¼“¼¨Ö¡¥¡5z5;Íýsñòo|¦|ðÃ: ~ö€±ßØ~Mñ´Ø¡2iO^cXV×ï8ùŃ6d”ú6ÙvÚ”¹tX0] &íH :ZgpKÅ$ûÆûFöº'|7ëÜ®jSOj8‹rìù.ÄÛ§‚©Ks½ûfej ï’AU9ãg“[3sò›®ß:y—Øúþõò¥Õ)¹ˆÛ•Ç…ÚM[z× uÝÔ¾+âíx ¦²}°B,®— JÙýè-Ïß­ ô]æÛŽy°HŸ/ܯdÔõKk¡!%×!¾ª•ç+ìÈœH*(Ìéß‚:JÊ5¿'(xVt Ð9eÛ†U“GîŒ{GH?7 ž¯i½cëÎ¥^Ÿþxƒ©ßÓƒº6²üY¤E>÷ÊRè #S "|ìÖÞ+ ù…Dné%Ú.©Bua]¥õWWnQ®ŸUÏ’=€ŒußILÃÄv‡¼‰Ž¾WA6×°S—ȉ=àDôØ™*¯ëI毱9—˜uo'y7±†×!Ú—&NGN†d}Öà‘“÷B²nZ­~/Ëï³W‰ÕCó¿Ø–š.:š2sl!wݺ~®à4]­Å’jk’Yµ@ãüæYPéâ‡þõ¸Žýâ® ¼1측 ³3ÐqKdØOfâ`œû©VI—aʦ”þË@m zºN‡ÉޏdªÞ]EÏËÐø4åaµ$cÅd%›UÎz+è~‹뛘¬Vå´—:ÝŠ#¼kÜÔ"³ºëa/8x$‘[‚L.?ßß‹{3Ó¥ÿÉž}½Ô75|ŽR<†‘Þ(æí¥ >§¬§S˱µ×z§œÎ&yz<°eïóº%òVP­ŽŒmuµœ•<ò™æ¢¶ »v¡Òל°¸ù•Ë”§=Ž5̈õ…xˤ†}Ÿ3-¦»ÊÞÈÍU–fÕCPÐý.–WùcTD«´u9eÆ{Çñ†›òµçžuž¦AãRQ·Ï`øÉžÜ©á²çë´ñŸ>™ÉB+™Ë{« ª-*¯¯w‹òí^ŒWæ¯/κg|kO½[3Íõj ~åT®-«¾Ä|{ýhõ#ÇíÇyµA¨ ƒÑ0¯CD­ÃÞ¦*í[uOaé²ÏmÂÔÕó®Õƒo5 Ò«˜²N< k†HX2³àS€>^ÕÄèª4¹¼ ^)xuÆŒ;nå./:DÕ+›ô£-:8Ëò±ë~f/y%vrÃê ]J¡[áf±ÖjÿμL‚›[kt¤éÂ|¤æý§ÏïUå3¤’ý·ñì™Æ+VÌsËn)4XÛä¶ÖǶ´vŒ´¸öµN2/PßÙ *7ëfnïëi}Œ-_}“óðf/×É€Ç^vWSTû–oS¡ùË/ “ȗ̲vš#zÑX¸Q×û¼ ï ½xÕK–Mzú÷à iÆÒîÎâÌýz•9žç“PÈSö2×Y š|Óæ8‘yÞuSé‘ìIý¤]È¢ƒeùå¯Õ9áÆ\½'ö滯^€…xZƒ5E úÙúJL•X¼j€pùYÊ5/J ÷!Kü]ÿ¹ÙðëP­ÀÉ»'`Án¼t0JAèýoŒïŸêO;Ñ$Å É=½«Ñ,F7åmÙ]0ˆsz–ãà«t ùCÙ|ø&’7B;h.~ yæSEïÄqa*µ5;\õîêãÆö8]¡c„!Év¶¨F…Ѧ±×žÏò+ßI:™îÈt*ç­€ˆ8?ä¶4TZ.¾èˆVñi§¸°ëëDZ4¨ÑP~µ“‡fÉÝ=µàÜN]µ÷ÃàP–©†Ãy ›XÎWè€ëûP%õĆ–³ŸøfÈ[˜ZX5.uHœE­e`²Óy ðoiVîí¶¬4 Ç‘M`”žÍ©¯á¶eŪ§‡/Í•C¸Z26ßòXtáZOæ6M¬— åE/2Csf€’^}Ïû‰¬Ÿ‡?ÚØ™rÑø¶l@FoÕ”'Wy•¨0ëˆ+Žñ§±\ -H?mÈ,¯!˜žÍOQî¬ :žÖê{6ͳ?2*CÀ!9wÅ a0öý E³«wû´§¸]„ýâ ÓÆzPÄJ»“?èm‰qyݵŽ+˜ð®òcý†ƒ¹oì6Üs0)˜èjh#O°Ø€IÎè&øšÆbD‹Cñ\ƈAÄ¡ÝËfÙËÍÏ-nwÅ#Ïd± »ø5ø½\;Ï‘ µì~8­ó½¦m£u=äTG.*<ýEBw?2I£P­PÞ>¨”å îKµ…ÿÍZƒîÆ%[ó“OU8ySÄ¥ŒÛ¬çç©È³¸Ü»|ìLãâ´ vkÉ÷‚d…˜FŸpX%b?Â眣/ž,“íwÁØ3[;µJžÅÜš]xš3”§8Û¼@ÇÊJÍbšö1  ºüŠå|Ï£¯Z”e·Uö©Ž¡tÓöfk­F´¯2£ì%oÔÎú[ª> endobj 668 0 obj << /Length1 744 /Length2 581 /Length3 0 /Length 1092 /Filter /FlateDecode >> stream xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž4S0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22´26áRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥rg^Z¾‚9D8¥´&U–ZT t”‚Бš @'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<(0¤s3s*¡ òs JKR‹|óSR‹òЕ†§BÜæ›š’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l ‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;z`‡è{8yºzjCb,˜™WRYª`€P æ"øÀ0*ʬPˆ6Ð300*B+Í.×¼äü”̼t#S3…Ä¢¢ÄJ. QF¦¦ Õ† ™y)© ©@ëëåå—µ(C¦V!-¿ˆ © ú¹™y¥Å Q.L_89åWTëš(èZšX(Y*˜[˜Õ¢¨K.-*JÍ+'`PÀøi™ÀàKM­HMæºy-?Ùº%kú¶¶•u®‹/¬bÕçüybíË›ì"vÔÍÎL© 6¨˜^²äÕÂG[û‹g_”ðJ¶ž*\´E²×¯'îË"á5[»,‹˜Ð`º_ïF°xes×4ÞÚê¯<†Í˜ÓúHÚjÑãYÊ:7¿(×Ÿà™—òÂ)jñ¾ï÷®q iMÒR’2¿¹‚ý.£˜xåÝçWÿH+r6Ï‹º¿=!¶ziøÓkžß^§J7— ˜ìâ±¼Ý딥b÷%hžî䉪[EKš2ú&¸RÑ÷úåã1wz ÓÄò³)Ó_•ÿ¸$>HÊÇÁù¼]Ùûh£‰+#ìÔïëž$(¡ɰÖ(ùE{àþ§VöufòKM’Ü%KSã&|ê˜!b;iué²_Ç6®›Ù娜QÊQÖ ² endstream endobj 669 0 obj << /Type /FontDescriptor /FontName /HBIEHQ+CMSY6 /Flags 4 /FontBBox [-4 -948 1329 786] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 93 /XHeight 431 /CharSet (/minus) /FontFile 668 0 R >> endobj 670 0 obj << /Length1 752 /Length2 721 /Length3 0 /Length 1247 /Filter /FlateDecode >> stream xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž4W0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22´25âRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥rg^Z¾‚9D8¥´&U–ZT t”‚Бš @'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<(0¤s3s*¡ òs JKR‹|óSR‹òЕ†§BÜæ›š’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l ‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;z`‡è»„9;†hCb,˜™WRYª`€P æ"øÀ0*ʬPˆ6Ð300*B+Í.×¼äü”̼t#S3…Ä¢¢ÄJ. QF¦¦ Õ† ™y)© ©@ëëåå—µ(C¦V!-¿ˆ ©Æ ú‰ÅÀÊ,ÎÆIH’ Ó3NNùÕºÀ„§kij¨`hdj¤`naT‹¢0¹´¨(5¯œ\€Aã§eƒ15µ"5™ëæµüdë–¬éÛÚVÖ¹.¾°ŠUŸó牵/o²ˆØQ7;3¥6Øt^ bzÉ’W mí;,ž}QÂ+ÙzªpÑÉ^¿ž¸/‹„×líZ°,bBƒé~½Áâ•Í]Óxÿi«¿ò<\6cNë#i«ýEgu*ëÜü¢\‚g^Ê §¨Åû¾ß»Æ-¤4IKIÊüæ ö»Œbâ•wŸ_ ô”ÛŸº²gþ£ç{‹¢ 4$=û½þ?³Ø½l£rÛñÏÚ‹®é-’¸ºÉï™Ð¡CüÎg­ÿò~ЖˆÎÔ­Vßw\“ïýŸúSï¾(ȸÇÍÍøøÍŽ'ÎÏ÷q9.üqbŽõÁlSçÕùiqkâxŽ(Í}ó'âaxª“ÏÄ9êvõ‹öUëM•ÚÞyQ=)zÏvf;†€€×zBO<ý¼VÞe¹døZ£¶«ÿr*‡1ŠF´½3»pøn^Õ¢÷sŽ0¯ÿ2/aV¡üáC‚ÏüúÕl–ÖÍ×vìÁ=½k}r[×+Õ[¶!ÂnÕe—>è7L¿Ô"w+­¼X*ëüîÕ³8fëªü°ïwv¶àÂܲµY&{µ±üz!¼ÐÀg*_Ù» ¿X¯º¦mÞuÔ0E5aÖe«È_ëž„–êíÙ¾½…±VàúßÚ/W*m˳ Ì Ê–%Ýz4UáÑÄøÚ½©<› ÿ^Ó}ru/ÏÁ¹z2Å){Þ hìz ¹lµ©™ÉëÃ5kïm²iµšµÜèü™ÂÞož ~üòð[ÎW.½l5É™qëÊâ¯3žõÅ>iÚiû7ôRA,ë…+½5z‹¶ÛèI«:/zØcfs}þÖYÛc¸o§ýüwýô¯$ýµŠÇ¯Nú-«m•ãæ¬™e²ñXàÅ‹7;:Fyý¾¸XƒéCìÒ·Ok24oßh_ú§rcÙ£¡SÞºý‹è«Í^?A»É03j÷ßWÅ–Ê›g±^rd¾X#ÿà¥ýr9³_j›rÚÈ„4rùøýû,ø&fÙzîfÃlNÛ ýš±(YC endstream endobj 671 0 obj << /Type /FontDescriptor /FontName /SDVCAT+CMSY7 /Flags 4 /FontBBox [-15 -951 1252 782] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 93 /XHeight 431 /CharSet (/asteriskmath) /FontFile 670 0 R >> endobj 672 0 obj << /Length1 807 /Length2 1009 /Length3 0 /Length 1561 /Filter /FlateDecode >> stream xÚ­’{8TyÇÑFŠ¥¨tùK®3sƒ¡Ú\C‘K*÷ŽsŽq2Îgf4“H[ŠÚ¤tq_ºmJÛZ‘Ê"zä%aM-)º×Ó“r©¤=´¶gõï>çŸó~ßïïý}Î÷=FL–#JF`n$!aqÙ\{àìåh¸lˆadäLa°' X‚Ù.ŸÏŽRàòdkoiiÏ¥MÀ™É)\%&Φc&[àƒQ8À –Da1ô Á1‰œ …Bà7vB ü01FÅa(›ÁåG$ àƒ3äAD’Àö‹ŒJE­8ŒÓPÀ„†44"JB9@±HÇ›¤ïÂh’ÿjòp7©Pè ÇŒ é›6ƒ åÿÈ‘T‚QÀ‹D1Š˜l]}aóÂP\3¹ë!…8âH„`q­ÙïK»á2 õÁ%Hˆ„…bl\Çt2 Þ8ÇÝ)`½›ù—­Ž÷|`œ¬•‹0}5×ܯ5…Ë@0Ć .m¤Ÿ‰·ÐIw¹‰â„XòlLQ°œÑ£,y<Ï8b2€Éh`› %ô@'“"IŠ1¶T+ÀÅtR¸8šÞIÔXs\‡''¤âk;ÀQ8ýQŠ¥5àˆq:t˜×¾ÍÀɉ”ų¬ ÀâÓ8\®ØÚòþcD¤…’ñ¿ŒNr¢ŽÄéô1L†! E‰8ìÜt´|WQ¢ëñ–3S9Óß7œ{¦P«ÙP‘˜ƒ£ þ¼|_¦@râyáò´:ÝèÛs=‡ÃÚÔ…yû¼ {wL»¸lOÁ© éI¼jv§¿®|Çž#3GÍŸ{ÔÅ®ËÌM~¨g_Mõf§X(Þlk˜‘>u :^5ÔÝ¡®eæwÐL¾­â´Z—²Ž®¼ëIûˆsúŽü`¿ûW̶ꅦ%î)Ö|îÜqú|>Ø - tåݨʴîô¬ÑTÞ}ªyqÒ@—¢U¿¸¤ÖjÉ/Ø&$ÄÓpA³åOÃ6–ªgl¨ÍÞ<àßpÝCSå|?ÕG4¹9q¦$µd˜¸‹TŒ >ÞÕÕiZöhl#©"º*$çŒBÚÕ GÌæÿp#<ä.5/K!lF–61Ý—Ú_Ípr{Öjþ'˜{¨¯-¨+çMSÈàIeõuk‹Õ{î¦/+CJìV\†æ ±}{+“æ )—‡—&ð­VVêoŽm¾q”È€ŒlÒûj«šÉÏI„O|®½JeBNB=eÑúð±Yèrñ},¸ùÅ]Îþ™ž¥ú¯äÍÒ埬\ûÉ,bå¥ ¾†.óylV¿;£¡<ðDñ@Xö€øiïÖáNÍ[põ¾ä…WœL®žmVíeÝùUZ¡œWuj‹»0ï)¯4;BÓù*kMªöÅ:oJtio\ÐN$oÆüúìÅE+¯öEÜí Y—+}x¯lÚ°q÷Çþ%6%§ýôg$Úô¦,p²á?¨€Doév …(TÏåB°þçÁCQVÑZŠ]‚÷nú/zòôæ-°úÜG÷EZàGäs£RìÆ]•[­?¥$ö?¨]~…¯•Ê;]ÙØÝ­ä§Öh¬’õùó“׌™FmJÉ, ³tC‘ùò)C -¹…!™±³+¦Cá¦i¸x¿qa׃ßþTû•AêÝU]õš%2×ß_¾ˆ³>8wÛ÷¿]HÄ}¸]µ9ÞúMòæEôãp¯R°øÚÎ ¯GþçÐ…Ù¶á©Vë3–»–«º¶Lsɪ¥Ô檲VÅèŒF%û¦AµÕû çåL¥>äèËô žwö¤§íÍbþUŸ­¡[zl0(RÚû]b2¨PÂFVul[0/•9ÚÓÎÔÓào*ê›þ7ƒ^ð: endstream endobj 673 0 obj << /Type /FontDescriptor /FontName /HBUWFP+CMSY8 /Flags 4 /FontBBox [-30 -955 1185 779] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 89 /XHeight 431 /CharSet (/asteriskmath/minus/prime/similar) /FontFile 672 0 R >> endobj 674 0 obj << /Length1 838 /Length2 2359 /Length3 0 /Length 2927 /Filter /FlateDecode >> stream xÚ­Ry<Ô[—½1È’åÚ~ö}Ì`fBe™ìÙÃü03Œ±‡²IY²„P)-¸”.RJ–ì2ÈZv•õ•ï¤{ß{ßÞßÏ9œïó|Ïó|Ï÷9òÒ¶öꆊhB!ÓÔ0„.€Á:˜#à‡Aäå1TO#RÈÇð4P@èèh& ãÀغH”.‘0”À*Ñ×(a”ЀaH%zãÉOó5¼ñ$ÀžâMi0ÀDì~ÜìÀ` ` ½i€èK$C4~h2'ûPôÏ0!$ð¯T(H fˆ”öd* ‘ ™@ˆ†5…Ñ dhùÈúµ¸I‰døQ~Ï©ÿÉ㈤ˆ?”€ÀH°H%ÿJ=þ‡ Ä€_³æ4<‰èmHö%€:B×þ'›ÃA‚-‘æíøàIÁà^$~UÂðoO‡†‹¹‘ó1'Õ?G»—´ÅÉ4‡ˆ@€ÿÍÞÈ¿1Ã$*1p…3\F0ˆŒõ× ÷K3c²7…@$ûšH€§RñÆ'b $…ˆd€á Å02…Ƹ0œ‰|(Tȹ2F£ÿú‰t ïÿ ££ø¨høþ /Ò ÿ2È”@ AÛƒÿkŽ‘%6ô%ée†£pyòU¥CM ××3pçå†F͕۬¥MbCìËSI\cþ·ŽßXXæûçáŠ]º;—¸|nηóº«5w´ãhŠ;ô :¤Ü}EUã„®‡þäúIh³¶SbÉqõ»C–‘ÆcÇÆ…&z« 6'òyº…s'‰‹æø: WjÙ;2#ìH¿·ZhMÃÔ» /ÏÇÞ|$˜/$×gƒ~vís¶:mvÙ4ÙÌ•o¡Û?".óÙtYSiwÇva?í=WæS÷ÅG‚ nŒåzÑ ‰<ò¢c{9Œ¸®"¥û´™úxüUXæÀRIE˜•IvɧWCžk«ØÅ¿s®PȰÛpo ØUbµ¸D3Òò{+îÆ/…°—¶|%„Clz¸f“ý§Í¤k×^É;,r͸ª7uåœÉK{õ5w¼;ÉøtàûNKŸyå°Íe ŽS82â B®Ûö~S4$–°^' Yy‹ªª5ÿ.qœ3õ :÷Ådrí໸µº*:!µ#Ûù—åf¤Û cUiL /)çjô låÉ~ç1,7ßhÔ.i]çÆÑ<¸gÕXÎáåXL#7†û Ö¨^h‚ÖTˇÊoôûù¸ð¡t•^^)´š­P‹oŒÝ§j×á5¼ðÂ|(P^¤@Z¦Uµ©ZxîÆcì"_˜ñXûefýPÚ(½5m!ãx¾Î¼ûA÷`áRÅæ˜šX=ÞrÛÎRPQ3ÂYûÔÆóúú°­D(NÀV?¦2(bÛ&‰3²fºˆ2k·Ì¾;ð1yKÜÚó\uç4Øû¨ýKa.±“uÒ\¬–g`¨/8·V¨šÚc«wh§Í^‹Ž?D9̵ÄŃ‚haä ,¸g5´@ûã–Ò–•ã´´•8¥öo(4t,`Ó†ú;I¬—‘ØŒ.AúAƒ.‡WåÍdª]O9`—^ª44H[ý¶= ²¹Š•ʼ.ÿѾUëžžìLJßj’E°¨VüjoÍ·6.VƒYn%Ó‘óýRf›v t4ðŸ«ÂLÎÔóßæoóá.æÄNúŽÈÕ"T'áû 4ßu”SÒ3Q“ërÙšI"éR¶ú_ú¶9J¸„wœÁõIMÄ˺P)JùÑÁ@ûð“PÎd·èç—†ye_Þp8æÐ6F{̘솫ÓZx}²»|¿®¿éÓ¬Ê}T‘ƒÅ}Á@KbüjסO»Ü†“ü£7?ØÇ9ô+ìzP<îjúS›â_5÷ÌÖöw•ŠŽ8y¹;IQ𣧶íoUß ó‡Ç‹‘T_ìýk ÖwØ4,0sïün/*w¼õ*?‚ýdm.Kåô¶:Ù€à÷áâ‹28]ûf—ÓeqDˆâøåKÙÂiN›ØúîÇwI‡£tp1¯ÂRL|fýÍê#zÀxa•‡Ôö~‘·|é|åöUA½ñŠÇfß߸©³váèFÄᨷ«\) [6g&ƒ2% }ZQ]œ;¼æ ãµKÖØï¯ð_–á™u9eѤõÙƒ ÕŽÈߟnUñ<^Þ.ä²)J˜2TwGç#CÊùÙ¤ ·aU‚%-‘¼G=¹˜ƒ‚PÄx²vî;º•^ë4PŸl9z^qšm-´?ภþò$_ïÜ;üÙ|:¡ØOsLÂù¨Ï_£ìê$ÈZƒ‘„µ¸Xô²¼ÜœšK¥ÚÐqÖ9O_wŽ. Ç(ù3»æÈÄ~+öiºÃØêÁµJÓ‘ÏfŒxeÄš_¦kΌ鿜3û¨-žºês.Å+ÝÂmA/˜å[Dz(>ð˜Ù@™KËG)ú"9Šðn3üEcÝ:Ä“vEÝÇrj[Nt‡3a¶ND,^ôª^ºÇýPºù=§çHZÛÉYÞŨ1µgÌoÑãMžQ°Þî¢o"Üe"(›ìcX>x÷i—º@„çE‰‹ºË«‰Æ¬Ã“4Ýä¹5úô2äá}#¿4Y¡Df'—Nx›Èèq–hâDà¶•™&×;^–É(7NäG±×1©EJcUeÚзòï6íJï{¸¾%4É^7½a¬n8šW<Ú›šc9îýîæw&o¶–éÜ “Ç>¡q0×ï•5ªVí ¬áªƒ¯ë8ZÐéO\«TùwëÅÀ¨'aŽH'™úò¡Ñ—]+B)&w£ýOšgŒQ˜j_;z±Ôí‹õ<»š oœ¿d–5å\‰·IQø6}y\[“^G:ΡÄñdW<Õ¾é, ä?EXW¸ò'î†#¥gôÀ …–Üékw^®Ž úöMæ.ñ¬´`4ÝÆŒ1o$n~MÙÅ} íóâëS[±Z˜o´hîbâvúÃ}×£§zÉY~À–Ûi=†„)eoºd8³Gªà 5M ÔÚË›³¯+ùG9™œƒÜÑBifq¹Â³!ú¬Û4C±¨#65‹3hú™TÙê•mþ¸ˆM¥HmiÙÖû&\Þ@«è0IT¥`÷Tzñ^¡moŸ‘Ï#<ôíl ¨ÍÚx¦ª¤º¬—ûtÊòŒ¡ý&iN®åê6½9à›’-‘áž–÷¹]â+>åsòñ2ÙV‰º,Íw´‡ZjÞ~ë§%®¯ˆC³ÏêãÐfršÇ‘}‹¡öÝÌy–{ÒjG´²Å“S®ù›É/F'Áñ}6Wb*° fD:¾×4ürqê·LoMî¦eêí²}²ÉOnÌ_Šá2‡¤Qýçld¦àñô^ßl²ÎóHÑ»c~ÿá| endstream endobj 675 0 obj << /Type /FontDescriptor /FontName /ZIBXDV+CMTI10 /Flags 4 /FontBBox [-163 -250 1146 969] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 68 /XHeight 431 /CharSet (/a/c/e/g/n/o/t) /FontFile 674 0 R >> endobj 676 0 obj << /Length1 1511 /Length2 10559 /Length3 0 /Length 11427 /Filter /FlateDecode >> stream xÚ­—eT\ݲ®q îi,¸»»»»Ó¸6îîÁ-hpwîîînAC€Ü.ßÞçìäîû÷ŽþÓOUͪ÷­ÕsÑ$JªôÂf&@ {zff€¨¼š43 €™ ‚B4v±r°3vò˜¹¹™®f. 3;+@ÔÁÑdeaé ¥þ§ˆ lY™Ûä],vï=Lmª¦V@O€°­-@åŸÎ 3ä4c@`f˜Y™ºL€VöŒÿ(’¶7wpþ;læêø¿)7 Èù]€ê]$5à]¢™ƒ½­'À hŽÀ¨àð> ø®äÿ‡¨ÿn.ájk«`l÷OûméÿÉÛYÙzþO…ƒ£« w0‚ìÿ»Tøoqò@3+W»ÿÎJ»ÛZ™ Û[ØôÌl LlÿŽ[9KXyÍ”¬\L-æÆ¶ÎÀÅöfÿ­ä}{ÿÒÁ¨-ª £¨Cû?õ_I%c+{5OG €éOõ¿˜ù¿/ dåÐeb`bb~/|ÿüï7ýÿ&noê`feo`açƒ@ÆžLï­XØÙÞÌ+{3 èñ®˜‘ÁÞÁåýà}3¾sÂ?O•ƒÀ(üOèßÄ `ýC\F±?Ä `ÿq2%ÿ €Qê±¥ÿ€Qæ½OÿCïþC\LF¥ÿл0%«?¹÷žªè½§ÚèýçÅhü‡Þ{šü¡wÕ¦z¾çLlß¾ÿacû'bg÷ç<3Ó» ³¿ðÝ)ð/|·jþß“æá?I«¿ŠßU[ü…ïÃ,ÿŒ~whééh ´ÿ«â=ö÷y£õ_ønÔæ/|wcû¾[µûKÙ»¿:ÿ£ÔáÏì÷Zû¿lý£ÜñOúý¬£1ho 4wùeþŸè¿ïöÂï"ßo·Ã_Kc~7îô¾ý…ï.ÿÂ÷Ú±¿Ïvqwø+ýîÚõ/|wíö¾;qÿ뼟öø ß%{þ…ï.½þïäý{Ôÿ{…ED<¼éY9ô,ìÌÿì“ÀÉÎäûšº‚Þ÷áò¯—äû‹àÙÜêýÝzMV—LyC¬ÓšÂÊüÄ fÊ¡© ÒKB&ºBÓyζxÑ@ÍÓj@¢_h¡hÖV¨©ç²UŒfæì;xMÂ>ÃÞªŒ¡+hÃH˜Ôyª°¦gz#_‡úPì²#V‰›i/ÖÈn¶Ýº käN˜9óñΣ Ê–—^®ýlü'wV¿˜‘}OEÐÿÚ.—Ô8ÞŽü!éPà°Z4‚£—qƒñºŠ×·9g³”ÎýUr©ôRW²&傪lÐx}ãˀϊäõú÷nØúcóæßMŸŸÍ:‰”ÝìÙ`´ÖëQƒ^¬¯ øŽ¡u{­¬[FŒ(w˜?Á]dö¹j¨s?ÝÍ[V:PL´­{;‹j'vZúaH“j1QÎ7Y@ò"5—µÍgùW-¶XäÛFå®ðb¥–*BqTZ{‚5[tNìÀ H¡ñy¾L8- úÓ#˜»žðÌák4NÆÞœó÷äEŸÝµÎv”¤@‹ö딌DiÏ Û&Ë='&í5¼Û¾ë]JÔ¢L‡«Œãà­ÏaXÍÔ4}z‹N²¶O˜ÈWDuLð]mŠl:úüvéŸ*úÚ–×1¨€D¢ÞO|kÞ&$©FÏŸ¯çå«xû✰ÝR²·Ѐ¤9æ1 ql¡é’€ýTh .‚-tdýë †S_¬ûVšK¶¿µ¸ºÔ•+PCߊ6õ´5ÖeÊxE—"H|ÜåÏH\HÅ—Šýf*º9æ”ò•J,øò'.‚3Üys×m@§D•‚=GY²Ÿ­€èiwËï¦OS[Õ¾ùšüŠ ¡ IN1Ï—j‡­‰/wÛÂð! ®5UÚ9£ýìðª&ç5p|(Íé4EãËD ú³jÌ‘A0ƒ)¼~à•ÕáýÊó«|zZÏw+¢ÄSÄnàQ+:<ã=êz:[ÏthÝ*ÙߤؖÏKRª¡/Ö6ƒÂ]Ô•Ò!G¦Ã/b(ŠÖ€^‹²ôÌÞÄ»Zt[)Ž\Ê ÍŸÔ ½z¤m¡Dö%V ôpã6é…ô—®zŒjwÜ­û<‡Ó°Šc¡Fü‹®³•¡ù½6× ¸ïm>JÄUYÓ«› È©s1®->6WN¸ASÙ2£Ú‘¸ôÿH…¬¼à¥CG`U_GX:$‹‰œ$!G³4÷ÚsÙçâ‡Ó>ÙþR·;Xßêk †r޵ëkƒœ f™gFfÔW–týè.TGq½{åb µ†€°#hÄíNׯFÂŽi ;•w_ 5ýÊä[J¸wÍê+MQ¡£:Ò¸Ýâx—Ž->]1}­E^Cö±ÂÀ„î—‚¯pC3þ«ãæÆ6™™tBS4ÅB”!øçõ%}d«ŽÙ¬U¶‹ -äùNÄdFÄD2Iö–7×%|Íçq×B©‹Zr¼ÿ>‘ó5"ë§D¦æ¹¯]êÌügߤ)æ¿Nw—{Ý!í‚A¥jšàt/˜Ø7êÆ@ྌRL†ñ6Uoë¬z7VÛ„šÌ=˜áÆ/B•ðùáËOƒoĶ­m‘^7yî_C Qz5T†·¬¡3 Õ+õ ”A|•*‘ü6Dž¶þ1i ¨Z^±Ì{…a×<5¬YÒû i®\^|²3ôó„S~ï `4ãÙ…s>Ø-Vêe«¦#j „ë@íçPVßžçv¹Ãê§â‰,‚ŠÞ2Ab]F›ê¤J\Z¥¢yJôn×f•àBAl]í÷øö·‘Ë¥è³ìWø¿¦ŠMJyìÞú ¶2"jYÇãÉ€ˆ‡b3*àF=l¦Å%S´,†ß"»³¿1ØÁjœ´:䦯§?Ó— qã”ÃÐ!ÔòÃËEãÌ»äÛî~¡%:b~°w^q ´ ’C¤`„—¶ÛjCÓQæv‰¯ÉÇ}ù8£öx†áúÐêØÏ:&2øTÉ0¥}¼X™M¥J ·v^â•…áY¡õ9²Zÿg¹ªÈ÷Qw<ÌÔ]DÁº/qÅþ“ù¶ÛP~[¶n:cr-Í,UU™Þ–› DÁüY!>¿rí}:œèÀ?i¥ý4)*”c¸P¥ÖÌeÑݺÄCšys@°1ñ¨"6L'¥¿1iƒE]‘¬âvÊ®Þ÷¡Œ àîvjK⟷WžÕƒÍ7$²ç«™~ÈÿÞ5¦¯S‹JH„­B(ò$†™B.ƒô¡U„Qµ@*¤›á¡QaÅ Ö‚°Çu*¡Hä‘Jm7\Ã$DdlŸ7RTÎÄÎ"F¤k˜ž/R®ÍÓñkŒÞÑO‘žÚ„Ü@$¯®½kjNí^:¨C ÕS‡ë£YÞÅÚ~Ãð‹sJO²od…yPß4áª{f¶Åï“3Ù+8ö•6·A¥?ì`¶&`INùµ7t[V*¾µì…¨ý{Vµ¸*ˆŽI#•túª=Wõ²°6ãÄkâNZ°}dü&›¥Ä¸"r'mÆ >JÏ?@TFNêì„~CãøZªÁðÚR;Ü–(^R¶šªNŸ$ë‰& 7¾IÚ=¡$ïàÖÆÆÇÖNÓ˜õ‚¾øëê#É÷¢Æ¨˜*òsž`by™ÁÄm¼”\Pwcš›Fã).¶¶z>Á‘¨†™ oRùŠ åΔÆ—›:ì‡Á&›É1ûÔÌåñS»„Ê! Ô™×íTMýù:.êŒ:«“BxøÀ óØÞ!á<›âòsõp¹nŒòU9_²W2uÊ(i¸(a™ÐFCT—«lV›{±` Ä⊆'d›}]ˆ¿9ú¢B5”A©®°¬dP¸WLÈÙ¾tIf;•gƒjC$ÇݸHóR›ˆÁ¢%ê–šiÍ‚¡á¥z3uŒçÀç‚Ì\4w8îô04–)QBYç RehcÓ`à–û¢®}‚‘?“D9Ï5s#"C&F Bž2ì%®kT,š6û¶N´yʽxÁɃoøóXFÞ.h¤Ê_ðšÒBYKWœ­¨=¬~J…½œ÷ÔÙì½%í*ŠÆð&#‚×”â O9Ud]aX–5¨TS£ï“c‚0¼Iλݷ˜FòëFŽâ´ ço,Š+v¥Xဒ}‰©<ä±agùM^o^¦Ñƒ6ËáÚA×uZ.î[àbrJ½"‚Ÿ4’§Û*wžþH‰qaÅöúZÿ±÷~¡Â“0᳸àá-ýS›eGLÞ3×8«J ûú=?<â†ô$ä]ºÓåuJìÞ§fÝõÚÕ*mÁÂ_žôLJ{µ¶]•›`å©`´v ŽÑžÂØcÚ˜·8~Cgç¨L~B¨ñý¸)ðUÕ_KfhnYûæKæzÊž‚~šÑéo VÃioÓíhsùˆÆÂÔüÒ:'–ÌgÂiƒÃ¼ç2ÄvÁ|„j ®e´’„‡W:A”ùú¨;/OÚp«ãØqý“¦S,>RcLí?f ˆ*råôJ Íÿêa}Ëׂ?7<;Ó®w¹øлBԺꜤ³³mÚCí.:ƒ]æÔ'·¯É›äÎT2à˜R«J&Dàq P:Â%.VŒçmŽ‘¡æØ®tP\«‘tˆýõÌW[mºø[½JÉÑYíJÐ${˜¢+1'rå'By¦Ž/Øå-O¹~ìŽhI- ç´½ãôE­ö¶+ÒžCN‹ÛáöºU+æœ}Uq#åö󺂃‡K£.ýMd’…}-¡€0lëÔkâœv±\.y+¿6‡e$>YY0*õS TïŒk×uÊ k†o%ú'®b‡†cÏ -J°0·J²Ø‡¶[×KL>N¿ŸøhÁý*1g#IìÇ1‘g7,¢3jÙòÊY>Ytjo¥O°DUŸ·°Ú’~gwC°´”$’·Q¡Æ™ Ý· D=ª;ЃtÒ·•-¾±¤Cfú݇FšE #7J|¡¢Í‡c½âÛé§½‹;ªÇg¬w>¤ÉÍŸi}µÀ*Nw>¤‡ó€xõ%Œª[F;t³ì8ä…§¢Å½™¯‘m¿).Çk‡±‰W-¼©-|U">†ã¦Ú5Áè€%ºqÀ)¶³¼9×Ö-^&ñ=G©—Ý&x¸Ð^´5‘Ƚåa]·‚º_zÛOÍ\OÂÏê+ÀÊS}ÍýÙ²‚XÃéAØ›ç‡løÙˆB˜kè:€]š+V;=Ý_:Ø ìæ8ÙÜ5õnë,ximù¤¯E†Ž§rd;õ¸Îƒûs„f õY”Ç1ïï8vXM•ÄÜX>†*Ä´¸Ï¤2n¨ˆG”rac"N»;Î…,¶"Ž×4Fîg©Ui•(Ú’¢Â¸‘:X .kè4&±·cÃÞ½pu/!L²êCz_ùˆpÜ µ]r‡ÜŒíKõ¥bö…»˜ã·¢¤ßAã<ïx$Ræ¤ì#2ÿÀûe®(àúƈ8@> )+cÊyéÀD¢};¿¨8†ÒãyŠSnÞÒéÓ2ç÷¿¥fOÔYdµÕÓ?>"Pïðaöé &sÚ½…\jPXNóàXâ—ÆÎ)ì£ôöaóHØò2òuf%ÐÑŒ#£,•Pk`Aã?iEbj:¼ƒt2 tD…i+D=⥯ÝõQ`–™4 ±EÂ锣 Ô?ˆkñgR6kö¡ ÃõiziÞ]™5«.M˜¹N œ®·x,õi’ûC6°SjŸ¡&2$›¯¼önöÌ–i\¤îŽ·è²ìµR,2¤÷™Nˆ¸FÊ"&í×,ùØbdl@ûS¢9µ´12è»Zk¨_Ô}l,5Eè âƒøƒe;7lqûN rÐKKµÁw;yÇ0„{¢Þ²ŒPÊ¿6 ¼á#Ö^dÈîp1$ŒÌíwäné—êÿÈ«XÖ‘= ._þ!çét.%RâÐÙ@ÀKI5èZ³j=N`‘±+±OöDjî Ýl1ÚFôÂÓºÂljZcÓt ä+¯Ö̤VÑïJe¨GkjÚù%«¦F*ÏÛ2-Æ“myÏ¡°êlM'ƒÖÆb/BÚ»í›-qɔ̆‡¬ísu¯“éØŒ‰ãcTô†…ê]“·yÏà “¯²×Û´ÛxªèÀi½‡–ÿiÀ½ž§<édEcÕ<îc±+DÀô{Ø+~º•6#%lü¼×›pŽð÷Á'teó^}Ö–—ܸaayÚ£n‘–L-­õ‚$À´oã/hí¼^qNJ²°{°ÅjÝönÚøíºæ¢üö¹{t|Ú’Çœ¬“3l-¾<Âýé¬xVן21:·½˜žYlmÆf^l0ZI¹kmV¹nÀ'±˜œ/­8\D,7jP¬ÄÍË€´ô´Ž™ «°X£¬ ˜m1|× ¡Å¾Ùã ÖlÃ;Ëó뎹&»ç'ª)SN}c_=˜…’48nôž¾.É€ž:¢ÐÐQŽp û—B/}w¶¹…n:¦3*©^ÝŠm!ÒÅÆ\AÍÌÄèûFG§Ž<Û°-MºÓ†¡¸t¥¤W8%pŒéYM~¤B¯«-Bû;Q´ÕÎì-‚³>Y@»–fÁ»½-ò±RtRæƒÜ•êd´ìbq*½p2À7Þ±‰ô‰hâq²;¿eM夋¬v89ySÄG:<‡ y0a4 Ï…¼>Ž€³óì'èaO9w=gËx )Õ¬_µà¦œ„³¼ùt].KŽÐpôÄ!ãCþ>ǃ‚Cýeላ²9mÛëÝÙW –Q´*"&Ë ~ _ÓôíÃ2àCm”@l¾'nË^ÕŽqßXQBº¨“ž9þ}®ÐÂñÀ³(6ŽâT-8¶Î gЙQ7t’GL‘uÆ1Ÿ@a½+ØkÆEøºC¹”!Úï™”…#bHÇØ³­#)‘ðSOÿßQWt:áL'O!5?Žù8{¶¶ISàýò\'•‡@ýQ0¾E`è_©­›¹“Ê丑rë w…q6”\zØÞí&[!¤Û‹ÁçɃÀYË‚×"yš¢Á¶azY­FpñÜoµK‘“wÕvHœ1 J•Œ”-fo"ž=Xß¾*Œ%kÊWãhÌ)ƒ"öýUŠ'¡2½ë|YCÇÄ3 Õ‡¢R·­ÎÓŸÆ7ΰK¿ÑëÎz¼í ø]p„(ÅüI°à›ÿuþÊCs¢kÙ&‚tººpèÞ´2y˜q¶|PWŠ 'MSÈ÷ꛊF_̧â€Þ­dkÛ|ÚvëÛÊO/íõ¬G0Ö-´xÑWM2g¤<ÂbŸ=aJjý-Ým¢'ý=ƒ€Íˆß]kCD¥9ÅbG\^¸Ýsöå}xL©‘ÀWØ 6@ƒ‚¡p*k•ãÙùIÔ€Û©<ù{"Χ-0D?:!¿ &kÐæù§[öJ‘¦sƒð©µ$õBŽ)=[9 ÿ³‰ç©š¿òÅ´K›íŠÆíŽ0Z·z²x¢7«¹ÉÑU 3ƒÚn_%äY亸° Ò'Å=øáÄ€å9ï×ýTZh |±a}h±êE•cÒˆ¾‘åÚPš³ß3šm P-›äSÌúäûÈ ¶±åTšô!Ïïim¯±b–xìKXíqúžÅ‹:س9‚=2‹±ÓÑ€¯1yßLå ?v²beôR+î5¼Ý ‚Û¼ã®9÷·¾ÔÅÛþ“Eë´Ú rY'&ݦ/Ws‚úCÌÊrã0Z! )Ÿ!R‹!,º,81/ÔvƒÅâámÔ»­ëÒøøíÂúm£€aç¾:ÿ·Î/ «ŸÞ/ÃWÔ ɶǧGÞ±Ö+£ImïÑ{HÑJöÓadéˆ(öøÀÃfñê©8×9¤íBG#§áøJ;ž àa.Ýþ´d¥Ì§.Dz£¼cÛ¥¸ß†d‡:ÓÛzJDûs¾Å0‹–ö%÷᪚q_EjcõÚ¬Ô垥 lJvç5¿¶{UÈ¿úßÈ •¥µÌø¸Òv4êÓ—Q|0ó÷ÚYD"ºT¶ï‘[´gšõo&Àr?à²,.ê§:' 8Û›T8?bñ¢ŸÏp ñSQ¸æ7ÅѺ²=!h‹ðÊ£Àj"&ÄOÔt({pAgG†L»&Mûè`8õh•;Aú9 C¢M‰ŸW_ž`dÀ®‹ÁH¾€çCЂiRBHqúáäRqë;Ÿý­²üŠTᣊN2$N~ɰDŠ«Ç>d·9×'ÏèÔXóIä_Æ QÌÚp»&Úæò2Yoæ%œÉó>$°Ãí³XùÚÄI\¦½zå%k’’šhÝ„ÅÍ^¹’ Qü)êrÞ8€7N > ´‚Ÿ£ùTÉë&aEþIô w1n}^ûCõEª§îN¨`ðÑsÖ #Á0¡ÍÜÅžžG½ñ¸ýNÍÏs%å±où{¶œüvª?E8EmG«iµÐÜ×N…±Ð2lœ¥¡Ùò¬ôVªíG—Úl†ëׯW%#ûÙ1©Ú©›ö£†Frð‘kݧƒDæÐwå°ð¤¸ÀÜAÑÊ4&(§ &çP!N~tòf‘O^+»~Á rÎÒÇt'ŒñÈs¾¸±ºB}N“? ì£cª=?õÔrüRµ*‡Ø÷çt1 ѵ~´F•µÍOþðë¦C¢ÆÙïºNrmývƒ¤¹Z…µÞ™«ãu*I¤…Ò倨”tÅd°b‚ßT“äÁÎaïW¡«I¦]Ucì~ttÜ+WÝõ‘¨#/*⬦‹TæÏé%pœHÄFùÜöÌ*åKÜ->i…{ñ@RÚ%VÙåž9ÅZ' m§u4Ìnƒg»_¥þó±[I†59]­=¿‚ÚÊF¶2«ù,ëj&L¼ dG;²éà†Dm)¦Ë_xnÁ'ÿ®Ãxð–z‹•¬/:ØnWÜe?+ : ª1ñcй³?׈A#sX7ÛêgÅⵯL#ø’Æì“ÒS¥øµ'–<$[m” /W(›šëÉÔ?`:n™gÑȧ´É2XoWPlcH~ù œmH²Ì©ÏkKpщvEàeN©Ñ’çƒixr…m[tÝG°Ëã|c#î ×';j4'Št.f^»p†Ö/¼ûÉDXVì¶\ó»š>à/*ýˆÏ²É}?²UóÈjUoû2DŒÕlRÙJ‰¦¤.†ö%g¼CUÂFy˜.C2ÌTL)/ D¸DïÕÅÎp\ÓÝQ–Ÿá#󞮸[ß–¦:ÂÕæeÓØ8Zî‰Ä¹é­†«yJÛùζûOgZ…‡í€]Í0H¤¯ž»‡iûF žª @ 3Çmçs;è ê3âá£8þ|\8©›¤F<ÿò„WÓÃZÐR¸ø]§áæ8Þ¤Jû{÷=‰ö) D!>„ƒþ%\uШ/VDç'ãä† B‘‡ëÒ²‹ŠžïBˆ.¼t3Çz!‘²cúy•PÝ-ó›XAnÇ1“_ø&yF?,·ÊOÚë-WCÊ#ÿ]ÓõFy_Ž^ˆ¶qNŽL+þ“Þö ‡dô_àƒàךùöŽf§3øyéü³4Ëy_+$·ä9ëƒv ‘ìKa{ööWXãÔ6Gr¿/ùЍªÇ ow%çH:b¹Ë'X¤7›s{3¾„MPšmfùäñ?"n7.}Ž MŽ>7øÎdz` NŠ3ó­i§“?Zé¥Ú[>Óà’N Dc‰h®KK³q/}~y]øE½w[!¤…>”ªÒÂõ b/’Ö/rËÊ º_9†Ï0úfê‡o¼RŽËv{QOЇr›"ÿ¢Ð܆Ǟ›ò¹òJ>\„Û5_ªcN°v>L¦>òPàóÃÞ²¦] d¤B¦’%ª5bòï"bªü±}*ä'ÆÛ¢î-ÔŸWdò³ó•øŒfLxÈ¡²K¯éßý›Dë'ì§&€©7‹P±ôù/8ÇÐÙÎÈv.˜m2-Ù¿n¬£$2ë È» @£•wG<¹s æJˆY4±Ï®] r•+š?6ý)™å2;?Æ>‡˜*¤@޹kâ1Å»ÅÈF­-¤-éô›³JxN›Ýš”Ö¢¨ß¹£)å,‡g¯k ù‡?†–5pÁ@yS } K(|²´BaŒN­Ñ=ÛbˆÞ‹7‘Ø¥–{¯·i.R±*RP4µÈÀ pcö^äÁÈ€ùA›wwQËë‚&Þ$2<_ŠÁ«p*¾èìH,Éò6åW,Ú÷<¨Õu¦»±Uâ‹<:Y ÖÀs)Í­o¦ëYýÏ >ͪ¢âÁ^‡nØ›UàÇ^]¢%û’V™Øk¿eª«w&nì#K5Ô$ªJ$ˆÕ]/ Wbuj¥íO;GŸâÞ‰Boß©qy.]mÌ¥³‰üP`oŸzã¢rÝæ‹3'xÇ@ŠŠ`° îýVjÙ.0j‡*m½Å‹zà47­Z®ê´OqW‰F¯õ{>yhf¥EaÛ‹3b´éW¬ªÕüVûU°8-äf3ÕÇ‹XA³ˆ ÅÂZOO2-„r:ª¨Xf5ÈO•–Ñ Y/4„¿Æ“ΰž|öšºÒR¨°!·gNŸ0ÜÌ^ξ68nNÚ¢ó Y™Ü"?Kœ$‘¦o_ªº²1±ô—ÓZŽ/-Ú ¢÷-²:¸±$½Ã°jD”¿¼l3¾ žé¿†}²’Ï’µÿ~õm¾uíêñ©,ò¢¤#^ìó7t’ö:cªe¸%ê ýÁwüzahR¹þßœçÕ›kd»¼Ÿ„¡?œ\ÁÖ¶€¨ö0v¼‘ØÃå‰ù]dþ‘ô.8DCÖí‹ÖÙCiÞAò‘=÷Ií—‘ÐK˜‘ƒ8;aL‘Ç­TËBÉ~¸¢·_ƒý[ÖÉD7ã¦ÒZxè?^b9uGé‚_Aï—"†|¿YEWßè_‘x XÖª(ÒdsTùà#¿÷n8Ð&y×ð"¿Iåa;Ô "gõcfª ©`¿¾F²ÉÄM¯”Ù;øä)OUZºâÝ=¤™¡ƒîSîƒÉW ÁXäúQ¥ŽÁY Ïý¤Ju˜'Ã|êÔÁÚ¾âaü«°Ÿ71¼5Ééð#â×/&+®:ñ•O}CŸñÇãP(¾~uû¾:Ó'FÕ`ŒµÁâ¶u‡Mkøm%’]WûÃÍrÊ-4fFŒë£®¾:›A{3¦‚¹ÇÔ˜Y·d· •l¹gòq%ýXè¿~áÏŸó¸&·š73|×"®q…Clèm%%és±2vÚ~%Å|ù0ô í`×áBàkáíªlã(K‰Ÿp†öºÅûÜ)úÛöCµÌ:µYú×´Š¿F‰aN6 ´¦Ú»D†g½½7͇Ԏ[ èìuìµj‹p®[  ?–æÉS¨ª—AAÜ;U%Yø`LzèáÃhùÞŠ„?¨ó ¯ßc·ÎʕР[ç_Ps­f°éi|£°eÜ€@¹ÿþ‚uPQhØÝ„¬cÄ·ƒ·ï§É2ŒŠÃj)¸9mr š/ö0ÕÎÀn4S~sG˽Ó[:QæÀ¡bÍúèѦÎ&.‹ŠÓ‡\Ì#Ÿ¤Ëõù; Z8$Ëâ˜1f%EœLvæÿ ¨/iBs©"ÿe½«ˆ;¯‰À`4¾ØGëê¤Vî…|á ¾}1Pcܺƒ°ûÒzŠg‘ÊJS=Ž8uá´~ÈÚ0ùþG•â¹.óºUN 6kí®3àøÞ„úð›ºÀÓâæc–úçì*Áaá`öa¾à1|ŽŠ¸U¢˜½Mê±Gfy’óá4Âþ^íÕÃP>èÏåø¢Î¡lŠTÊä±lÄÇéqbRwÅÌ®Ð¤Š³™G„¿FN[÷ž0†”×¼zz²®7îQX€_¿û>É?;ÏßĬaFS·À–†À@ˆÊ »R i ÅG>VÅÈÅ ‰ÎQný$5µÌœÇˆrùE†G€&EøÕ:ßcôðæL9¶ ÒHIjiÚ€?˜5D?Ùæ„ož¥D_ð„Èåê9ôÑÁûn0Y+›/uÏ­µL«2üü‰1£zõ2Ý‘òƒ¿þà‹ºß yhª„†Áà>:xסý²Æ…¾޽zñAîV‹K 3C´üæàïïýXG g59&èIpP‘b±¿›È$uQ˜ñªšî¬ôÍù´Áý]ZNUµqÿ´Å†³«p4z=B2–\Ì"ó°II9Üoç¨üZfé´ˆ‡Ô×±ŠÔMætÞŸºæØ§G˜ìh"|‰ÇßÜÉŒz¬FÈ¿ÐüИꌄ6{yˈµéßÙU]œk¿Ù ~ÊðıMñm†À˜@ŠÀåyákÒù¢íŸÌ›UXfŸ£6§4ÑSÉZâ½pµV«Eˆn­éP_'Ъœ`•¯¦oÑbHªšRê­SZ!Zˆm>%Ñ©ø/œ·®×›B£c°É$ÔHý–+ñ‘}º·Ç?/~Âø„­ù¶ªÕx5<ºxé¬b[W]áaD•“)סn¥}ú½V×H2èœUH‡™‚‘”Ž$º&D¼}Œ8+Òlpfž0(Žú=3"±u~VtéƒÏ¡h%¹*œ,cÎ3*@±˜Š3J| ³ÏØí•Û»c!$ÃöX!*ˆŠ÷mø.'Óº2rrÿ>aåØLñcÓž`ëÁl êâ¤jçvcéæb¾æ— –Óœá#Ì6¨+AÁyœEð*~ó¸ñÎ_Å9¯A¾—.Ú‰×t× üLõ–˪oÓˆ®r¤&â%­*¾W2t+jžDϼ*O îjíU§ Œö71¿G³ãžJEX.9]®•³92Tç¼§¯£Ò=h^àÌê· a’iBS1CßG n¹);j€[å.}åÜû€]ÝîÈRåf1OS«W…5»“åîD_I‚§ã”×3§Z„°\pt²\¬Bòm°c çÕ Ñ •®ƒL±ÿé›*ŸQèõ$T9áEH Ñ |ÃWáƒß> endobj 678 0 obj << /Length1 2253 /Length2 14744 /Length3 0 /Length 15969 /Filter /FlateDecode >> stream xÚ­·eX\Ͷ5Š»»Ó8ÁÝÝÝ5¸4îNpw Áƒ»»»»»‡  ’Ü~÷>g'û|ïÓý£Ç¬YsŒ³ªÖj*2uFQsGS ”£ƒ#++@\QCƒ•ÀÊÄÂ"†@E%î4q³vt0qòXyyÙ¢N.6.+ è‹@wtòv±¶´rЊø'‰ jt±63q(š¸YíA5ÌLìêŽfÖ@7o&€¨@ퟮ5 +ÐÅh΄ÀÊ 0·6s˜-­˜ÿÑ$ë`áàþwØÜÝé‡<€.® QÚÉü‰4wt°ó˜-˜•Al@–ÿ?dýßâRîvvJ&öÿ”ÿ—Sÿϸ‰½µ÷ÿd8Ú;¹»]ŠŽæ@‡ÿ›ª ü·8E ¹µ»ýÿ•u3±³6u°´Xþ²v•²öš«X»™YÜ\Üÿ Ìÿ¯sÿRÀ,*®¡¬)Aÿ?MýנЉµƒ›†·Óªþ“ý/Ìúƒìq±öè±€üe%‚>ÿûËàÿI:˜9š[;XØ8¹&..&Þ íBœV€µƒ9Ð ô ffrptM€<ñX8º üÓQ.NÊBÿF\f±?ˆÀ,þñ˜%þ ^³ä7 €Yêb0KÿAlf™?ˆÀ,ûq˜åþ ù?¤EáiQüƒ@Z”þ åÿ •?Ä®öØÕÿ »Æb×üƒ@ìZˆ]û±ëüA vÝÿ ^ûÇ?4Ïä?ˆ4ÏÄÞ txL@{æ?9 &®fÖÖfÖ.fîöÿ‰³‚ù¿ܬíÌÿ‰s°ýmkkWÛ?íø§ˆÛŸš &Ó?4ÃÔÄÌÖÕÎÄÕê¯úÿ„]þ €Ü1u11Ú-Üþ sþOøß‡ù?UYÿ¶ºýW>/ûâÿgÈ(³ÿ ND3G;Ð-òŸ…qü±·ÿc+ ÈÍ?N±ƒ 1w´³û[3èP0ÿñt˜ÿEÊõϸ³;è–ùO>а3ùËjCª€2,¬=þ*ûϰ£ûß´ Ë?$ qËnjàß) åüq›d¢•·“ÐᯠPÌú/oóíÛ¿ ȯ?‹àctuýkäî_+]7̨8Aµ¬þ¬ˆDíànoúÏEnù—$Ð3€ÙñhPMÇ¿f±²‚êôgÄádâtø¯þs°þOô¿»Ï’Úúf@‡¿R¹þ³vüÓc±Nvî-ŒqþS䪳»£ÐÜô¯–òþOð¿)YYAÉu„´è?…9A“\öÖÿ½ 9ÿÉzüÕ&NPWÐeü… …üŸ“Ä ZÇZNnV.À¿öÈ(7OÇ¿&€j¸ÿ9 NwÐEíâjæèò·Û –{üA‚=ÿ:– ¢^A«÷_Ô©O4ƒ*}ºü[Áÿû°sôòaä0²ö7;+èeñû¯43wPGÝþõ"zàý/¶°=@/ ÂúŠ£¨MzKx¹¿dÑ\4¸˜ek¢Rcßb7bÈZ¸]É„¼3ÝNƒÎKe&Ê ô ©ç¡kt—¯ê´ÔMsbÆò¯㓬Oí„:wYŠÞÇNäÏ!¨-K—œàÊ ;“å)ºÅÃ_nG. Th%4¾Án‘õëy4õg‡rqëHeÙiF„5P³“©¡e8—GrDl{¢¥$CmφøÛDÀµÑo~wìrÇx)‚ËÿüËì§LL0›XîZë¬`D#>϶¾„åÏíXXcI/3•ivMfMÌR‡ÃzçóFïܾzG}¿7ØÒÛ¼)Ý4þ·QZØ9^Wí+ØJ)d5¨ >ÉÖ*E4[WÈê™0¶RÉÜálå+ }ÈÇâtš²&ôO¿‰ågBHšÑZÂpÓæz¬ƒ[-“{ UÛ’Ÿï$ú•.Q>úÊ Q$ÿ ïÓþ…QËþÐ{ž÷}6KqåÒ©p¨ÿèž¶à‚ꈓê•§ÏŸvŠóË©˜­Ÿè¹ Rè¶zêWÈŠ3¸ý1Fž¼y:²SëLïÜÊòi¦”OxKødôŠ9–uì¯Ä.¯üh {UqýùSC°ÕÃrÇL¯.|n'ŽuA8$ñ¤cïAåŸoÞ“èy$z=卿€ú93[¨·)Äkäe{‹[ûJIZòÉó[¡³ó2Þ‡¾uº€v¯~/èMf9¿×¯Ž+µáN\Êà; ¯µ@?«Á|VŒ$m®™ÊŠ˜¯}UT´!Ö²ÝQ¤•7§ÖY‡WaMÑ“ä乨¦ì™ã‚ßÖ9]å66>a™ö£/É- éiÏ5¿!ÊàŽØÈ7ãß–Q°v°(—yó2íuõí—¸5¼ñ âBà­RJŽV ໑~ýåÛkL…0E#)ß —>!Ÿ˜òÕÂ%5BíJÞÐ{?ÜØCÛ0ü6÷%Ï#ìîÂ죧ZD# ÀzGIQãÛ» z¡}©ƒ3 ™+d"Ë,íZû¿fZy=û·uò9göEóh¹ïÆEuc÷ÜÙÅÜôßÎe+:Ük®‡·÷×z­dÉh0+Û‰5¦‚ÒÙ˜*]ö©<Ç6\Ì¡oŽfzzˆ2î 0pBÉÝ{æàCt j±ÑÆ<43=·ãÈ}ëýy ~™Ý5u]b ޝG,¡¢ 9#cô}‰´ÀPßÊàÞ¦,LìElöüð´ŒÊF⨟i8…æáñ‚Æ/ؘK4bÍøâ÷Og3lÈ\ªjgȆ-”ÅÒ↠fnz$í*zöqîš@Œ˜ÌðƒFåü{ÓG—ë}ãâšÌ½=cAŸ³$!¶Õ×âoÛm}½1à3x œI¢­YöíšÛîvñgƒèŠuì, î,u&“ÚuÅ8£[ó@hÀ‚cõ ¢V¾ïÆýr{PŒX{ ¼åT:v$qcþàÆ†ü™‹Ñ=Sàñšöâ`ïkµÙꬩœc¾Ùƒ!רõŠ](™¬ô:ÝØµ½iS¯±ñ-:AÄÇ3î9Jéh×L¹S7‰ûx«Lc >Y rc ú¶w§x~`¢O5œýh9Šô8š{ ZoͶ"ó¤Ea¸;ƽPgèjQëÆk ÛR‹Ö2å¶LûáË;­UÐ4´†Å#ÒݪÕ=~aý;ºýAç|ßQЪÿ^oDº·”!Šº±A×TÇÔ`ä'…²ÒãųÆ5E¢å¸MØæ"ÊáRµ"OáN1Î…ƒ—#­Ñg‹íâºd¦™ÑNŒ†s‡×®}úΰEüʳˆËy~ÚÙe¤†ûG:[¥àÒ³P[¤œ¸¶3SjðÐ7i”‘¯7yå ¤Ipwé5ÍÃ&у;7|®8?Pâc1F%Kâ7%ˆñ»Ôº×ö/BËÉÒã¿R®¦û \Eyôwä54í~ z ÄcØï_Ä œ»tñ%>°[ØêüCLz±·Æ“”Š5ç[ ~øÊ†ò/€Î`˜TœŒz–ŠY:7žýeß‚"Á„¦=N‘ï®;$^iQ£w7”ûçó»qq1ßðe>Ì TÆãRµ¤ÜÔRÃÀß ”U1ÂëÊ÷bφ r44>Jun"ÛÁ‘2ɪ%;€›ªÈŸƒÝå„ÿ`;)<½ÝÜígЪe+•cràš(9øh³<.ñb¡ö$õÍ–éÄõjæ`åäºEUb‰Š+®¼(°Å@Þ’£¾¼óxàð†äv°B®e+/ô VÊRæm´‰hÅ'õú9RÛ É›”‘ŠQ;E§ˆåjös½ _¸è|(Ë[†¨Ôp¹F ©žK+†>BCÊ`3=^©Û pú v® Ñà‘½?b¶»}Êë v[òäæp9k?2°+’XâÞpÄÃPYÀw·«´ÝGïÑ„.¹PtÎ2P£v¿ƒGöÿ øc«ýØe» †a€2Ÿz`ããèŒlÀ·õAÆ?Sxð`–o¿ Ž››In!)hIÜ„9íc)èY a{bª«LLm—!É€m— J‹XçöC­BÚNW»?—€éN*Ê%'C}ÐØsOÞ§N*†·ì†™€’6IÌ¿|z»ÞÓ¾ÈzʹLÀ‘%·é§TŒ«ÙhØpþ°êÆ9o®ít`piçi¿‰¨ãq5 i‰Jlã)# Lz3’ÅÁžÆ)VÁæ¹çµÿ¡˜Q·8Yœm±+ÙÎê¡Ýf»fQ»-\´Œ…æãïæ¢ÙOz©Ö¯ ƒ0µé•p]Vëp§ðç^^ÇÙËv,)”éï;w8üƒÙ2»ŽŸGgoC­«Ó¢¼!êØ*z‡®5õ&TÜÏô<í-?4F›”Q)ë­Sò)-5Ta@äYVĨnµCRdÌUmf\Ý, šþRýB49ºB¯ïÚmFèª':u ·nf!\ÞI‰<gõ³ÍÊ=JE~ÜÆ’Û!ÍÙ¥ëÝ ­Ox.Y+dìjšy,—·ÖÆ'‹F¢"±åÊ÷.N(ž{ƒ´–þYŸX!mJäVB Ÿé ʇL 1‡×nß ¼by§–yFî"'ÐGœ9¹TÏ¡"³>y\ß[T×úAI¾1ò ÀÆ.P8ƒ Öè&Hûë©Xæe'^l€RÂlvpÌ7ʵ¹úWa»Ï˹ÔOİ&3(–ÝwO÷³}cQð"íã<2ôm¦\˜ìðŒ¿0l”i™›®¾ÿN¿OUT§íSÙiž|ZüÊïì8«…;¾”Êl>‘Ž(²êî KYYl/ÒÿÉ%Q“²C“¬æµL(ðÛæá¤è+|¹Ê^BCÂ$a oõ ·ZI¦â•Ý×üÁ*/;ýû@Õ)¿å³ ½hŽPJÆ‚,i}1+R­u¥³|?›•ä`É6ÁBÂÝò:)ù|·¢\ßwM8˜©··«iýTí˜ë¬èê7#MòÁ N¢l%išƒäÍÐ 2_à£l8”Ðõ61G\¬ª_ Öá‚ÄÛpRw+Æ$bKIÒ3îü˜ÚH ¯¿^)fgPqšý¼™Å>)ÍÆ¯|-”T×mQÞãï¤uv¢ ûåþéùÔcÓ^™+c‰WÊa—Š1s¬2zÙ‰b´±_õŸ‹Í K- ¦ö Eg8È;jDð¥‹Æ†e^=¢ Σ=M— FÔ öEHisqÂÀ%¿5<Þ3Šg* |ÔgF'^E¸ A¤¿ó¦)xÖ#žÛqÚ ²#¹³—óV·9Ëð:%´mÝdûűöûÓÓ^r=®nP4†Y)eZ)h²£õ’EÙ“ŒLd•ÿàâgPج´ÛÖM@Áöæ/Þ¼0´ÀKÏlÆ-ɃSÕ“ãžÛ|ïnkõ(æÔ•qžRnŸcÃÖ¯ — 4£ý-kGõ_ž1)ÑëÚB4¾&„&£0•ö}CÞÀ…q·ÎlvÒˆfªª²Ê… |ãN©éi5JíqQp?rFa¨24ì^$üU=·Ýr“×]ëõiCø#‹Ôæ æ7ÿ4Ü.&AþxßW,þ”Y–];ªXÁ-ž[Ýì"‹9¹ÞA»ùúèòÔWú³ †9«›øòúá¨(Ú¾&*wúBaYmwcç´êÉi3…›©à¢¦ÐsvùTLÒ vVmªjÌrâ3úá%6ïF¦A’)`ø©àÕæ|¸°p#98ñ^A¼(8ׯ6)˜Nᢛ“ÙžT‡ª×•üJöT†ñF%2í5®–ÎV:8v²*-ß¿|ÜeT•Q(c7¼¢àýåxùœËåýcrjl«RÛÂõ#^Öñ¸Š2ûüÅ0a9S¿9IÓ´vwyúÔ‡ù.× 6ª s…e]o¡ÂgiŒw)¶³ö¡\?ï ‰«—¶Cᬠúˆ± ôKµ¦ýÞWÍñÍlq~xªGí\çN44^€~\Ç]xàÁäjW¢­Ïá̕Љ¦¼‹¾Ïx<Ôš;¼ãácn§ž ütϨšÊœ5³a"ù넦Öhã̆$:Ndp5˜Ãôt²øf»ãú*ë©â-müåoÎ Ž†H.«á}T¬Ê®vBbçÐnøh–ŒXÞnäµøwñŠã/!ÔW}ãß–Ô†tÔUßäuÑBêð°]>Œû³€í~rÍß÷BÍâÐ<Ñ)l9uäQ5š² <ÇFÁq—u…Ÿw,¾¿ª“¤l€ƒÓ@´Û˜”\6 –{,T RåãqþéÙ—eWWª¼|½~±´c:›MÈPpÁk%¡'=Q&Ç¡®¬žðÕd) Ow5¯U sæ¼€JnFÙx·zi_ùE×—Á¤îgõ–¢+…?%üg!Tþã&WœyW‘æå¶ó¯—ú* à?J–ÌoÔ;LPV`Hw R#zTK¸óHv»°¿ÈÍvŠ›aûÄÓœ*ðæ…ùû’Ø~E”›”é©"¹tÓÅ.R×_èPRÃßÈjê"ò­†•nÉS ÓÿÐWïü4„F&áä¢×QäG›ŒåEÓM¼YƒªóµÅWÛAó}̳øŠ oÞËûÛmæž’Q^I$Ú›s~©ï4†y]ìLè6) ~?OÊsžû)xj-ô̱.¤Ô-²CH¼…iÕ©nqq-# .B3>˜5^ùæy„ŠÚ¥8²ºO+&Zt«ŸÍïÆBkã *ú¯ë޵Ll±k{‚øzôR}_²âó±›Û?4)9çgY««}ÉÑ¿EþL0Cçyl ìÐS\Ú€QµŠIUäfqÙ”žÑ¨YùžÎ‡’bêc&œ ^Uê}¦VwäǪãóclØ}5(X™èK›ß½âG{‹¾©&} ÛKîÕ­üÏ>ì ú–¼Åy¢.ïÇι‡Ì70r™ÐS¿ÓéLJv<¢BUyðÁnv‰HeDUá×_o‡1êh°6ï¾Ó:ËYbJãWg? )ÕÖŠQXyo†ËȘ896Ñý©Ðœ8Jë½7‹ôFÇšz• PÒÒ @°òš5þþ\LúÜHb¶°s£‘×,Û¶˜®òÇ{´L¢Y\E 9µƒmŠœœñ˵ ›…?¯‰Ñ’þÀ…ÃÜŒHFÔõ2}äüJý6g¶¥_ë0ª>ó˜¼']xöAèymçŽXééá7\+ˆ[¿í)—à–á-³ §æD9p®¥‘¨•<šgIµÙ òC ¿Ü…§ é~‚«üÚ;GsÑô¥+æóo3òO4¶¾ÝŠy®·óåÝ׊ \uu¿ôV#QRë;ªL·ü%LÕH7Åþ¨ø¡È´H¼ØÕÕÛÙJŒþ†ƒ× |c})ë+øú渺¦*CĹ~ˆ(YhkI“REÛˆ¦zaxýHeg#Zìœ 'åR,Ÿê Vª&gÏcÜõ–ö€d(×Ãâ*çb ¤Y‹3JQ–-S1ÔO”Šàû²Ùø_‚®¤k€ø·KV‘&ö;t>1·–JDàÄJ8›ÃzˆGòäèæR¨Y®ÃˆKBÉQFðĘZHa.ª‰õ©[4é8ÈëQÍ ­¨Š ó]´¾*žË/ó«¯ÿ‰ØP¹ ƒ­Ò??[ÀÄØΊqÛ1 Ù«¢ÿ½U”ñÆ`½r>֪ʆ¸†´Új®ƒ:ðî‚“„‚xÞ¤M–à6ßn'E7s‡¦›“ø;ÛçцÕöÒÑÑ è‰™’ýRN^š¾éë † Œ:”GÞIÖý¡“ª‰Ì÷Ж Ò+ø 3G'I]‰ŸøÞÇQµærîhH8» ©CìË:© &÷ Gh`ÕÃqókÜõt7V`¡Ö;ì­£XUå ©=¢ÁÄ<Ç£,RŽnDú0²ªh¡¬³˜ö©ó˜ ¶JO÷!o¤Á·“æÖàÙ˜h‰’æÉÙµôü”/ë‹øSy nù´JǪo1̾›ÅÝv*u¨“Ègk*¿GÐ…’ƒ”²f·Ç·=‹ù¼ûl=œŽ]G†#Ê ¾=œ:/Íqý¾û‚¥ÁãòÒÊ’¬»þîÐ} Œ6qO™~<ˆéåzÝNü`É”"w‡(Þ´t•j1øaÇMcY Ⳝb\žÊÈuÉ—VïN ÍC>7#å±êNV-!{XtnÂH½ÀóXiBNM H^ìû¤¡LÛtíãF>°Ÿßp{É  ª‘:‹`à¹ô.V‰ ¡¨¡½ÐÁi1©?ì{~ò÷S½ O½…_‚m@ÓG ˜ˆ>*-ø•_#¼q$xp £Îl&U\¡ùÅh#õùˆj|l˜îцZèsLÄ- N9Šx凟dÝ©?Ç~R±ªb šÕòP…Æv÷ͤfÅ·È<¬ïîØú©»ƒ Ï¼sDÄÓaÉ*ËÓ•ª!Y‡¶kߊ¸ºöñ®npL-ŒæÄ«‹ ç{èÚ{^4Û¸~®YdzèÝ 5šóGa¹¸'8›p³¬ñ­8ÓvØ5nJ2+>•I£÷)Š2aMŠX(¸P3O´žÓ¢”ýaÈÖÒÐA‰o’xí%Û.06˜Ü-U&Ž’Q'…2X2P< Ø{[èÇérüÏŸfñÕ ü…ØÄ«ƒd–œýî8ˆJ'¦Š±¹ „‚hÙhÄѾq@¶h/”,%ñ‡ Ž©,‡0„¢0?HRB¶—luË;ú¸fDÔM?ñÂ8•ÝóÂNkŽ–j÷´ÁH¼Â:µêˆ4‹MU¯u~ûÛÊÕþ"\žæ÷·U.Ï燅ߓÞkï8’ˆD&šRW‹ì>Y…7‡fêÿ"×™Q5‘†!ÑÝÿp§?iÀ£I‘X=нÝ៲¹\„å˜.-&šÍl"ƒuÀ70wòäÙï#I›¡ª»K©{a#Í¥ÔAqQ ³ZA¼˜¸'MÚó@öeÜ£äÔˆóŠZ²)`ÿ>Uà(…,¹ Õç*Ѓ€s…oùþ•Õ¢¬¡“¹*D¢ê{ "ö¼›ç'ÊËG$ŒøŽ˜Š;ÝîÁ2É誴YAÞ™O:¯kþ…z.ítUÄ.¹®î+Öw‡B†`Ëõ0uæ…ìÀoéG}o|'³Ü[”Ãê}¤$—¶Z¶*bîšU¬+ýÓµÁ6Îß¶^¥5ÇÜæ4Ñf;Ë QmÈ"cß s¶è,žIl'¼Ò] 31YF ǘK9M¯b)ÁAWFæVIë« 1”Yw À]ó·†þ¥ª€@-û¢¢œÓæ¬öVTÔ‡Óõâ•«šS[g˜j—êËê ýëeß)ÂÓ]gŒ]ŽÄ˜|…RBîbp?¬_sS”³åc4© jà™5£M«p'OÜØ¨ŒÝ eئ“«;Æ'R×¢@õQ©žª¯}KÿoîÉØ¬ê‘í#enÏükÌ­œötBC‰µ_äçG‡ð°†”ï1½ˆÆÎ/ÇGm·ù+Ö§bøÆí‘¿3('¾Èø u/4Ëý≒òpæÇ¼Ýù…\ŸÞ»Šú¹`ú®…øÂYvÞFE0Æ'TùRÙSZix“¬ŠHØd ÔHÏûnò8á‹TÉ÷ÃÂLé™¶”¨|(˜·] rù‡G'$--b¡ÒOq¾b&¦V&¦?Ðñ†­ø{„`Éñ ×lŒº‹¼ ~>ÎÁdíÄÈ–Z“lT¤’K`fOns4ÏÞÓU)9±º¢ºq9a>ÜæâÈ býتÿ‚î!¦"¨º‰‹:ªz¦¸Ì)­R8×îØÖæiuevõ™ Üê}ð«RÂì£9,Ô—'ƒOƒùgÜï ¡<°½G}Å ò,xE”V0ØùÙ^)KÎ× ³J+8ç´ݧ”ú]±Ë\ ÖãÜ1¢p£(™3W¤ (ip×N`)œì]*»†Ø'Ñd«\L!#2²§Éüˆ^NÚ‰jÇYÌs†­nTL%ß|zâ©Ôܼ_ïƒLtÆmy?Æjw¿©æ{ÒPëûšñR… o8â„h³k´=¿›9íçz[gš'gu;²7…6ÿðI ÇÇg‹ŸvˆnJ¢s*¿ÌJÐäé 1úóβ»-ŠM@ø¢iö‘$™Š®m>ý^´Ï®¼þAtŽ0Þ+r¿Löí¬§Fùý íôñƒþpº"U—~±âÐzrÇ×Öö=ÌݺäøÞÕkIñޔ¶_!sÛÂ}¯ nâfô7œdÝÈãßkñ‹+·#¥çÂzÛR_¼B Ë$ï¶&ÙÚÁmÖá6騛 ¿ËbDU´±L¼DóUJO@PðÌ.´PóÔýÚrì×ß&×dÍC(\PâYÛ*¡ƒÓ§é×vÊIñ\êŒN‰zÖ,“âò>ŽÏÁP1=_zS#>XíÙ4”FÁÓ} ¤D0„›ÚEÔÆìPð-:^žÀngç÷sµ¼øf9»{¥q=–OEÎ;]&Ï«„Y%Vˆ¬;œž<ÃÀ=¤jßálC7/ÂüŸÅŠúaûß5hhÉ‚Œûq§jߟ©©åÅÀ©¤…üN¬ò›òô…u1±’øçˆ£ø×QAÎ~é©fÖìܤanƒ|•Øéª#A~»æšKJšzÞºìôyç®P$Âöæž}¹z–À:#mª[ãÂ}¼TñSrÔç.l,"ð;±¶mÌX¹Ï0ïàkgS“‚«cŸ®LwˆÓØÞ0ž½¡y¢iC-TÀ´cú‘Þ‡.i”0HH#6¨™iϪÀu‘Mä¤ïVšG¿± ÚÊÄÊj£x⣻Шó[ü¬Β²lÑŽ§DjÏ,R)»ÌYǰT ^ò3 BË•?a®ù­ž“ÄƧ´kSŠ×á°Æâ…‘7Ee`CMÀ„êIþÈ`è_GÂ=qëîÝ‘¼©…ÍÑðFƒÙ6¾‹2\â-´; ±x¦ó šò;ËþV¨ç5yŒ¯~hü«ß‘C2¿ÝÝ3žizfÈ-”ÑEtà ÕÏšº‚ú4gËW$¾w¶¼.Û£t)èM(Ë78ÎÚšg¡Ìç‘/4Œof)7cÓ¹$œ™î'ù+Á¶\'œ“5‹B€_M%ìî‘Nð˜ñB Ékߢ’¦6õ É6ãZa#3[ïöb$õvVoî]ekkDHÉñÙE‰ôò[j }#ú|¼BX…õ,J9NDw`@dïv¬ê±]¦ö)ÃÙ]ü%á‰ÄÖˆƒª„(I®éîQ$«û5•2ÙzD§™Š+G× žÎB]/xu'ß³¨b|¥7Œë­ˆ»²ÏF#?^—»ƒ•]'M0àïeдÇ÷ª‘CÁ>ñ4Ãò7 Îfÿ2¥Yß{¯šÿ\·A+ßèÞþ•á‚i3Ú\\USµº®r¢í˜*¾U–²r÷!A®è%2ÒûÝúý0`XÏÓ^ê:ŒM8Wšãü›¦$YØ0WââèÕODDƒÛY½à}”•‡2‚ º^¼ÁŒÌ«ƒÓ]T~#·Vý¶–çýTTó® –ý¥r¹©—k§§Yáõg^Ï1M¹çP ßCk¤”Xлôˆª·Œ¤ë¾ër„¿«~㚯íðýp2.NÍC:ÛÒ‰xÉËð^G-}M¶ø|!]ÙÒ=á³W„rØ?!Ú8ó7¼©Þ[Á\UÖÞêÙ-]Vgò‰ß¥ºhj¸êàöÔ/ÖRX2µÂƒ§}Ù㣌VÌÛÝÓ_⸞Œ§P ”çÕGž­¸7Yjôÿ%Ì£Ž×«Sž'éæÕudÍYã…Ž{—Qç&'‚S™JõHü*¡`Ç—01V÷ …TŽç=³ ÃÀúcÉ\ÛÀÐÿ^ŠHá#Wh^ZObŒØò¬®ãå‡8Åw[”¡j;zo@Ô+î-e7x“³LÂc˜Ì{•Pñ ¡Ê¦¸ü‰RªrfÚ^ËçxBG!X=û[6Û—ò÷ÖÇÌžy7‹#Us”ºõˆ† ýÞˆÜ ŒK*/›5‡Q¤ÉK¶–î»·ê!&,¥ï–TK º˜ô5ì È |¡°o¼ÊýâüKt³[‡Æ•¤ß¼ 5)ƒ0ˆ§»Uyû™^ƒÛÐx“bMËëNÐ)ÉŒæqQ´Ëƒ…Z“4”nPùÈÙ-e 5fªµË|T£"̲ìdÌ¡tõZ¶É¤Äí?hKv%çV,¡qö°Æº¡ªãP|øÙF%Ê *•oa]¼n8RWvh]®.ˆ¡àÓú¬†K1­\'¸µg©O㦆îGÃb·ÞÏ0njÍޤàD¿ 3Ý%ÓòuEã@,Ʊ_Ü€¸Ô:ÚîxȃÅÿgà˜·ƒ¥PEµßøn5’ ƒ,Óx”Üž»_$T¨ÔaÈŠ^&Å@bîžGy‘ˆ^­À¾Ú¼ðÛ~rŒþ §”»†2måæò# uC^XÀêË®/÷Íí—_„ITÄ?\‰_aq8b öº·$Xw‘_'N ¥Iʈkf¼(PûX¤ ÖWˆ(åû&öìéªñÈÊ#‹¯ƒõe—Ƶé>p@µ^¢8¤™Œ/(Î×·®Õ{œ¿3_éCþ¼Ó"lÃ$ʃêÜì)Šã—ãQ½’›~¿W-ö#|àƒ v#ð®ß;<=÷…oû¬,-Ü^×çi¥U탚’1½&×…¢` Iü׿g“zÛÍöú¸¸ìò¼¾fÉMqMÑ·ËÌ0¦ä2ß[Ös\khtÿ¶—¬ü±Àšq‘ìw¬íl·‹´“8 °µÇž–ž‡Â‰ÎxÄË¥¬óÕ’X¿ð?)_Ç–‹ÚÔ”ÀoL?¥òDÄ!q|Õž$‡j¶Å"-g9ǃwÉæb;ìçD½wÒ{ž[ž%qO_ߥ´æGO¤Z#4qž3bèí½hœ¹‰§ØØ]~À“V –¾rùlûÑÒÊE yˉæ+6,_åôòö×i¼ÏÙé”)Ó³’[¹Ë¹ÓtW*`–K¬ÞMœ²+sUfü|ïx2’gI/G¡Ž–ô’<)v)q-þQý'“TÁà¬ï"ŠIâr;k;“]ˆ¸ÕˆDˬJùKuÓáׯ`…GpD; Õ['ÉøZt††œ+ D¿õÕá¯_B}²XõÙ’òÜ!èäe^ŸÐß©­AáTh¢„Èt ƒ¸ÁÚ]ŠÛ—CXL4¯¶ì.ÛKU6õÌP¤‚XPðó)¥Œ ƒ÷M0ôV`ñÎórw ¸Üì©9»EåþR„©­ ¯Ÿ¸ø Ù1š­ Gà9Çi›V3se×¼+W{4iu/ò…œÉ±ïåö¤ÌÏɯc±ÿ¥>L4^+©ÝlY_ÆÀ=üõ³Ày÷ÙÞsæ‰_ø„öµžƒÔ*ž 1ûJ8¢UŸBQùqI„!F°n Ðg‚ã‘§dtòÝ5G}—Ÿ›º9¡Œ]¸NÅ‚/NôHWP8UoÄ`‚q$†ÏaLŸT9EL‘æ®§Å_WcóÃÇ:NÃð4ü)ÉßãÈZR渚z$‹Ê9‰6ƒ¼Tèï5æz–EVclGªR²>¥ ²u?Ÿ”óShÑ”Bœ«%wÇí‰7µÆT÷w£Ž$ˆ@–1hÄ:Ǿ]­µ¤7Õx$gïë/Ö6!ÞAê5ÿZ“îÌ¢ºlUÁ›¶°x騮»ºÙ¡—kŒ‡ë2r³1dû@™&oàeÓ³¬ƒ¯(-ŽL¥¿Ylø˜$‰Œž\8*"’/€9Ô{3Í{˜ë”b"¢Ï ÒÝ£ÔàeëËÞî›Ì>[4"Od÷Er8a;ucqöy"¢áõs¬0¾hŽˆ¿ÞÜm—k¹ÚTæâ÷Øw\6ØI,oâ=ä¨\+{‰F¹éݼ¶¦Í*–gN+=™Ð¢çÍeüõëA¸7ø¸ÛÍV´ïOìè†nå5ûÖÞüõ“ô€5q @t)VÙ;!Ù§¼€ôŠqa¸Âãç†Ý•x~"WÉÁ`n´Nwß`ß%‚Ò-ÙvòRA=1µ½FÇîœ+ídò×wÑLÉ0Ô–ù™¡86Þ»>×°Ì÷×JÖÝG‹šÂƒ´'/å4‡$ýbÜŒ”Ó!gjO§<½i/$“]Oìàá•9ã^gŸ§~¼¾¼è h4× [q.œf¯Âá?¯—¡ºÅY–r1›¾±våbÈ|aê ,nß@î¹Ù•š_+^~,çr‹E 8S]ª3mòÈ|]Ã3Á7¤èèpûi¡3(~Ç"½›µÊ@ÄDç!Rþb‡ã¸ëP/¶ösù¦UâZ˜vOþ‰Ï‘Ek5ž•Â.èpé…éÍï×í×Å4¡kàHÐЕ¾”.!ù"Mt5!¯¤£qç AžÒx) ‘|yž,ôÆàóüM\¼]6>ñJ¿Ïu—>zñÆ@+Åi%ѯ8!¹ûsZhŸbz™wJ×)èöƒty§içì,£xùåúºå§×Á$Cé2/’²“ýœ´ü¤¹$Õ›ï·- ™°ÎÜUÑæ=&c5¿*ÞËižgqŠx&eí¼ä™DírðÙ#ù:”î ¾s8 1DLDHÏÊu˜W&ÍpÙ,Òœ¹ø˜­®…ã‰DÎåqŒ²3ïòÃ÷†ƒqA¡WÈ?;~F¡œo³bŽˆÜÆÎrF´•éK¿¾Ã=ûP\øñŒǧàÇ®o.8Ådê·_c"Â0MÝæøb"·Ö„a§jyS²/Åzrf·¡cVg§‚àdµŠµY'Í¥×ZÌœžG!+Éåõœ)]qkηënÖ ¡2U[ÑãQürÈÐà>M1˜+‘Ñš@ÿÖÈFü3·bŠR!óFSÇñ ÇóL9ˆðÕ«ô]¡Lü»Â•\‘SLY«&Ê™sŸ¶ÖYÿ9iÏMXZr«’ÂW­%-Žg¿µ¬ë^úç§þ x~iwWwð¥M<À­Û!øP"lÝð¬áëGݰ!xû²Xý¨Ñ$©Ä$þ+¡Ó3²WÏfûº]y¾%†­Q‘ŽŠËjV]!…ÐåÕŠ½ïdê¶Ÿ÷³L?¤Ð{,Ç6hÏ-YÝ“¯ë•ñ\-ojd”óšUR™¨„0kÂõ%d§ )ÎÒÕ‹¬Â[n}›¡xŠhß>M2¹àf‰Uþ€ð Ÿ¹n5LN\–˜–X8¤"Ûvn:Qëu„•.÷¿ñ>bæIô?Áù§jCÞ!€rj åv34ðöÒ†¯¾ v]ºÑdLKe1«Òt_ûÜŸ©z€Á$8žm·Ú÷ÔÀ˂ٿë'Þá@¢Ž´¼®ç‹¥¨¨>Tž•ë¶þ‘¦)Wgbú¾ýþ¸W*Ý{¥‰ÒLnéxiÆÐðØmœi c6wþŽâµ˜îSÝwò+B…ÑÁjqÄm±–Yý ÷á¥÷Nž¼™ß$AïžQh÷<©é.(—ku÷½¾£æmÔWlDÞä×Ý>çFvHçË ¢ôA,ltëÃ=ágµc¯%½|ôJ1˜WŽO«V1†ëÐíÎõEÜ ®eÑÅ(7¢í•ŸÂ ñ|+¦+ž0ÆNÖ4õ,¯´ÒüÌŽ]&!¹‘úCðs0­9tý^¾5ûÔ,ȆUgi½`1–¥.·§‡$Å£Êñ;m©”˜bä^(]¬ç„¤†<½£ÆýÕÁ\`¿S¤=¤ö£Å’{®_‡ZcÂ0^Þwtu0ÊáY˜džO¸›ñØÅs„ó~Wµ ‹-Øxìð(ê½ÐæÙð t¥‹×Y)·Û“7 ÛÄ‹p\*r‘(ºq¿¢ˆ„@±é K¸I$T‚;'Ãb[m ¹PVâû±°ðŸæ§Ý´¾ò¼âÀºà½À£‡›AÕ΢衠‘ÌÁè´­x±JMü˜tÐ#?Eϱ]€¶®Œ}Ñ –7c{&:’_Ü´Ò®lï§Kg)Dx—¡ô¦íüsVáGdW¤‚úºÿÉaƒkŸÿ€ ŒõþsÆ#¤PʰxÕ ®S5žü=—„Íze¤†¾Ä¯v=œ#O,zÊxç1A¿2ëË‚8”»FKcp-e«E²¸‡.é ¡¯ ­]–[w¸ìO(3Iý5vÔnäî9pX*–ýr =!6½Âˆ²?~Æ’õ«OLû­âB/££ÒÛe¾CEÕÆÉŠ[‹¾yŽ1ëÇ+¸h%£]O¶Ý=[z>åˆ*°×M‘h­¬¬~;âǛӅMŠ,`€[`vRïE"|ó‘à²'>禾ª†Ã;=ÛVóC¡”ÆðO#ã«“½¿j,¢3Ìap>hž ºd½žÊÙÊæÇô/ ÇïÕ(â˜&±Vc×^%ú0™/pÒ¯ôYn4ÌÅÌu:Y&gŒ5c>q-ŠÒ h¡ûöÆ¿[Šå qkX´2úâ´`ã’AXO"~©6nLøŒaW÷^ø±P$•ffSÛ­5åó/l]3vø0°D5Îe€ÿ,Y.ápûŒY¼VÇÉž+ ‰ÒNýóUÈNúö¶ö|ÆI{bÌt´˜vîuðYi)ÆY›øÞ˜T ׎lyßtšºp<ÝÊw^8ý“µ ªA>¡æjÓÙ°ÿ–SŠ endstream endobj 679 0 obj << /Type /FontDescriptor /FontName /ACTOUD+CMTT10 /Flags 4 /FontBBox [-4 -235 731 800] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/X/Y/Z/a/ampersand/asciicircum/asciitilde/asterisk/at/b/backslash/bar/braceleft/braceright/bracketleft/bracketright/c/colon/comma/d/dollar/e/eight/equal/exclam/f/five/four/g/greater/h/hyphen/i/j/k/l/less/m/n/nine/numbersign/o/one/p/parenleft/parenright/percent/period/plus/q/quotedbl/quoteright/r/s/semicolon/seven/six/slash/t/three/two/u/underscore/v/w/x/y/z/zero) /FontFile 678 0 R >> endobj 680 0 obj << /Length1 2110 /Length2 13357 /Length3 0 /Length 14512 /Filter /FlateDecode >> stream xÚ­µUXœÝ²5 ×à ±àî‚»»»C7îîîî‚÷ àÜÝÝ%èéo­½W²ö{ž¾éQU³Æ(™ó¥$UTa2›‰ƒ€Î ,Œ,¼9UUV #3"%¥ˆ£™‘³(jälÆ `ááa¹XX™,œ¼ì¼ìœˆ”½‡£•…¥3€Z„æŸ .€™£•‰ gälifÎabd P™X™9{0„lmÊÿœp(›9™9ºš™2"²°L­LœÆfV@D¦IÍA®›M]ìÿ×åjæè ‹¤€%š‚€¶S3sD&y˜Ë ¬äÿQÿ7¹¸‹­­¼‘Ý?éÿÕ¥ÿÇodgeëñ? ;{g3G€ÈÔÌøC5Ìþ-NÎÌÔÊÅîÿz¥œl­L„€¶f曬œÄ­ÜÍL­œM,ÎŽ.fÿ2›Mÿ¯pßþ¥€IVDEIIžîú/§¢‘ÐYÕÃþ?Yÿ‰þfùƒÁíq´rè0323³€Á¿ÿý§÷ÈÄ€& S+ x#88FŽŽFˆàÕ#€ À hjæ0s fb‚œÁGàžøÌAŽˆÿÌ““À$ôé߈À$üq˜Dþ n“èÄ`ûâb0‰ÿA,&‰?ˆÀ$ù±˜¤þ 0»Ìf—ýƒÀìr˜]þ³+üqƒÙÿ 0ŸòæSùƒØLª˜]í³«ÿA`v?̧õ^d&£ÿ 6°2#;{ð…0oÂÿZÙÁ*ŒœÀËgådó§i`z#ç?yÀ'ÿ ð c#'[#'ËÿXYXÙÿ1;þ 7רgælkfþW2¶ÿØÿ}éþãk7ùâsš€lÁW÷?JÙÿ±ØÙý©ˆ…ÜÐ?¥°c ²µýK x™Ìþ$G˜ý)ç?~ðåþO°>ðÚÙý•\²ùŸ,às+׿Òþã¹üM ±øCö[üó<šý.çOûØÁ#¶ô°·4þ¶YýÁâ­ÿ‚àáÚüÁýúS'¸1¶fNNùÁÝý«"pÀ*p. ðOEl`j ‹ñ?¯§Å_’À/èhpNÐ_§XÀo“ý7˜ÃÞÈÑ ø_óggùëOŸ ,¼›&fÀ¿B9ÿe³ýµ®àÆÚÛºüU Øâð§ð‹™Ó?_¢?¹Ùÿ1‚œÍLÿš3Ïÿÿ[ 8ø¯1±€;ñ‡|ÈÉÌÎê¿7“ãŸ3׿fÇNâ~ÿ#\Ýÿ¹/,àâþÐr€»âléhö×R»çìúë8‡Ë_9zu"È×: ¾…nùÔá‚ñXŸŸôjðÎtLÝðó ²€—-‰4†:H¤ól~!•´êtñ±VP¥¶ÍãÕÀ(RÁ‚§Ûf›’˜oD+ëÕPèiVSBÅ~.©L‹2ócF0mⳈNl¤Œ°‰È¦Ø:Ön<õÌF2A#×ögн±£Ì‡w‘¬†ù1³µË*šL(žk41m‰³eâŽë¿±®c²^46v °ØÉŒvü<2|îÞ%éÑây¦ÜêaÅÕ÷6•³Ú¤Ó³þ¬Ó´#ž¯Å†`)ZSŽáb)õ8ªA¨ÔÝë/ éÃòU§ó·\çòvÅI¾d±þý‰í͉‰„’Šc%ÏkÓö,Õó;rÌ•ÜHWF˜Ô)%…ßgïúT÷ÑÕg&±~å¶T_!MýIÐIß6mßtý±¿øÊ*×ÓúåµR˹n‘fEe¿¯öð\—^Ôú „6Zn"±âƒËÐÖ‰ÄË úq¶Ñí´Ú÷õ¡e\Í WÞþ‹ÚQŒ©·zFøwÓ¾¬KÙÛ¶ªlfj+Ÿx™?¨?~˹ðÒƒŽ’°t’\k f«Œ«¯Nc´ ðà%Ö¨<%…Ê¡·@r'Ä aØ÷K:õAÒ¯Âíj Çóe >µ‹lüÊ·Ù§t&‚o]¶ cù2øû¢öåÐgÝExÀùœïâ(ü]¿˜°' zmj¤¦݆$½›ð†`Ìq)Zý!ŸK}3ùšáNãí†ËKä ¾èš%á÷Ý5¨y‰k.r,f„iϳÞíg'Î$ÉÛ1LK=úñÁ/EÌ“Ë_‚RÛšx±lÎé|–ð(V÷ qÔ&œ”nMê6)'7ô†Ï$î·9%ódoÄvo6Wõ¯šS.ƒOt„½Ýf²ï¸*vCRý°Çünï’-ûF\Ϥ¶N›­UQ£¾a`‚ªur>ô_ex”â´3iµxjmHá˜ÙšˆM´¾„ mª2Ô1`p²ñ,Ö `.\fpS°Óºú÷³Se“¾ñRãÍ*»”oŒ3)œ%½ŒÕÛKöït[»Ó߬ȴÂÚ·óÙ„-ªòëÎi•Fêb‡'’~…e!ĸ`ÅË ½^ 9^D¼´)N§JéÆá+“rꇹÊ8KðDÍãÇ\]²Ä’ûÙˆö^}êi kæ$ÅÅùÞ8Ha ³ÎZÕ4"²P=+ü‚^eG}‚ µï‹4NÓ /TË‘b Ÿ^ØÓûûŸñ9E©O¨l9%©¡Ç—»nòˆbÃ=^œ$F™ö¢A¾RúêE‘<œéù¥Á‘#b “*úØï::Ïï‘Û`^‡×£¿¥ö\‰Åú±/ÞkiÇêÍ®-Äö†mð£*¥dD¥sÒú8ÅûÊ[fBZ„æP(£t2†ÎÚom{áØf×9ÖûÌ$%' ϤDÉ`tÅ\K>£D=Ô×>j¹¨¨žH¯¸ ß´]6»‡yv[Œ •ê%ö©R@6ÿy@`­‰Bsg‹ŒÇ;{OòËט»ù*E{ÀÓ‹2’qa#£Þ²y:-Ö„b)}H?+q‰#oµ¥tù‡MWÃK¿P¹Â0¨Ê¼éË5vàó™m€˜Xùi#µ×ãÀúkFz›H à 2ïaë ×Rëòbã+]#"4šd®×/ŸË; +jùZ2¨\¦‰•¥4îaaÙº8Û¸¾õÐVŒÅw÷·Ò(5òU1V·GWŽäSž×ô®ëV‰ x©õýH…ǵcöMÙÐûùÏ5㵃P3E”9€±FõL;—T%î#™1ãÊ>͹O oÎOMÒØŽ@s5¦4´”Ã]”C§§(±ÙL¬•¤/é{—*’üá ðúk[†>Ø4ĺ‚;Æk­ìã_rH°Ý›½VÃòv2!]‡Çõ¤{ÇtMq¬ñ…ŠÐ'žò¥×'îN¯å§ÊÝDèÿ4±T´ 1¢ƒ3;âðk[eßì ó®AÄAë´B4÷,áÈ÷Öí­»TúxNƒÞó!WËÐ'·m¡Ë‘(ìä#N‹Œ4äG ·ñA"FêÓ;xEç¹jeÚ]»¶;–´ ÁòHz¯]½ÏШ5üïãhm 1¤ÔŸFDzµr†ÔË»§²·’7Ì\”®òd…!/g­Pü5­hr?‚è>öW¥N>þ.{ç˜l2R]“Žm•ù8½®ÐE«r<[•:TDîLд…ërÛ}÷­wÁÄ…ñÕ õ‡*‰rá7DDAQsyýTÁ®T–QZ¯¨¹>F!̾«bø¹Íiþˆô½Ð/&@| â¯Ð V½3]£48gf¾¥ÎÉl²,>™–g 8ÿ>G^¹Ðì†WÞÖ)ÜX7~½Asލþó8tÝ Ôè4Ìåtîg÷§pHôýAʨ7çÃ#…=Z$vÄ%yÁÆ"¢Ø¾R‰×1Ÿù&>W@ú4£=*S^—A¹Êí2‘g¼QÕCQKcØ‘ž(55ÌôÈúÙÙžPR0s:kߦÓb„A8ÉÝ˗ɱ›´HÖßïKµ]rÄ Ðä ŽúŽn¥UGª+nÉ5!E c\ް63:‹±£ÔöÅìž9“¨ßŽÖ[/Êf Fñ¨T k= ‚A;SFÐB" Ùœ‡¼Hßé½!n:5Ù"î- ÊçÍ:´tsÜÑŸ½ÞevvKŠs($íø“5×f$?Ô«gJ†5rÁÖ‹;oK¤#êÐ~¡(‰¡À‰X³Ý%Úe©Ìšê>\¥ {ó¿¼÷ˆ\‚ˆ¿h=|,ùªèÄ‚P›Þ·à¸“Oc^>W•¿\5K¤á¬­ÛgëŠ3ò£MZ˜põá81 e½svD¦9.’UÁï~»›¾%²&*ÕÜ7Âw$XÖÇP[¯ÛQ4RÄŽéç…9Ýô’'pãXj¤pQOÌV¤ès–ˆ‹Ã~JáLuì8‰'ïÀ9]ºmMr¸ Rˆ©scE®‚DübBt4š¢Ã„9íÁ±Ìcú’)øäTØ¢§‰x-WÅÓÕBqx?ï ¨,PžQC}¨ÞÆ®òsªh±!ªU DÖkéñÂPÁÿMófGèÇæú¡¦ŽÿWMç4ö—eN}”æ§ó“êiïêÈèÓQœ/POÚa„Gƒl=âF¢DU’ÚǹŸÃ]0kD-o»æ_ô‹4cqC§ÔÐoäûì# %•M!QÇ—ñKÔçA¯P‰Ë¥Ÿ$BBŸ¼Â\‰ Ät=¶˜Þ†‚àù×/K$n'ÒñC“s¬ësõ§I½)÷á¡ÚlÔ'{–ÿ–Ä`sp ¶Ö¶–/àJ[ñQô#bÖÅZÎqßê" Ù»ÌËÕsvEÜõTKq5 LôÛeÔúáµ÷¹Jü²ªqÓƒ OVÞ¹@¹ëæhs¡RªrTFme¥Ã᨞•¼; GN©.t/j_“T +ç"ºhàÈ„pL0‘7µJ+ÂCÜÀÖ¡ÚlÇñÖ\~+AÁ>3R¥þ-UŒô®vþ êiÞo>E:fWAn¹<Þ¬@ ˆq(!JݽÒäÏcå«°tnÃ]èÞ85ÿДz4ñÍ/ªz¨PMÎ%ÑÈÊò㠥Ƒ±¹#JhNål#f#:F؇7Õ§¸qYÅó¹1DÜ,ùáic˦—רBì±ÒÐÅÃ}_=8éóx¬³áˆ0äÑRl˜P2__[qñRV]ƒ¢ÀÞ±±+ÿ¼°èÇ›¢XŸ`=\ÄSx»KEøîG€Á½þ[-zåL­5EÄÕô©ðÚål!ȬÕ)Ú~Âüõ|óN»ÕBx‡Ì›×ãy&§tˆ™ì‚U[ŠYÌw=Vò¨ Ê>ó»V¿ž¡x†œùÑ{ˆ®¬ËŽžbmèÙ¬ÉTf ‘ÔgíŒÐúÀ…rîî”à„¦•= VMÛ„t”ócÍX§¹}šÉ•rÔWq7.ß>—k¾—-wÀ%—êL¢Œê÷º•xp©y&á_ç4p.t1¬q‡cÅ‹É5„ÜÞsq|ù7šp­¥+½á‚‘±ov“?ƒçåTá ¬|`L°¼AÒ¢7/v:¥WÊ1 ¨M½5ÚÃ^4G_¬vsw8Œ}¹ÊkÀÀa²;ŠŽ©­E“h·®*²|¡ý6šG¶ßZLàOÄyTªÀòœ ?F?Ö—×¾Ú¸÷d18¿„n5#<\>F ÷ñ™%Œù»§¿ûf‡ÝxóÑ žý†×ÓçkeçÚ-e”iy5”_t­·Èr×9M:Z°sÛ:ã܆€^™‚ËIcTÀ<`E-Ãhc#j¹wŠu<ÉíþîBÊ$ƒ‹ÊÕJ椶aîÝŒØT8ܰ˜ÒgÎù/æ…Fä%LH?D) öcn˜Þ>;LZ=İt.‰Ø5µz­a ‘ôácØp¨k{¸Î}ŽàD:¿xfg¯Ç>n£Uˆ¦£<‰q•Å¥H"à÷µÈDvçZº?i1 5ñ‰û)þ‹þ°:“…L¥*©^DéÆ,²¹A›â¶°Ú’¡Š!6™ä¤ƒjµ»t’ÂðÓÏ3`BJ—6G!ß’b.ÓõˆÕ-m…+º}ü¼ýŠ`4.–ÒCRÿÐŒ­£6ï5×êS‡&Ñ;û$Ò4Ö! @)|”«¹–ÌœäðÝMÀ.{´;Ö<Ù!†"i* ßSa Oê|4ЛD-=nY;)^'õêh¦ì ­‚ô”6©k“ åM#C“M†`{y?C ßùRYáØÐ‘êZ½,KäsðGxèf”õ.KjŒnÏÝPÆú󼀎–µÏ¥[Y74?ÍÍx( ¼`ý+ò4ÞPNÆc"uÐûÓ¦C²ãÛ”š`=}‹ÅÕ8d¡½2'6»ªq#i9bøòCh>?éG$ìfÏšS]‰uº@Ô»3'E×Ïm¡—Ì£Æsw*c;tlKaMºAÄF†|z¼UstŒ«‹­¥†‡îY›s+tìŸïçãâ [Ç$D騇8¾Ðž–z>¶Þ²§p*y™«Ø&d×ÊÍÃÛ=uŒA“.-ÉÒЧý|y¢ ºãꤡE`6³†œTÕ¬EºˆHY0° Í襒óÙ:ašÔ2ñv]QT²èeÜâžÍó¬¾ Ä{qR«ßÉooKk±ï,£•Ý´D¨²iCeŸ: ½Unˆ™5óŒºjAªßÅ.r€ºƒ³MXûS§]V» r¸£møO©îÖpUm™?¬BcÑ^ù¡‡Ò¾¡‘Ê q“s*DCêKNø¬‚œ¬ˆoôé¶Bè;|î7¹ŸK+|"ô*”¢é0cédî¯wY¦ÈŒïN' dzo(°Èùç!‰ðì.¨‰­q Í#à³ê-ÕíeRNÔîŽ0bɯ¤'‹mdQq‰¨|çßã݈:9oGF®k =BoF7‚»P½dxÅ0KNìËl\Ä3HD)>F„DýÆ#`©Þf¼y.‹Ý’}”^¼JzrŠK;uñÏÖŸú"ËùÒ­6Ū4 šqò®1„g¢éž»N7»îö,?‚~¾Vá½:†É8[}¾í饰Ÿëù©QR6Y…þ1i”µ¾>#ufg¾_f9ƒáÙdpšØ'*ËÅáÉW 6™$¾ew!ïU¾*™)>Yh£mAÌ4);¢ª™È:G–“=(bÉ‹l:‹ƒ¦†b(µ¶ ð¦j=Í;RD&&ˆ>%ì¤Àµ µ¨½½æÀm?$×–R†÷üËp­ê¦JKè¾k<ÿÃ`õ°¼ÛfÊ(ª#æ˜ñ4Ê*HžhW*’?0‰7¨Iƒ‚,<´jã4¼2ý@z¶îη¯VO™gònb¶[Z‘ô¼’4óÚóöÚ}$³²I°Z8r2Y5!| ­Â%j‡âF½â½~LVªËp¡FÚ(5´ËMöÈjh~7ÊýY %ùÔ%´uf7O<e\ _Ø™aa'^+.Ç=ýÙˆÑqв¿$ýdõés§ßkbŽÿ÷HøºZé åØG× hÝÜfKË©½Ñ›àFâc!”‰ز¶Ãoßç°g ÔL—¼·*+ïlE£xS"sYÑ—? ¬ùÆ;á´*ß‘Æ2o …X”òmKߘ’KŽKôA³þ´¸$C †= k}Øk˜ÒºbAŠFožoµ½‘hÚƒŒøF{-ÕMó68ÝùÞ+´ä‚»}B°ù5SúwùΜÀ²)ÃJ“Sž5Ðoç2ÙµËßI®qzc¬q¸d—±e¶-Ç9U”þdªñé= æVgBÔÞPä&Ù•‘®Áøz ‚jc†2ûÍ~Ÿ.cq/û‰Ý×ͺ’»’yv¿[w9sØ]À'¥„Ä4¥¦Néš Ìš Õ¦áOÜ¥ßt÷œF­W¶…§œ³µÁð’ÈÑ­`ÓüO—ŠhŸ¥Éfh›&¯K8=·MК2êø?jÔ…•‡ÖœDÈúûeúÍù:¡à•‰¬‡à8KÑè(VÞÁ³­?RÔªÖ™H9²K¨ÿžXHä™Ïx2NÏñú\!^='ÕJŸgŒý=t¯¹Ñù\ý‚½?r£}óg‡õ|‚ ´Ü\–âþR’µþ¼wa3R)PÙ²eàÔ#o1§Ä›Í3œ™¦P¬©[žøÑÅ+òó—|Fä9w§ O±<ÍÚóßQr]ºéXpPj&"•ÃKµ)˜?ç~U£J„á÷<—仕µÏí¶žÒØÞ> oÍ8jw e¸×ߊ&}³Ù}`˜©%ã¹Jo¨È›UN4j¦ˆ Âñw5Ë-ÑÊ®žÌ`N:©¶û­ûB{Y—›RW½¸5¶Nd”ÔÛ(a®GìÿEø›‚¿3zOÝi>ÍAá©ÎLêoæ<Öé`™ÄÀ[,˜ôß(¾UŠ^gW¥ßG¨·¨º_€öÅ#,SN¿É¹s _f¶E¾ÈØ1°çv÷-àqåÅ…ñx‹Ã~ì-7Žw,\«ÕÓ½Z µËcr!¶Á,d‘~…¶–h‰ÔlÕ%ºk6YXB]Œíí‰ýX·¨Ð7x*Ž&:Æ:½éJƪŽ‚×Igw #¾§Þˆü¬±Bk³añúØÝÀÃâˆ@”á©bZ”ŽïÌò±g©£ÚJ/±‹üªö¾Òâ3$s–dР–=‚¬˜áB Pigvž›[ÀŠ^C"®až9 ‹ƒu÷7_¨šahq±/õuÔ1{ξj\©nÂÁ0,÷ÃäƒRÝþ&ò휰‡ò”~’]gƒfùý¯#¹í'%U|^Ï—dXO/Ôá K’Í®¡ïXš–’‘ÄK÷˶;ë÷©£v€¥>"À€f®äöðÝX³‡6, ü“<æØÏÌOêŠÅæL|–j]œè¯äDÍH~T.ªpF‰¶7fcM7œŽ¹‡x”Tã “^^쉵aµ.6Ä}Ó©¨pè "q§mja|{&øUg²ÊW†x3n âù|sð ™¡b¶ß¸5þ¬½¹‹Z¶îH“Ư.•¡°ºd=5‰ŒLìxåZ¨Qty¿`yg“и !v`!¥e`jß±/TêçÁç"Þï†*XTÇD0ÐavÚúéáØgvîù±sCÇ,ѹ+°ùQeEµ­XíºÈ®oõ{Ùž'"§¥ÃO‹1¸+^ÆgéXgøèŸPìÐxrºÏ«[Êׇ£!ˆã §éÒŸ‘ܽã9'ƒ²Â©%¡‘UÒ0r'z»MÕ"q‚£µy^fÅW‚.S](Z.NQDê¼P¼üøyô 9 Y+WÝ„q!fLø( y?ϼ r-àfw‘þ¥Ç*7·ö}* ämEô$ÇÆQ˜ÌöÃß2@ñeª¯eÁ¼±‘"ºçœx Tq±L~†‚5jм-Þ»öJÔPµg5S<ÏÉSY+Í`>œv¸¼#xeÐÀÆi6¸)òé}>È=ß«Ùn.²réâ° 9Ö„ £§˜C}áãT.åª+}JùØ–ôÛÄÞQF½õºÆiÖ Œß••#6ø±6ºÆ¿5µf3‹È…»^ú1&b…$(Á}Ï`¨·Ãyà–ÈIþx +д/22ÝÞóÖÇ«0_ÿ(£Œ+ÿ´f¥hdTn0þËJÉP†^ãB7˜÷Ö˜DRwj©„}ÆLSZ*Rm‚¿DÅXLºI²33!²»î´‡+”G¹<ΆîÊX¤ïÒp±ž#^™u\ï ¹}j7Vºš×N™ê>yƒÿ›€SðÔ‹+Ò60|÷ µoãP"úžfšuÏKÎu™m5O6‹Ýw^úý‰ óæ~Q^˜ä—¼zL‡CTö|ÖšÒ×[/oÏ–¼L‰¬ÊŽí¿oTQC¦ô×}ß'ÎÒ%ö‹(Ö&Ämø]'*-N}Ž ãì÷ç³K2$TÑÍ ùi{ †fõ›–“7Sª?I¿õ cïÅ,6F¸µ·ö#dy;Uê rˆ1Ú¿£!š 9åAæ›·–_l éï@2lƦȺN|ðÜ*ó åPÜ”š#±¥Ë æ ݲ\ôÑ3Ì»—X…ûa؈ø›Ÿv.à…ÈNkÿ’©Òg’…PÀª5Po‘çáF·âÑ B9å4JÁ>ce‡3Ÿ"~ñAk %hHwùFBƒI¾>€#ôGxe|åLŽð2ˆX•¯£%Êøµ%Jši»V•LÑÔOþõE»™¼3Ê„4E&@•½œô" áåÈó)ýÓ¦r$‰M¥Ií{s¶¥ú×-1`̠³B4´ˆ~•uÉ9LûóúFÅÖAWôÙò4žÂn)¯+ay”ß]šz K„w—«ðô_ŽHÈêüîL?>EM¾Øv£z»\R“[Õ‚Æ {„š•tVe/­÷%&–{füµŒ_Ë|z©„úz^Þ¹cd7²2È{“Á#`²å×=0…še“üö^Ä}}ßÔ¹ï# Œ_ÑÂTµDò} n\g§ï¡Ñ‰0ÕŒÑë&ÎAzÅ—êzj¶ ŽÂž®„ÔIÄ\tš"p0hP÷nÓhä´³¿$üá4‰:ð³ÓÁ…õJäøÍ  ¢`ѰD™»+CŠ/æïyK’eQ×@}µCÐ#Ë»5®X;‚ðQ/Rb>É6šÒïúsô­ªž1v·â¼]Qª÷[j<Òkˆã`¤ÕÒzÄ¿íÔcÇŽLPhcsÛøavjÀlwøž »†Z(¼¬6tì8*mø„änÛîŠ ^CÈ#É]#—Ò¸•eyBznŠ.¸)RDÍ…½në^b?„“Á¤Å×°l¶•Uep÷Üsˆój‚NËEª½³Ô¹]Âk]PHC!J·àë”w{gòØXÇ{â\m’nmîʲŒÅ„VE1:G¡“áåw ò2Ú©€-;0èÕ¹ï¯î´+â„âû"Z{J}â7ÆVó’éîǬÌÿ1S1ä+¿6Õ:hHFK ™íðCr‘Yyô}c¦oê°w°Ä¥°BC;yqƒ ý$^ÉÏñkŠ 9Ƀ²™û(vTí RAåÚËB|ϱü}@}5Ð:ðz™â¬)‘?8»)Ge‰²Mt™3äëÊ©¯IÝK:ãÆË;b´a‰Ú.ÐàaÈôr ùk™Ýß[aêÓüP¥I ¢Üžù%,ú‰aÌOsûã] *-«iÌ.¶mEQg»©$ÿ VŠÃíŒþƒ 7vzïÆ#HI¥[®kâ³¹P`¡íkØôÁ‹ô}wûí­|÷ [«¾©^—&½µAçä­þ²QÎ7ÿ¬XÃɶaÙj¹ æe··þ/½Z÷ª³9…˜ß’lûœLÉÌÃ4Ñ,N= GMßosŠ_ÌåP¬à(è°XB’ëû¹ß^è‚ý.[€5ÈüW×üJÛ¶’Ÿ µ'ãe3s¾q¾>‹ºNEQÚˆí†'D³ÆÐ-þœKsœò{ìE±!¥ƒb4­n±Ffƹ¡†» Ùû&ôÆ^šgÍÏ•ÝÉz…•Rª•~ØÈ¾¸´?`ƒ°–* ¹7 w_T?YG“4’ËÏ8Ò.G!RŒÙígÓè‰ï9ø’¨-zºè0@Ô"d‰èDºOJø’Vn2´ýò+xbj+N<’y§KzC\Ì€¥Çéa¬Wô¥ùÍeã¬b–™€g竳Ý/Ïþ­å˜„ˆs¯2âàGcÖ‡~lWf÷DæUFÇe(©õÍwÓ}^HÊaÔV7«Q ç^ê÷jå+¶âð:³ë†Ù’´ûÈ_åææ7*/N 3nÁ;½h¦›gÑ(`~ø[O#À€H²›îß&Ú4Jô+Æè=¯Ö;Æù 9œ¦ ìÅ2ôÌàŽ«‘uéÉO_ÈydCÉÏñ~‰¯C¼[åfö»G¨6ñ¬œsVžýï‰ó‹¡ô¿I î‹¡ïqj‰f…ÂhKº[ÆÇ-—¢MŠ2ÝŒ0†ÒE;óDd¥ ‘×Q.²–qÕ|ŠŽf‘dS²ÊÊ'ívÑpPYVvÞìèt ó€~Ëó|ÝÓGp[‘Âè×––ÿn¶fwiß÷lT¾W 7÷lɆ™KzÖ¯K!êiWÒ®}¼Åú81æŒ2³*9å0 á©4)F„—±¨m¤Ù¬áP¤¨•["Ô¦õèÙ˜ÊZ•×w ©jVh¤¡ÆÒMé ˜Ó×ùz¥ëwŠ‘Ý>ØY_$i[ôY^O¡ HÝ"t×µ yêÌAañ…Ô¡êÌXVjãÛÝuKçsÅ—¸Ùô´i¶ùþ91äyõÒX‰¬…V›ÝCÜåiŸ™ÍóÎ2XN,ª¾ŒþøU׬f=ͯZ‹€­ŽÜò]¦ð]ç[=v®k{Twj£zá®àsJÂ9ºÕ~l2«ëBàÎçš+–Fn‰ ¤µ÷ËFkUü}¦ñt›Cˆ KÚ:,'8C˜èùõ øåHt6_ÌAKv²[´Üò^°„> endobj 467 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XXBDFI+CMBX10 /FontDescriptor 639 0 R /FirstChar 97 /LastChar 121 /Widths 616 0 R >> endobj 144 0 obj << /Type /Font /Subtype /Type1 /BaseFont /QZEIXH+CMBX12 /FontDescriptor 641 0 R /FirstChar 12 /LastChar 122 /Widths 631 0 R >> endobj 323 0 obj << /Type /Font /Subtype /Type1 /BaseFont /FZSBSD+CMBXTI10 /FontDescriptor 643 0 R /FirstChar 97 /LastChar 121 /Widths 619 0 R >> endobj 242 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZCWKRZ+CMEX10 /FontDescriptor 645 0 R /FirstChar 48 /LastChar 80 /Widths 621 0 R >> endobj 324 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZYEXHY+CMITT10 /FontDescriptor 647 0 R /FirstChar 99 /LastChar 122 /Widths 618 0 R >> endobj 161 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NCOGKM+CMMI12 /FontDescriptor 649 0 R /FirstChar 0 /LastChar 121 /Widths 627 0 R >> endobj 234 0 obj << /Type /Font /Subtype /Type1 /BaseFont /CBVNBD+CMMI6 /FontDescriptor 651 0 R /FirstChar 105 /LastChar 108 /Widths 623 0 R >> endobj 169 0 obj << /Type /Font /Subtype /Type1 /BaseFont /WXDJCM+CMMI8 /FontDescriptor 653 0 R /FirstChar 13 /LastChar 118 /Widths 625 0 R >> endobj 142 0 obj << /Type /Font /Subtype /Type1 /BaseFont /FIFIGX+CMR10 /FontDescriptor 655 0 R /FirstChar 11 /LastChar 121 /Widths 633 0 R >> endobj 140 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ARTEHJ+CMR12 /FontDescriptor 657 0 R /FirstChar 11 /LastChar 127 /Widths 635 0 R >> endobj 139 0 obj << /Type /Font /Subtype /Type1 /BaseFont /JROVXD+CMR17 /FontDescriptor 659 0 R /FirstChar 39 /LastChar 117 /Widths 636 0 R >> endobj 233 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XTJZVU+CMR6 /FontDescriptor 661 0 R /FirstChar 49 /LastChar 50 /Widths 624 0 R >> endobj 168 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZIWGZJ+CMR8 /FontDescriptor 663 0 R /FirstChar 40 /LastChar 61 /Widths 626 0 R >> endobj 288 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NODOJI+CMSL12 /FontDescriptor 665 0 R /FirstChar 44 /LastChar 117 /Widths 620 0 R >> endobj 141 0 obj << /Type /Font /Subtype /Type1 /BaseFont /DIFHEF+CMSY10 /FontDescriptor 667 0 R /FirstChar 0 /LastChar 112 /Widths 634 0 R >> endobj 241 0 obj << /Type /Font /Subtype /Type1 /BaseFont /HBIEHQ+CMSY6 /FontDescriptor 669 0 R /FirstChar 0 /LastChar 0 /Widths 622 0 R >> endobj 145 0 obj << /Type /Font /Subtype /Type1 /BaseFont /SDVCAT+CMSY7 /FontDescriptor 671 0 R /FirstChar 3 /LastChar 3 /Widths 630 0 R >> endobj 160 0 obj << /Type /Font /Subtype /Type1 /BaseFont /HBUWFP+CMSY8 /FontDescriptor 673 0 R /FirstChar 0 /LastChar 48 /Widths 628 0 R >> endobj 459 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZIBXDV+CMTI10 /FontDescriptor 675 0 R /FirstChar 97 /LastChar 116 /Widths 617 0 R >> endobj 138 0 obj << /Type /Font /Subtype /Type1 /BaseFont /YCNJOZ+CMTI12 /FontDescriptor 677 0 R /FirstChar 5 /LastChar 122 /Widths 637 0 R >> endobj 143 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ACTOUD+CMTT10 /FontDescriptor 679 0 R /FirstChar 33 /LastChar 126 /Widths 632 0 R >> endobj 159 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LCSQQN+CMTT12 /FontDescriptor 681 0 R /FirstChar 33 /LastChar 124 /Widths 629 0 R >> endobj 146 0 obj << /Type /Pages /Count 6 /Parent 682 0 R /Kids [110 0 R 156 0 R 165 0 R 175 0 R 187 0 R 196 0 R] >> endobj 205 0 obj << /Type /Pages /Count 6 /Parent 682 0 R /Kids [202 0 R 209 0 R 220 0 R 226 0 R 230 0 R 238 0 R] >> endobj 247 0 obj << /Type /Pages /Count 6 /Parent 682 0 R /Kids [244 0 R 256 0 R 275 0 R 285 0 R 298 0 R 305 0 R] >> endobj 312 0 obj << /Type /Pages /Count 6 /Parent 682 0 R /Kids [309 0 R 315 0 R 320 0 R 327 0 R 334 0 R 340 0 R] >> endobj 354 0 obj << /Type /Pages /Count 6 /Parent 682 0 R /Kids [348 0 R 366 0 R 384 0 R 397 0 R 404 0 R 414 0 R] >> endobj 421 0 obj << /Type /Pages /Count 6 /Parent 682 0 R /Kids [418 0 R 424 0 R 432 0 R 440 0 R 446 0 R 451 0 R] >> endobj 460 0 obj << /Type /Pages /Count 6 /Parent 683 0 R /Kids [456 0 R 463 0 R 470 0 R 475 0 R 480 0 R 484 0 R] >> endobj 491 0 obj << /Type /Pages /Count 6 /Parent 683 0 R /Kids [488 0 R 493 0 R 497 0 R 501 0 R 505 0 R 509 0 R] >> endobj 518 0 obj << /Type /Pages /Count 6 /Parent 683 0 R /Kids [514 0 R 524 0 R 528 0 R 532 0 R 536 0 R 540 0 R] >> endobj 547 0 obj << /Type /Pages /Count 6 /Parent 683 0 R /Kids [544 0 R 550 0 R 554 0 R 558 0 R 562 0 R 566 0 R] >> endobj 573 0 obj << /Type /Pages /Count 6 /Parent 683 0 R /Kids [570 0 R 575 0 R 579 0 R 583 0 R 587 0 R 591 0 R] >> endobj 598 0 obj << /Type /Pages /Count 4 /Parent 683 0 R /Kids [595 0 R 600 0 R 604 0 R 610 0 R] >> endobj 682 0 obj << /Type /Pages /Count 36 /Parent 684 0 R /Kids [146 0 R 205 0 R 247 0 R 312 0 R 354 0 R 421 0 R] >> endobj 683 0 obj << /Type /Pages /Count 34 /Parent 684 0 R /Kids [460 0 R 491 0 R 518 0 R 547 0 R 573 0 R 598 0 R] >> endobj 684 0 obj << /Type /Pages /Count 70 /Kids [682 0 R 683 0 R] >> endobj 685 0 obj << /Type /Outlines /First 7 0 R /Last 107 0 R /Count 21 >> endobj 107 0 obj << /Title 108 0 R /A 105 0 R /Parent 685 0 R /Prev 103 0 R >> endobj 103 0 obj << /Title 104 0 R /A 101 0 R /Parent 685 0 R /Prev 79 0 R /Next 107 0 R >> endobj 99 0 obj << /Title 100 0 R /A 97 0 R /Parent 79 0 R /Prev 95 0 R >> endobj 95 0 obj << /Title 96 0 R /A 93 0 R /Parent 79 0 R /Prev 91 0 R /Next 99 0 R >> endobj 91 0 obj << /Title 92 0 R /A 89 0 R /Parent 79 0 R /Prev 87 0 R /Next 95 0 R >> endobj 87 0 obj << /Title 88 0 R /A 85 0 R /Parent 79 0 R /Prev 83 0 R /Next 91 0 R >> endobj 83 0 obj << /Title 84 0 R /A 81 0 R /Parent 79 0 R /Next 87 0 R >> endobj 79 0 obj << /Title 80 0 R /A 77 0 R /Parent 685 0 R /Prev 75 0 R /Next 103 0 R /First 83 0 R /Last 99 0 R /Count -5 >> endobj 75 0 obj << /Title 76 0 R /A 73 0 R /Parent 685 0 R /Prev 71 0 R /Next 79 0 R >> endobj 71 0 obj << /Title 72 0 R /A 69 0 R /Parent 685 0 R /Prev 67 0 R /Next 75 0 R >> endobj 67 0 obj << /Title 68 0 R /A 65 0 R /Parent 685 0 R /Prev 63 0 R /Next 71 0 R >> endobj 63 0 obj << /Title 64 0 R /A 61 0 R /Parent 685 0 R /Prev 59 0 R /Next 67 0 R >> endobj 59 0 obj << /Title 60 0 R /A 57 0 R /Parent 685 0 R /Prev 55 0 R /Next 63 0 R >> endobj 55 0 obj << /Title 56 0 R /A 53 0 R /Parent 685 0 R /Prev 51 0 R /Next 59 0 R >> endobj 51 0 obj << /Title 52 0 R /A 49 0 R /Parent 685 0 R /Prev 47 0 R /Next 55 0 R >> endobj 47 0 obj << /Title 48 0 R /A 45 0 R /Parent 685 0 R /Prev 43 0 R /Next 51 0 R >> endobj 43 0 obj << /Title 44 0 R /A 41 0 R /Parent 685 0 R /Prev 39 0 R /Next 47 0 R >> endobj 39 0 obj << /Title 40 0 R /A 37 0 R /Parent 685 0 R /Prev 35 0 R /Next 43 0 R >> endobj 35 0 obj << /Title 36 0 R /A 33 0 R /Parent 685 0 R /Prev 31 0 R /Next 39 0 R >> endobj 31 0 obj << /Title 32 0 R /A 29 0 R /Parent 685 0 R /Prev 27 0 R /Next 35 0 R >> endobj 27 0 obj << /Title 28 0 R /A 25 0 R /Parent 685 0 R /Prev 23 0 R /Next 31 0 R >> endobj 23 0 obj << /Title 24 0 R /A 21 0 R /Parent 685 0 R /Prev 19 0 R /Next 27 0 R >> endobj 19 0 obj << /Title 20 0 R /A 17 0 R /Parent 685 0 R /Prev 15 0 R /Next 23 0 R >> endobj 15 0 obj << /Title 16 0 R /A 13 0 R /Parent 685 0 R /Prev 11 0 R /Next 19 0 R >> endobj 11 0 obj << /Title 12 0 R /A 9 0 R /Parent 685 0 R /Prev 7 0 R /Next 15 0 R >> endobj 7 0 obj << /Title 8 0 R /A 5 0 R /Parent 685 0 R /Next 11 0 R >> endobj 686 0 obj << /Names [(Doc-Start) 137 0 R (cite.boyer) 478 0 R (cite.hadamard) 395 0 R (cite.latin) 400 0 R (cite.mathon) 337 0 R (cite.miyazaki) 407 0 R] /Limits [(Doc-Start) (cite.miyazaki)] >> endobj 687 0 obj << /Names [(cite.pgi) 162 0 R (cite.ref2) 614 0 R (cite.ref3) 615 0 R (cite.saucy) 163 0 R (figure.1) 178 0 R (figure.2) 190 0 R] /Limits [(cite.pgi) (figure.2)] >> endobj 688 0 obj << /Names [(figure.3) 352 0 R (figure.4) 359 0 R (figure.5) 370 0 R (figure.6) 379 0 R (figure.7) 388 0 R (figure.8) 517 0 R] /Limits [(figure.3) (figure.8)] >> endobj 689 0 obj << /Names [(page.1) 136 0 R (page.10) 228 0 R (page.11) 232 0 R (page.12) 240 0 R (page.13) 246 0 R (page.14) 258 0 R] /Limits [(page.1) (page.14)] >> endobj 690 0 obj << /Names [(page.15) 277 0 R (page.16) 287 0 R (page.17) 300 0 R (page.18) 307 0 R (page.19) 311 0 R (page.2) 158 0 R] /Limits [(page.15) (page.2)] >> endobj 691 0 obj << /Names [(page.20) 317 0 R (page.21) 322 0 R (page.22) 329 0 R (page.23) 336 0 R (page.24) 342 0 R (page.25) 350 0 R] /Limits [(page.20) (page.25)] >> endobj 692 0 obj << /Names [(page.26) 368 0 R (page.27) 386 0 R (page.28) 399 0 R (page.29) 406 0 R (page.3) 167 0 R (page.30) 416 0 R] /Limits [(page.26) (page.30)] >> endobj 693 0 obj << /Names [(page.31) 420 0 R (page.32) 426 0 R (page.33) 434 0 R (page.34) 442 0 R (page.35) 448 0 R (page.36) 453 0 R] /Limits [(page.31) (page.36)] >> endobj 694 0 obj << /Names [(page.37) 458 0 R (page.38) 465 0 R (page.39) 472 0 R (page.4) 177 0 R (page.40) 477 0 R (page.41) 482 0 R] /Limits [(page.37) (page.41)] >> endobj 695 0 obj << /Names [(page.42) 486 0 R (page.43) 490 0 R (page.44) 495 0 R (page.45) 499 0 R (page.46) 503 0 R (page.47) 507 0 R] /Limits [(page.42) (page.47)] >> endobj 696 0 obj << /Names [(page.48) 511 0 R (page.49) 516 0 R (page.5) 189 0 R (page.50) 526 0 R (page.51) 530 0 R (page.52) 534 0 R] /Limits [(page.48) (page.52)] >> endobj 697 0 obj << /Names [(page.53) 538 0 R (page.54) 542 0 R (page.55) 546 0 R (page.56) 552 0 R (page.57) 556 0 R (page.58) 560 0 R] /Limits [(page.53) (page.58)] >> endobj 698 0 obj << /Names [(page.59) 564 0 R (page.6) 198 0 R (page.60) 568 0 R (page.61) 572 0 R (page.62) 577 0 R (page.63) 581 0 R] /Limits [(page.59) (page.63)] >> endobj 699 0 obj << /Names [(page.64) 585 0 R (page.65) 589 0 R (page.66) 593 0 R (page.67) 597 0 R (page.68) 602 0 R (page.69) 606 0 R] /Limits [(page.64) (page.69)] >> endobj 700 0 obj << /Names [(page.7) 204 0 R (page.70) 612 0 R (page.8) 211 0 R (page.9) 222 0 R (refs) 147 0 R (section*.1) 351 0 R] /Limits [(page.7) (section*.1)] >> endobj 701 0 obj << /Names [(section*.2) 353 0 R (section*.3) 369 0 R (section*.4) 371 0 R (section*.5) 387 0 R (section*.6) 613 0 R (section.0) 6 0 R] /Limits [(section*.2) (section.0)] >> endobj 702 0 obj << /Names [(section.1) 10 0 R (section.10) 46 0 R (section.11) 50 0 R (section.12) 54 0 R (section.13) 58 0 R (section.14) 62 0 R] /Limits [(section.1) (section.14)] >> endobj 703 0 obj << /Names [(section.15) 66 0 R (section.16) 70 0 R (section.17) 74 0 R (section.18) 78 0 R (section.19) 102 0 R (section.2) 14 0 R] /Limits [(section.15) (section.2)] >> endobj 704 0 obj << /Names [(section.20) 106 0 R (section.3) 18 0 R (section.4) 22 0 R (section.5) 26 0 R (section.6) 30 0 R (section.7) 34 0 R] /Limits [(section.20) (section.7)] >> endobj 705 0 obj << /Names [(section.8) 38 0 R (section.9) 42 0 R (subsection.18.1) 82 0 R (subsection.18.2) 86 0 R (subsection.18.3) 90 0 R (subsection.18.4) 94 0 R] /Limits [(section.8) (subsection.18.4)] >> endobj 706 0 obj << /Names [(subsection.18.5) 98 0 R (theorem.1) 170 0 R (theorem.2) 466 0 R] /Limits [(subsection.18.5) (theorem.2)] >> endobj 707 0 obj << /Kids [686 0 R 687 0 R 688 0 R 689 0 R 690 0 R 691 0 R] /Limits [(Doc-Start) (page.25)] >> endobj 708 0 obj << /Kids [692 0 R 693 0 R 694 0 R 695 0 R 696 0 R 697 0 R] /Limits [(page.26) (page.58)] >> endobj 709 0 obj << /Kids [698 0 R 699 0 R 700 0 R 701 0 R 702 0 R 703 0 R] /Limits [(page.59) (section.2)] >> endobj 710 0 obj << /Kids [704 0 R 705 0 R 706 0 R] /Limits [(section.20) (theorem.2)] >> endobj 711 0 obj << /Kids [707 0 R 708 0 R 709 0 R 710 0 R] /Limits [(Doc-Start) (theorem.2)] >> endobj 712 0 obj << /Dests 711 0 R >> endobj 713 0 obj << /Type /Catalog /Pages 684 0 R /Outlines 685 0 R /Names 712 0 R /PageMode/UseOutlines /OpenAction 109 0 R >> endobj 714 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.3)/Keywords() /CreationDate (D:20091104133016+11'00') /ModDate (D:20091104133016+11'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX using libpoppler, Version 3.141592-1.40.3-2.2 (Web2C 7.5.6) kpathsea version 3.5.6) >> endobj xref 0 715 0000000001 65535 f 0000000002 00000 f 0000000003 00000 f 0000000004 00000 f 0000000000 00000 f 0000000015 00000 n 0000012292 00000 n 0000373385 00000 n 0000000060 00000 n 0000000100 00000 n 0000012343 00000 n 0000373299 00000 n 0000000145 00000 n 0000000177 00000 n 0000012399 00000 n 0000373211 00000 n 0000000223 00000 n 0000000256 00000 n 0000021898 00000 n 0000373123 00000 n 0000000302 00000 n 0000000337 00000 n 0000030671 00000 n 0000373035 00000 n 0000000383 00000 n 0000000414 00000 n 0000034462 00000 n 0000372947 00000 n 0000000460 00000 n 0000000490 00000 n 0000051038 00000 n 0000372859 00000 n 0000000536 00000 n 0000000562 00000 n 0000057663 00000 n 0000372771 00000 n 0000000608 00000 n 0000000636 00000 n 0000071331 00000 n 0000372683 00000 n 0000000682 00000 n 0000000725 00000 n 0000084823 00000 n 0000372595 00000 n 0000000771 00000 n 0000000808 00000 n 0000096095 00000 n 0000372507 00000 n 0000000855 00000 n 0000000908 00000 n 0000102297 00000 n 0000372419 00000 n 0000000955 00000 n 0000001013 00000 n 0000112230 00000 n 0000372331 00000 n 0000001060 00000 n 0000001090 00000 n 0000128800 00000 n 0000372243 00000 n 0000001137 00000 n 0000001187 00000 n 0000132209 00000 n 0000372155 00000 n 0000001234 00000 n 0000001264 00000 n 0000140079 00000 n 0000372067 00000 n 0000001311 00000 n 0000001340 00000 n 0000167607 00000 n 0000371979 00000 n 0000001387 00000 n 0000001413 00000 n 0000170458 00000 n 0000371891 00000 n 0000001460 00000 n 0000001494 00000 n 0000170514 00000 n 0000371765 00000 n 0000001541 00000 n 0000001593 00000 n 0000172072 00000 n 0000371691 00000 n 0000001645 00000 n 0000001711 00000 n 0000175066 00000 n 0000371604 00000 n 0000001763 00000 n 0000001830 00000 n 0000177664 00000 n 0000371517 00000 n 0000001882 00000 n 0000001950 00000 n 0000180384 00000 n 0000371430 00000 n 0000002002 00000 n 0000002069 00000 n 0000185600 00000 n 0000371355 00000 n 0000002121 00000 n 0000002193 00000 n 0000189911 00000 n 0000371263 00000 n 0000002241 00000 n 0000002298 00000 n 0000195314 00000 n 0000371184 00000 n 0000002346 00000 n 0000002396 00000 n 0000003743 00000 n 0000004043 00000 n 0000004193 00000 n 0000004342 00000 n 0000004492 00000 n 0000004642 00000 n 0000004792 00000 n 0000004941 00000 n 0000005091 00000 n 0000005241 00000 n 0000005391 00000 n 0000005541 00000 n 0000005692 00000 n 0000005843 00000 n 0000005994 00000 n 0000006144 00000 n 0000006295 00000 n 0000006446 00000 n 0000006597 00000 n 0000006746 00000 n 0000006897 00000 n 0000007048 00000 n 0000007199 00000 n 0000010942 00000 n 0000007450 00000 n 0000002449 00000 n 0000007344 00000 n 0000007397 00000 n 0000368983 00000 n 0000367706 00000 n 0000367563 00000 n 0000368275 00000 n 0000367420 00000 n 0000369126 00000 n 0000366412 00000 n 0000368558 00000 n 0000369414 00000 n 0000214866 00000 n 0000011095 00000 n 0000011248 00000 n 0000011426 00000 n 0000011635 00000 n 0000011786 00000 n 0000011935 00000 n 0000012088 00000 n 0000012455 00000 n 0000010754 00000 n 0000007613 00000 n 0000012239 00000 n 0000369270 00000 n 0000368698 00000 n 0000366990 00000 n 0000215432 00000 n 0000215033 00000 n 0000017520 00000 n 0000017298 00000 n 0000012605 00000 n 0000017410 00000 n 0000367990 00000 n 0000367277 00000 n 0000017463 00000 n 0000021482 00000 n 0000021633 00000 n 0000019940 00000 n 0000021954 00000 n 0000019800 00000 n 0000017683 00000 n 0000021784 00000 n 0000021837 00000 n 0000021047 00000 n 0000021265 00000 n 0000021312 00000 n 0000021384 00000 n 0000021461 00000 n 0000025943 00000 n 0000027344 00000 n 0000027609 00000 n 0000025811 00000 n 0000022119 00000 n 0000027495 00000 n 0000027548 00000 n 0000026985 00000 n 0000027203 00000 n 0000027250 00000 n 0000027323 00000 n 0000030727 00000 n 0000030506 00000 n 0000027761 00000 n 0000030618 00000 n 0000038575 00000 n 0000038727 00000 n 0000034514 00000 n 0000034297 00000 n 0000030864 00000 n 0000034409 00000 n 0000369531 00000 n 0000038879 00000 n 0000039030 00000 n 0000039234 00000 n 0000038419 00000 n 0000034651 00000 n 0000039181 00000 n 0000042698 00000 n 0000042850 00000 n 0000043002 00000 n 0000043154 00000 n 0000043306 00000 n 0000043458 00000 n 0000043610 00000 n 0000043814 00000 n 0000042518 00000 n 0000039371 00000 n 0000043761 00000 n 0000047457 00000 n 0000050833 00000 n 0000047662 00000 n 0000047325 00000 n 0000043951 00000 n 0000047609 00000 n 0000051094 00000 n 0000050701 00000 n 0000047799 00000 n 0000050985 00000 n 0000367849 00000 n 0000367133 00000 n 0000053968 00000 n 0000056201 00000 n 0000054172 00000 n 0000053836 00000 n 0000051283 00000 n 0000054119 00000 n 0000368418 00000 n 0000366702 00000 n 0000057715 00000 n 0000056089 00000 n 0000054387 00000 n 0000057610 00000 n 0000369648 00000 n 0000057236 00000 n 0000057465 00000 n 0000057512 00000 n 0000057589 00000 n 0000059753 00000 n 0000061546 00000 n 0000063341 00000 n 0000065185 00000 n 0000059641 00000 n 0000057906 00000 n 0000065132 00000 n 0000061171 00000 n 0000061400 00000 n 0000061447 00000 n 0000061524 00000 n 0000062966 00000 n 0000063195 00000 n 0000063242 00000 n 0000063319 00000 n 0000064757 00000 n 0000064986 00000 n 0000065033 00000 n 0000065110 00000 n 0000069182 00000 n 0000070976 00000 n 0000071126 00000 n 0000071387 00000 n 0000069042 00000 n 0000065363 00000 n 0000071278 00000 n 0000070601 00000 n 0000070830 00000 n 0000070877 00000 n 0000070954 00000 n 0000074899 00000 n 0000075051 00000 n 0000075253 00000 n 0000074759 00000 n 0000071578 00000 n 0000075200 00000 n 0000368131 00000 n 0000078797 00000 n 0000078949 00000 n 0000079101 00000 n 0000079252 00000 n 0000079404 00000 n 0000079556 00000 n 0000079708 00000 n 0000079859 00000 n 0000080063 00000 n 0000078609 00000 n 0000075416 00000 n 0000080010 00000 n 0000084318 00000 n 0000084468 00000 n 0000084620 00000 n 0000084879 00000 n 0000084170 00000 n 0000080265 00000 n 0000084770 00000 n 0000088994 00000 n 0000088829 00000 n 0000085055 00000 n 0000088941 00000 n 0000369765 00000 n 0000092331 00000 n 0000092536 00000 n 0000092199 00000 n 0000089131 00000 n 0000092483 00000 n 0000095889 00000 n 0000096147 00000 n 0000095757 00000 n 0000092647 00000 n 0000096042 00000 n 0000366556 00000 n 0000366845 00000 n 0000101634 00000 n 0000099182 00000 n 0000099017 00000 n 0000096310 00000 n 0000099129 00000 n 0000101786 00000 n 0000101940 00000 n 0000102092 00000 n 0000102353 00000 n 0000101478 00000 n 0000099332 00000 n 0000102244 00000 n 0000215375 00000 n 0000105490 00000 n 0000105695 00000 n 0000105358 00000 n 0000102490 00000 n 0000105642 00000 n 0000111875 00000 n 0000108649 00000 n 0000115144 00000 n 0000112026 00000 n 0000112457 00000 n 0000108509 00000 n 0000105832 00000 n 0000112177 00000 n 0000112282 00000 n 0000112339 00000 n 0000112401 00000 n 0000369882 00000 n 0000111515 00000 n 0000111733 00000 n 0000111780 00000 n 0000111853 00000 n 0000119070 00000 n 0000116646 00000 n 0000118719 00000 n 0000118870 00000 n 0000122130 00000 n 0000125112 00000 n 0000119305 00000 n 0000115004 00000 n 0000112635 00000 n 0000119017 00000 n 0000119131 00000 n 0000119188 00000 n 0000119248 00000 n 0000116361 00000 n 0000116578 00000 n 0000116625 00000 n 0000118358 00000 n 0000118577 00000 n 0000118624 00000 n 0000118697 00000 n 0000125471 00000 n 0000123378 00000 n 0000125267 00000 n 0000128596 00000 n 0000125651 00000 n 0000121990 00000 n 0000119523 00000 n 0000125418 00000 n 0000125532 00000 n 0000125589 00000 n 0000123067 00000 n 0000123310 00000 n 0000123357 00000 n 0000124825 00000 n 0000125043 00000 n 0000125090 00000 n 0000215090 00000 n 0000128855 00000 n 0000128464 00000 n 0000125870 00000 n 0000128747 00000 n 0000215204 00000 n 0000131848 00000 n 0000132002 00000 n 0000132265 00000 n 0000131708 00000 n 0000128979 00000 n 0000132156 00000 n 0000215261 00000 n 0000139105 00000 n 0000139289 00000 n 0000139480 00000 n 0000139671 00000 n 0000139841 00000 n 0000135882 00000 n 0000135717 00000 n 0000132402 00000 n 0000135829 00000 n 0000140131 00000 n 0000138941 00000 n 0000136019 00000 n 0000140026 00000 n 0000369999 00000 n 0000143956 00000 n 0000144163 00000 n 0000143824 00000 n 0000140294 00000 n 0000144110 00000 n 0000147801 00000 n 0000147952 00000 n 0000148104 00000 n 0000151045 00000 n 0000148309 00000 n 0000147653 00000 n 0000144287 00000 n 0000148256 00000 n 0000151197 00000 n 0000151348 00000 n 0000155568 00000 n 0000155719 00000 n 0000151553 00000 n 0000150897 00000 n 0000148472 00000 n 0000151500 00000 n 0000155869 00000 n 0000156021 00000 n 0000156224 00000 n 0000155412 00000 n 0000151690 00000 n 0000156171 00000 n 0000161463 00000 n 0000159412 00000 n 0000159247 00000 n 0000156400 00000 n 0000159359 00000 n 0000161614 00000 n 0000161816 00000 n 0000161323 00000 n 0000159575 00000 n 0000161763 00000 n 0000368839 00000 n 0000370116 00000 n 0000167250 00000 n 0000164925 00000 n 0000164703 00000 n 0000161940 00000 n 0000164815 00000 n 0000164868 00000 n 0000366268 00000 n 0000167401 00000 n 0000167663 00000 n 0000167110 00000 n 0000165114 00000 n 0000167554 00000 n 0000170252 00000 n 0000170570 00000 n 0000170120 00000 n 0000167774 00000 n 0000170405 00000 n 0000214976 00000 n 0000172124 00000 n 0000171907 00000 n 0000170681 00000 n 0000172019 00000 n 0000173581 00000 n 0000173416 00000 n 0000172235 00000 n 0000173528 00000 n 0000175118 00000 n 0000174901 00000 n 0000173666 00000 n 0000175013 00000 n 0000370233 00000 n 0000176435 00000 n 0000176270 00000 n 0000175229 00000 n 0000176382 00000 n 0000177716 00000 n 0000177499 00000 n 0000176520 00000 n 0000177611 00000 n 0000179052 00000 n 0000178887 00000 n 0000177827 00000 n 0000178999 00000 n 0000180436 00000 n 0000180219 00000 n 0000179137 00000 n 0000180331 00000 n 0000181298 00000 n 0000181133 00000 n 0000180547 00000 n 0000181245 00000 n 0000182443 00000 n 0000185714 00000 n 0000182331 00000 n 0000181383 00000 n 0000185547 00000 n 0000185652 00000 n 0000370350 00000 n 0000185184 00000 n 0000185405 00000 n 0000185452 00000 n 0000185525 00000 n 0000186786 00000 n 0000186621 00000 n 0000185854 00000 n 0000186733 00000 n 0000187945 00000 n 0000187780 00000 n 0000186871 00000 n 0000187892 00000 n 0000188474 00000 n 0000188309 00000 n 0000188030 00000 n 0000188421 00000 n 0000189964 00000 n 0000189746 00000 n 0000188559 00000 n 0000189858 00000 n 0000191183 00000 n 0000191018 00000 n 0000190088 00000 n 0000191130 00000 n 0000192575 00000 n 0000192410 00000 n 0000191268 00000 n 0000192522 00000 n 0000370467 00000 n 0000193719 00000 n 0000193953 00000 n 0000193587 00000 n 0000192660 00000 n 0000193900 00000 n 0000195367 00000 n 0000195149 00000 n 0000194064 00000 n 0000195261 00000 n 0000196516 00000 n 0000196351 00000 n 0000195478 00000 n 0000196463 00000 n 0000198061 00000 n 0000197896 00000 n 0000196601 00000 n 0000198008 00000 n 0000199612 00000 n 0000199447 00000 n 0000198146 00000 n 0000199559 00000 n 0000201189 00000 n 0000201024 00000 n 0000199697 00000 n 0000201136 00000 n 0000370584 00000 n 0000202499 00000 n 0000202334 00000 n 0000201274 00000 n 0000202446 00000 n 0000203851 00000 n 0000203686 00000 n 0000202584 00000 n 0000203798 00000 n 0000205477 00000 n 0000205312 00000 n 0000203936 00000 n 0000205424 00000 n 0000207163 00000 n 0000206998 00000 n 0000205562 00000 n 0000207110 00000 n 0000208429 00000 n 0000208264 00000 n 0000207248 00000 n 0000208376 00000 n 0000210020 00000 n 0000209855 00000 n 0000208514 00000 n 0000209967 00000 n 0000370701 00000 n 0000211611 00000 n 0000211446 00000 n 0000210105 00000 n 0000211558 00000 n 0000212446 00000 n 0000212281 00000 n 0000211696 00000 n 0000212393 00000 n 0000214442 00000 n 0000214629 00000 n 0000215489 00000 n 0000214302 00000 n 0000212531 00000 n 0000214813 00000 n 0000214919 00000 n 0000215147 00000 n 0000215318 00000 n 0000215639 00000 n 0000215802 00000 n 0000215929 00000 n 0000216044 00000 n 0000216207 00000 n 0000216613 00000 n 0000216826 00000 n 0000216849 00000 n 0000216892 00000 n 0000216923 00000 n 0000217576 00000 n 0000217727 00000 n 0000218450 00000 n 0000218776 00000 n 0000219347 00000 n 0000219372 00000 n 0000220013 00000 n 0000220408 00000 n 0000221025 00000 n 0000221673 00000 n 0000222315 00000 n 0000222804 00000 n 0000223349 00000 n 0000226474 00000 n 0000226704 00000 n 0000237207 00000 n 0000237591 00000 n 0000241393 00000 n 0000241640 00000 n 0000244086 00000 n 0000244391 00000 n 0000248501 00000 n 0000248748 00000 n 0000259768 00000 n 0000260116 00000 n 0000262320 00000 n 0000262544 00000 n 0000266841 00000 n 0000267105 00000 n 0000277277 00000 n 0000277633 00000 n 0000293419 00000 n 0000293990 00000 n 0000298064 00000 n 0000298350 00000 n 0000300213 00000 n 0000300437 00000 n 0000303575 00000 n 0000303853 00000 n 0000308120 00000 n 0000308371 00000 n 0000313715 00000 n 0000314190 00000 n 0000315400 00000 n 0000315624 00000 n 0000316989 00000 n 0000317221 00000 n 0000318901 00000 n 0000319153 00000 n 0000322199 00000 n 0000322434 00000 n 0000333982 00000 n 0000334349 00000 n 0000350439 00000 n 0000351063 00000 n 0000365696 00000 n 0000370802 00000 n 0000370920 00000 n 0000371038 00000 n 0000371108 00000 n 0000373457 00000 n 0000373659 00000 n 0000373841 00000 n 0000374019 00000 n 0000374187 00000 n 0000374355 00000 n 0000374525 00000 n 0000374694 00000 n 0000374864 00000 n 0000375033 00000 n 0000375203 00000 n 0000375372 00000 n 0000375542 00000 n 0000375711 00000 n 0000375881 00000 n 0000376050 00000 n 0000376240 00000 n 0000376426 00000 n 0000376613 00000 n 0000376796 00000 n 0000377006 00000 n 0000377143 00000 n 0000377254 00000 n 0000377363 00000 n 0000377474 00000 n 0000377564 00000 n 0000377661 00000 n 0000377699 00000 n 0000377827 00000 n trailer << /Size 715 /Root 713 0 R /Info 714 0 R /ID [ ] >> startxref 378158 %%EOF nauty24r2/multig.c0000600000604200001440000004722411274163463012765 0ustar bdmusers/* multig.c version 1.2; B D McKay, Apr 5, 2007 */ #define USAGE \ "multig [-q] [-u|-T|-G|-A|-B] [-e#|-e#:#]\ [-m#] [-f#] [-D#|-r#|-l#] [infile [outfile]]" #define HELPTEXT \ " Read undirected loop-free graphs and replace their edges with multiple\n\ edges in all possible ways (multiplicity at least 1).\n\ Isomorphic multigraphs derived from the same input are suppressed.\n\ If the input graphs are non-isomorphic then the output graphs are also.\n\ \n\ -e# | -e#:# specify a value or range of the total number of edges\n\ counting multiplicities\n\ -m# maximum edge multiplicity (minimum is 1)\n\ -D# upper bound on maximum degree\n\ -r# make regular of specified degree (incompatible with -l, -D, -e)\n\ -l# make regular multigraphs with multiloops, degree #\n\ (incompatible with -r, -D, -e)\n\ Either -l, -r, -D, -e or -m with a finite maximum must be given\n\ -f# Use the group that fixes the first # vertices setwise\n\ -T use a simple text output format (nv ne {v1 v2 mult})\n\ -G like -T but includes group size as third item (if less than 10^10)\n\ The group size does not include exchange of isolated vertices.\n\ -A write as the upper triangle of an adjacency matrix, row by row,\n\ including the diagonal, and preceded by the number of vertices\n\ -B write as an integer matrix preceded by the number of rows and\n\ number of columns, where -f determines the number of rows\n\ -u no output, just count them\n\ -q suppress auxiliary information\n" /*************************************************************************/ #include "gtools.h" #include "naugroup.h" typedef struct { long hi,lo; } bigint; #define ZEROBIG(big) big.hi = big.lo = 0L #define ADDBIG(big,extra) if ((big.lo += (extra)) >= 1000000000L) \ { ++big.hi; big.lo -= 1000000000L;} #define PRINTBIG(file,big) if (big.hi == 0) \ fprintf(file,"%ld",big.lo); else fprintf(file,"%ld%09ld",big.hi,big.lo) static bigint nin,nout; FILE *outfile; #define MAXNV 128 #define MAXNE 1024 static int v0[MAXNE+MAXNV],v1[MAXNE+MAXNV]; static int edgeno[MAXNV][MAXNV]; static int lastlev[MAXNE]; static int ix[MAXNE+MAXNV],nix; static boolean first; static permutation lastreject[MAXNV]; static boolean lastrejok; static unsigned long groupsize; static unsigned long newgroupsize; static boolean Gswitch,Tswitch,Aswitch,Bswitch; static int Brows; #define GROUPTEST_NOT #ifdef GROUPTEST static long long totallab; #endif #define PATHCOUNTS_NOT #ifdef PATHCOUNTS static long long count0,count1,count2,count3,count4,count5; static long oldlo; #endif /* If OUTPROC is defined at compile time, and -u is not used, the * procedure OUTPROC is called for each graph. This must be linked * by the compiler. The arguments are * f = open output file * n = number of vertices * ne = number of edges * gp = group size ignoring isolated vertices (note: may have overflowed) * v0[*], v1[*], ix[*] = integer arrays. The edges are * v0[i]-v1[i] with multiplicity ix[i] for i=0..ne-1. ix[i]>0 always. */ #ifdef OUTPROC extern void OUTPROC(FILE*,int,int,unsigned long,int*,int*,int*); #endif /**************************************************************************/ void writeautom(permutation *p, int n) /* Called by allgroup. */ { int i; for (i = 0; i < n; ++i) printf(" %2d",p[i]); printf("\n"); } /**************************************************************************/ static boolean ismax(permutation *p, int n) /* test if x^p <= x */ { int i,k; for (i = 0; i < nix; ++i) { k = edgeno[p[v1[i]]][p[v0[i]]]; if (ix[k] > ix[i]) return FALSE; else if (ix[k] < ix[i]) return TRUE; } ++newgroupsize; return TRUE; } /**************************************************************************/ void testmax(permutation *p, int n, int *abort) /* Called by allgroup2. */ { int i; if (first) { /* only the identity */ first = FALSE; return; } if (!ismax(p,n)) { *abort = 1; for (i = 0; i < n; ++i) lastreject[i] = p[i]; lastrejok = TRUE; } } /**************************************************************************/ void printam(FILE *f, int n, int ne, int *ix) /* Write adjacency matrix formats */ { int i,j; if (Aswitch) { fprintf(f,"%d ",n); for (i = 0; i < n; ++i) for (j = i; j < n; ++j) fprintf(f," %d",ix[edgeno[i][j]]); fprintf(f,"\n"); } else { if (Brows <= 0 || Brows > n) { fprintf(stderr,">E multig: impossible matrix size for output\n"); exit(1); } fprintf(f,"%d %d",Brows,n-Brows); for (i = 0; i < Brows; ++i) { fprintf(f," "); for (j = Brows; j < n; ++j) fprintf(f," %d",ix[edgeno[i][j]]); } fprintf(f,"\n"); } } /**************************************************************************/ static void trythisone(grouprec *group, boolean lswitch, int *deg, int maxdeg, int ne, int n) /* Try one solution, accept if minimal. */ { int i,ne2; boolean accept; nix = ne; newgroupsize = 1; if (!group || groupsize == 1) accept = TRUE; else if (lastrejok && !ismax(lastreject,n)) accept = FALSE; else if (lastrejok && groupsize == 2) accept = TRUE; else { newgroupsize = 1; first = TRUE; if (allgroup2(group,testmax) == 0) accept = TRUE; else accept = FALSE; } if (accept) { #ifdef GROUPTEST if (groupsize % newgroupsize != 0) gt_abort("group size error\n"); totallab += groupsize/newgroupsize; #endif ADDBIG(nout,1); if (outfile) { ne2 = ne; if (lswitch) for (i = 0; i < n; ++i) if (deg[i] < maxdeg) { v0[ne2] = v1[ne2] = i; ix[ne2] = (maxdeg-deg[i])/2; ++ne2; } #ifdef OUTPROC OUTPROC(outfile,n,ne2,newgroupsize,v0,v1,ix); #else if (Aswitch || Bswitch) printam(outfile,n,ne2,ix); else { fprintf(outfile,"%d %d",n,ne2); if (Gswitch) fprintf(outfile," %lu",newgroupsize); for (i = 0; i < ne2; ++i) fprintf(outfile," %d %d %d",v0[i],v1[i],ix[i]); fprintf(outfile,"\n"); } #endif } return; } else return; } /**************************************************************************/ static void scan(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n) /* Recursive scan for default case */ { int left; long min,max,k; if (level == ne) { trythisone(group,FALSE,NULL,0,ne,n); return; } left = ne - level - 1; min = minedges - sofar - maxmult*left; if (min < 1) min = 1; max = maxedges - sofar - left; if (max > maxmult) max = maxmult; for (k = min; k <= max; ++k) { ix[level] = k; scan(level+1,ne,minedges,maxedges,sofar+k,maxmult,group,n); } return; } /**************************************************************************/ static void scan_md(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n, int *deg, int maxdeg) /* Recursive scan, maxdeg version */ { int left; int min,max,k; int x1,x2; if (level == ne) { trythisone(group,FALSE,deg,maxdeg,ne,n); return; } x1 = v0[level]; x2 = v1[level]; left = ne - level - 1; min = minedges - sofar - maxmult*left; if (min < 1) min = 1; max = maxedges - sofar - left; if (max > maxmult) max = maxmult; if (deg[x1] + max - 1 > maxdeg) max = maxdeg - deg[x1] + 1; if (deg[x2] + max - 1 > maxdeg) max = maxdeg - deg[x2] + 1; for (k = min; k <= max; ++k) { ix[level] = k; deg[x1] += k-1; deg[x2] += k-1; scan_md(level+1,ne,minedges,maxedges,sofar+k,maxmult,group, n,deg,maxdeg); deg[x1] -= k-1; deg[x2] -= k-1; } return; } /**************************************************************************/ static void scan_lp(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n, int *deg, int maxdeg) /* Recursive scan, regular-with-loops version. */ { int left; long min,max,k; int x1,x2; boolean odd,even; if (level == ne) { trythisone(group,TRUE,deg,maxdeg,ne,n); return; } x1 = v0[level]; x2 = v1[level]; left = ne - level - 1; min = minedges - sofar - maxmult*left; if (min < 1) min = 1; max = maxedges - sofar - left; if (max > maxmult) max = maxmult; if (deg[x1] + max - 1 > maxdeg) max = maxdeg - deg[x1] + 1; if (deg[x2] + max - 1 > maxdeg) max = maxdeg - deg[x2] + 1; odd = even = FALSE; if (lastlev[x1] == level) { if (((maxdeg-deg[x1])&1) == 1) even = TRUE; else odd = TRUE; } if (lastlev[x2] == level) { if (((maxdeg-deg[x2])&1) == 1) even = TRUE; else odd = TRUE; } if (even && odd) return; for (k = min; k <= max; ++k) { if (even && (k&1) == 1) continue; if (odd && (k&1) == 0) continue; ix[level] = k; deg[x1] += k-1; deg[x2] += k-1; scan_lp(level+1,ne,minedges,maxedges,sofar+k,maxmult,group, n,deg,maxdeg); deg[x1] -= k-1; deg[x2] -= k-1; } return; } /**************************************************************************/ static void scan_reg(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n, int *delta, int *def, int maxdeg) /* Recursive scan, regular version. */ { int left; long min,max,k; int x1,x2; if (level == ne) { trythisone(group,FALSE,NULL,maxdeg,ne,n); return; } x1 = v0[level]; x2 = v1[level]; left = ne - level - 1; min = minedges - sofar - maxmult*left; if (min < 1) min = 1; max = maxedges - sofar - left; if (max > maxmult) max = maxmult; if (max > def[x1] + 1) max = def[x1] + 1; if (max > def[x2] + 1) max = def[x2] + 1; if (min < def[x2] + 1 - delta[x1]) min = def[x2] + 1 - delta[x1]; if (min < def[x1] + 1 - delta[x2]) min = def[x1] + 1 - delta[x2]; if (lastlev[x1] == level && min < def[x1] + 1) min = def[x1] + 1; if (lastlev[x2] == level && min < def[x2] + 1) min = def[x2] + 1; for (k = min; k <= max; ++k) { ix[level] = k; delta[x1] += k-1 - def[x2]; delta[x2] += k-1 - def[x1]; def[x1] -= k-1; def[x2] -= k-1; scan_reg(level+1,ne,minedges,maxedges,sofar+k,maxmult,group, n,delta,def,maxdeg); def[x1] += k-1; def[x2] += k-1; delta[x1] -= k-1 - def[x2]; delta[x2] -= k-1 - def[x1]; } return; } /**************************************************************************/ static void multi(graph *g, int nfixed, long minedges, long maxedges, long maxmult, int maxdeg, boolean lswitch, int m, int n) { static DEFAULTOPTIONS_GRAPH(options); statsblk stats; setword workspace[100]; grouprec *group; int ne; int i,j,k,j0,j1,thisdeg,maxd,x0,x1; set *gi; int lab[MAXNV],ptn[MAXNV],orbits[MAXNV],deg[MAXNV]; int delta[MAXNV],def[MAXNV]; set active[(MAXNV+WORDSIZE-1)/WORDSIZE]; boolean isreg; #ifdef PATHCOUNTS ++count0; #endif j0 = -1; /* last vertex with degree 0 */ j1 = n; /* first vertex with degree > 0 */ ne = 0; maxd = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { thisdeg = 0; for (j = 0; j < m; ++j) thisdeg += POPCOUNT(gi[j]); deg[i] = thisdeg; if (thisdeg > maxd) maxd = thisdeg; if (thisdeg == 0) lab[++j0] = i; else lab[--j1] = i; ne += thisdeg; } ne /= 2; if (maxdeg >= 0 && maxd > maxdeg) return; #ifdef PATHCOUNTS ++count1; #endif if (ne == 0 && minedges <= 0 && (!lswitch || lswitch && (maxdeg&1) == 0)) { trythisone(NULL,lswitch,deg,maxdeg,0,n); return; } #ifdef PATHCOUNTS ++count2; #endif if (Aswitch || Bswitch) for (i = 0; i < n; ++i) for (j = 0; j < n; ++j) edgeno[i][j] = -1; k = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { for (j = i; (j = nextelement(gi,m,j)) >= 0; ) { v0[k] = i; v1[k] = j; edgeno[i][j] = edgeno[j][i] = k; lastlev[i] = lastlev[j] = k; ++k; } } isreg = !lswitch && (maxdeg >= 0 && 2*minedges == n*(long)maxdeg); /* Case of regular multigraphs */ if (isreg) /* regular case */ /* Condition: def(v) <= total def of neighbours */ { for (i = 0; i < n; ++i) { def[i] = maxdeg - deg[i]; delta[i] = -def[i]; } for (i = 0; i < k; ++i) { x0 = v0[i]; x1 = v1[i]; delta[x0] += def[x1]; delta[x1] += def[x0]; } for (i = 0; i < n; ++i) if (delta[i] < 0) return; } if ((isreg || lswitch) && (maxdeg & n & 1) == 1) return; if (isreg && j0 >= 0 && maxdeg > 0) return; if (lswitch && j0 >= 0 && (maxdeg&1) == 1) return; #ifdef PATHCOUNTS ++count3; #endif if (maxedges == NOLIMIT) maxedges = ne*maxmult; if (maxmult == NOLIMIT) maxmult = maxedges - ne + 1; if (maxedges < ne || ne*maxmult < minedges) return; #ifdef PATHCOUNTS ++count4; #endif if (n > MAXNV || ne > MAXNE) { fprintf(stderr,">E multig: MAXNV or MAXNE exceeded\n"); exit(1); } nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); for (i = 0; i < n; ++i) ptn[i] = 1; ptn[n-1] = 0; EMPTYSET(active,m); if (j0 != n-1) ADDELEMENT(active,j0+1); for (i = 0; i <= j0; ++i) ptn[i] = 0; for (i = j0+1; i < n; ++i) if (lab[i] < nfixed) break; if (i != j0+1 && i != n) { ptn[i-1] = 0; ADDELEMENT(active,i); } options.defaultptn = FALSE; options.userautomproc = groupautomproc; options.userlevelproc = grouplevelproc; nauty(g,lab,ptn,active,orbits,&options,&stats,workspace,100,m,n,NULL); if (stats.grpsize2 == 0) groupsize = stats.grpsize1 + 0.1; else groupsize = 0; group = groupptr(FALSE); makecosetreps(group); lastrejok = FALSE; if (isreg) scan_reg(0,ne,minedges,maxedges,0,maxmult,group,n,delta,def,maxdeg); else if (lswitch) scan_lp(0,ne,minedges,maxedges,0,maxmult,group,n,deg,maxdeg); else if (maxdeg >= 0) scan_md(0,ne,minedges,maxedges,0,maxmult,group,n,deg,maxdeg); else scan(0,ne,minedges,maxedges,0,maxmult,group,n); } /**************************************************************************/ int main(int argc, char *argv[]) { graph *g; int m,n,codetype; int argnum,j,nfixed,maxdeg,regdeg,ldeg; char *arg,sw; boolean badargs; boolean fswitch,uswitch,eswitch,qswitch,mswitch,Dswitch; boolean lswitch,rswitch; long minedges,maxedges,maxmult; double t; char *infilename,*outfilename; FILE *infile; char msg[201]; int msglen; HELP; nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); rswitch = fswitch = Tswitch = Gswitch = FALSE; uswitch = eswitch = mswitch = qswitch = FALSE; lswitch = Aswitch = Bswitch = Dswitch = FALSE; infilename = outfilename = NULL; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWLONG('m',mswitch,maxmult,"multig -m") else SWBOOLEAN('q',qswitch) else SWBOOLEAN('u',uswitch) else SWBOOLEAN('T',Tswitch) else SWBOOLEAN('G',Gswitch) else SWBOOLEAN('A',Aswitch) else SWBOOLEAN('B',Bswitch) else SWINT('f',fswitch,nfixed,"multig -f") else SWINT('D',Dswitch,maxdeg,"multig -D") else SWINT('r',rswitch,regdeg,"multig -r") else SWINT('l',lswitch,ldeg,"multig -l") else SWRANGE('e',":-",eswitch,minedges,maxedges,"multig -e") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if ((Gswitch!=0) + (Tswitch!=0) + (uswitch!=0) + (Aswitch!=0) + (Bswitch!=0) >= 2) gt_abort(">E multig: -G, -T, -A, -B and -u are incompatible\n"); if (!Tswitch && !Gswitch && !Aswitch && !Bswitch && !uswitch) gt_abort(">E multig: must use -A, -B, -T, -G or -u\n"); if (rswitch && (Dswitch || eswitch)) gt_abort(">E multig: -r is incompatible with -D and -e\n"); if (lswitch && (rswitch || Dswitch || eswitch)) gt_abort(">E multig: -l is incompatible with -r, -D and -e\n"); if (!eswitch) { minedges = 0; maxedges = NOLIMIT; } if (!mswitch) maxmult = NOLIMIT; if (!fswitch) nfixed = 0; if (Bswitch && nfixed == 0) gt_abort(">E multig: -B requires -f# with #>0\n"); if (fswitch) Brows = nfixed; if (maxedges >= NOLIMIT && maxmult >= NOLIMIT && !Dswitch && !rswitch && !lswitch) gt_abort( ">E multig: either -D or -e or -m or -r must impose a real limit\n"); if (!qswitch) { msg[0] = '\0'; CATMSG0(">A multig"); if (eswitch || mswitch || uswitch || fswitch && nfixed > 0 || lswitch || rswitch || Dswitch || Tswitch || Gswitch || Aswitch || Bswitch) CATMSG0(" -"); if (mswitch) CATMSG1("m%ld",maxmult); if (uswitch) CATMSG0("u"); if (Tswitch) CATMSG0("T"); if (Gswitch) CATMSG0("G"); if (Aswitch) CATMSG0("A"); if (Bswitch) CATMSG0("B"); if (fswitch) CATMSG1("f%d",nfixed); if (eswitch) CATMSG2("e%ld:%ld",minedges,maxedges); if (Dswitch) CATMSG1("D%d",maxdeg); if (rswitch) CATMSG1("r%d",regdeg); if (lswitch) CATMSG1("l%d",ldeg); msglen = strlen(msg); if (argnum > 0) msglen += strlen(infilename); if (argnum > 1) msglen += strlen(outfilename); if (msglen >= 196) { fputs(msg,stderr); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); } else { if (argnum > 0) CATMSG1(" %s",infilename); if (argnum > 1) CATMSG1(" %s",outfilename); CATMSG0("\n"); fputs(msg,stderr); } fflush(stderr); } if (rswitch) { eswitch = Dswitch = TRUE; maxdeg = regdeg; } if (lswitch) { eswitch = Dswitch = TRUE; maxdeg = ldeg; } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (uswitch) outfile = NULL; else { if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } } ZEROBIG(nin); ZEROBIG(nout); t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ADDBIG(nin,1); #ifdef PATHCOUNTS oldlo = nout.lo; #endif if (rswitch) { minedges = ((long)n * (long)regdeg + 1) / 2; maxedges = ((long)n * (long)regdeg) / 2; } if (lswitch) { maxedges = ((long)n * (long)ldeg) / 2; if ((ldeg & 1) == 1) minedges = (n + 1) / 2; else minedges = 0; } multi(g,nfixed,minedges,maxedges,maxmult, (Dswitch?maxdeg:-1),lswitch,m,n); #ifdef PATHCOUNTS if (nout.lo != oldlo) ++count5; #endif FREES(g); } t = CPUTIME - t; if (!qswitch) { fprintf(stderr,">Z "); PRINTBIG(stderr,nin); fprintf(stderr," graphs read from %s",infilename); fprintf(stderr,"; "); PRINTBIG(stderr,nout); if (!uswitch) fprintf(stderr," multigraphs written to %s",outfilename); else fprintf(stderr," multigraphs generated"); fprintf(stderr,"; %.2f sec\n",t); } #ifdef GROUPTEST fprintf(stderr,"Group test = %lld\n",totallab); #endif #ifdef PATHCOUNTS fprintf(stderr,"Counts: %lld %lld %lld %lld %lld %lld\n", count0,count1,count2,count3,count4,count5); #endif exit(0); } nauty24r2/naugroup.c0000600000604200001440000002301711274163463013316 0ustar bdmusers/* naugroup.c Procedures for handling groups found by nauty. */ #include "naugroup.h" static permrec *freelist = NULL; static int freelist_n = 0; static grouprec *group = NULL; static int group_depth = 0; DYNALLSTAT(cosetrec,coset,coset_sz); static permrec *gens; DYNALLSTAT(set,workset,workset_sz); DYNALLSTAT(permutation,allp,allp_sz); DYNALLSTAT(permutation,id,id_sz); /**************************************************************************/ permrec *newpermrec(int n) /* Get a permrec of order n. This procedure and the next one are designed to be efficient if lots of group ops are done with the same value of n. */ { permrec *p; if (freelist_n != n) { while (freelist != NULL) { p = freelist; freelist = freelist->ptr; free(p); } freelist_n = n; } if (freelist != NULL) { p = freelist; freelist = freelist->ptr; return p; } p = (permrec*) malloc(sizeof(permrec)+(freelist_n-2)*sizeof(permutation)); if (p == NULL) { fprintf(ERRFILE,">E malloc failed in newpermrec()\n"); exit(1); } return p; } /**************************************************************************/ void freepermrec(permrec *p, int n) /* Free a permrec of given size. */ { if (p == NULL) return; if (freelist_n != n) { while (freelist) { p = freelist; freelist = freelist->ptr; free(p); } freelist_n = n; } p->ptr = freelist; freelist = p; } /**************************************************************************/ grouprec * groupptr(boolean cutloose) /* Give the address of the group structure, cutting it loose if requested. */ { grouprec *p; p = group; if (cutloose) { group = NULL; group_depth = 0; coset = NULL; coset_sz = 0; } return p; } /**************************************************************************/ void freegroup(grouprec *grp) /* Free (or pretend to free) group structure. */ { int i,j; cosetrec *p; permrec *q,*qq; for (i = 0; i < grp->depth; ++i) { p = grp->levelinfo[i].replist; if (p != NULL) for (j = grp->levelinfo[i].orbitsize; --j >= 0; ) { freepermrec(p[j].rep,grp->n); p[j].rep = NULL; } } if (grp->depth > 0) { p = grp->levelinfo[0].replist; if (p != NULL && p != coset) { free(p); grp->levelinfo[0].replist = NULL; } q = grp->levelinfo[0].gens; while (q != NULL) { qq = q; q = q->ptr; freepermrec(qq,grp->n); } grp->levelinfo[0].gens = NULL; } } /**************************************************************************/ void groupautomproc(int count, permutation *perm, int *orbits, int numorbits, int stabvertex, int n) { permrec *p; int i; p = newpermrec(n); for (i = 0; i < n; ++i) p->p[i] = perm[i]; p->ptr = gens; gens = p; } /**************************************************************************/ void grouplevelproc(int *lab, int *ptn, int level, int *orbits, statsblk *stats, int tv, int index, int tcellsize, int numcells, int cc, int n) { int depth; size_t sz; if (numcells == n) /* first call */ { depth = level - 1; if (group) freegroup(group); if (depth > group_depth || !group) { if (depth <= 1) sz = sizeof(grouprec); else sz = sizeof(grouprec) + (depth-1)*sizeof(levelrec); if (group) group = (grouprec*)realloc((void*)group,sz); else group = (grouprec*)malloc(sz); if (group == NULL) { fprintf(ERRFILE,">E malloc failed in grouplevelproc\n"); exit(1); } group_depth = depth; } group->n = n; group->depth = depth; gens = NULL; return; } group->levelinfo[level-1].fixedpt = tv; group->levelinfo[level-1].orbitsize = index; group->levelinfo[level-1].gens = gens; group->levelinfo[level-1].replist = NULL; if (level == 1) group->numorbits = stats->numorbits; } /**************************************************************************/ void makecosetreps(grouprec *grp) /* Make all coset representatives for this group */ { int i,j,k,n,depth; int l,index; permutation *p,*q; permrec *gen,*g; cosetrec *cr; int head,tail; DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,lab,lab_sz); n = grp->n; depth = grp->depth; DYNALLOC1(int,queue,queue_sz,n,"malloc"); DYNALLOC1(int,lab,lab_sz,n,"malloc"); j = 0; for (i = 0; i < depth; ++i) j += grp->levelinfo[i].orbitsize; if (j > 0) DYNALLOC1(cosetrec,coset,coset_sz,j,"malloc"); cr = coset; for (i = 0; i < depth; ++i) { grp->levelinfo[i].replist = cr; cr += grp->levelinfo[i].orbitsize; } for (i = 0; i < depth; ++i) { cr = grp->levelinfo[i].replist; gen = grp->levelinfo[i].gens; for (j = 0; j < n; ++j) lab[j] = -1; queue[0] = grp->levelinfo[i].fixedpt; lab[queue[0]] = 0; cr[0].image = queue[0]; cr[0].rep = NULL; head = 0; tail = 1; index = 0; while (head < tail) { j = queue[head++]; p = (cr[lab[j]].rep ? cr[lab[j]].rep->p : NULL); for (g = gen; g != NULL; g = g->ptr) { k = g->p[j]; if (lab[k] < 0) { ++index; lab[k] = index; queue[tail++] = k; cr[index].image = k; cr[index].rep = newpermrec(n); q = cr[index].rep->p; if (p == NULL) for (l = 0; l < n; ++l) q[l] = g->p[l]; else for (l = 0; l < n; ++l) q[l] = g->p[p[l]]; } } } } } /**************************************************************************/ int permcycles(permutation *p, int n, int *len, boolean sort) /* Puts in len[0..] the cycle lengths of p. If sort, sort them. Return the number of cycles. */ { int m,i,j,k,h,nc,leni; m = (n + WORDSIZE - 1) / WORDSIZE; DYNALLOC1(set,workset,workset_sz,m,"malloc"); EMPTYSET(workset,m); nc = 0; for (i = 0; i < n; ++i) if (!ISELEMENT(workset,i)) { k = 1; for (j = p[i]; j != i; j = p[j]) { ADDELEMENT(workset,j); ++k; } len[nc++] = k; } if (sort && nc > 1) { j = nc / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < nc; ++i) { leni = len[i]; for (j = i; len[j-h] > leni; ) { len[j] = len[j-h]; if ((j -= h) < h) break; } len[j] = leni; } h /= 3; } while (h > 0); } return nc; } /**************************************************************************/ static void groupelts(levelrec *lr, int n, int level, void (*action)(permutation*,int), permutation *before, permutation *after, permutation *id) /* Recursive routine used by allgroup. */ { int i,j,orbsize; permutation *p,*cr; cosetrec *coset; coset = lr[level].replist; orbsize = lr[level].orbitsize; for (j = 0; j < orbsize; ++j) { cr = (coset[j].rep == NULL ? NULL : coset[j].rep->p); if (before == NULL) p = cr; else if (cr == NULL) p = before; else { p = after; for (i = 0; i < n; ++i) p[i] = cr[before[i]]; } if (level == 0) (*action)((p == NULL ? id : p),n); else groupelts(lr,n,level-1,action,p,after+n,id); } } /**************************************************************************/ void allgroup(grouprec *grp, void (*action)(permutation*,int)) /* Call action(p,n) for every element of the group, including the identity. The identity is always the first call. */ { int i,depth,n; depth = grp->depth; n = grp->n; DYNALLOC1(permutation,id,id_sz,n,"malloc"); for (i = 0; i < n; ++i) id[i] = i; if (depth == 0) { (*action)(id,n); return; } DYNALLOC1(permutation,allp,allp_sz,n*depth,"malloc"); groupelts(grp->levelinfo,n,depth-1,action,NULL,allp,id); } /**************************************************************************/ static void groupelts2(levelrec *lr, int n, int level, void (*action)(permutation*,int,int*), permutation *before, permutation *after, permutation *id, int *abort) /* Recursive routine used by allgroup2. */ { int i,j,orbsize; permutation *p,*cr; cosetrec *coset; coset = lr[level].replist; orbsize = lr[level].orbitsize; for (j = 0; j < orbsize; ++j) { cr = (coset[j].rep == NULL ? NULL : coset[j].rep->p); if (before == NULL) p = cr; else if (cr == NULL) p = before; else { p = after; for (i = 0; i < n; ++i) p[i] = cr[before[i]]; } if (level == 0) (*action)((p == NULL ? id : p),n,abort); else groupelts2(lr,n,level-1,action,p,after+n,id,abort); if (*abort) return; } } /**************************************************************************/ int allgroup2(grouprec *grp, void (*action)(permutation*,int,int*)) /* Call action(p,n,&abort) for every element of the group, including the identity. The identity is always the first call. If action() stores a non-zero value in abort, group generation is aborted and the abort value is returned by this procedure. If no non-zero value is ever returned in abort by action(), this procedure returns 0. */ { int i,depth,n,abort; depth = grp->depth; n = grp->n; DYNALLOC1(permutation,id,id_sz,n,"malloc"); for (i = 0; i < n; ++i) id[i] = i; abort = 0; if (depth == 0) { (*action)(id,n,&abort); return abort; } DYNALLOC1(permutation,allp,allp_sz,n*depth,"malloc"); groupelts2(grp->levelinfo,n,depth-1,action,NULL,allp,id,&abort); return abort; } nauty24r2/nautinv.c0000600000604200001440000016155411405400302013131 0ustar bdmusers/***************************************************************************** * * * Vertex-invariants source file for nauty 2.4. * * * * Copyright (1989-2010) Brendan McKay. All rights reserved. * * Subject to waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 13-Mar-90 : initial release for version 1.5 * * 10-Nov-90 : changes for version 1.6 : * * - added dummy routine nautinv_null() * * 27-Aug-92 : renamed to version 1.7, no changes to this file * * 5-Jun-93 : renamed to version 1.7+, no changes to this file * * 18-Aug-93 : renamed to version 1.8, no changes to this file * * 17-Sep-93 : changes for version 1.9 : * * - added invariant routine adjacencies() * * 20-Jun-96 : changes for version 2.0 : * * - added invariants cellfano() and cellfano2() * * 11-Jul-96 - added dynamic allocation * * 21-Oct-98 - use shortish in place of short for BIGNAUTY * * 9-Jan-00 - added nautinv_check() * * 12-Feb-00 - minor code formatting * * 16-Nov-00 - made changes listed in nauty.h * * 22-Apr-01 : changes for version 2.1 : * * - made all large dynamic memory external to routines * * - added nautinv_freedyn() to free all such memory * * - include nautinv.h rather than naututil.h * * - removed nautinv_null() * * - added code to facilitate compilation into Magma * * - removed EXTDEFS * * 12-Jul-01 - use invararg in distances() * * - fixed comments in ind and cliq routines * * 21-Nov-01 : use NAUTYREQUIRED in nautinv_check() * * 10-Dec-06 : remove BIGNAUTY * * * *****************************************************************************/ #define ONE_WORD_SETS #include "nautinv.h" #if MAXM==1 #define M 1 #else #define M m #endif #define ACCUM(x,y) x = (((x) + (y)) & 077777) static int fuzz1[] = {037541,061532,005257,026416}; static int fuzz2[] = {006532,070236,035523,062437}; #define FUZZ1(x) ((x) ^ fuzz1[(x)&3]) #define FUZZ2(x) ((x) ^ fuzz2[(x)&3]) #define MAXCLIQUE 10 /* max clique size for cliques() and maxindset() */ #if MAXN static set workset[MAXM]; static shortish workshort[MAXN+2]; static set ws1[MAXM], ws2[MAXM]; static shortish vv[MAXN],ww[MAXN]; static set w01[MAXM],w02[MAXM],w03[MAXM],w12[MAXM],w13[MAXM],w23[MAXM]; static set pt0[MAXM],pt1[MAXM],pt2[MAXM]; static set wss[MAXCLIQUE-1][MAXM]; #else DYNALLSTAT(set,workset,workset_sz); DYNALLSTAT(shortish,workshort,workshort_sz); DYNALLSTAT(set,ws1,ws1_sz); DYNALLSTAT(set,ws2,ws2_sz); DYNALLSTAT(shortish,vv,vv_sz); DYNALLSTAT(shortish,ww,ww_sz); DYNALLSTAT(set,w01,w01_sz); DYNALLSTAT(set,w02,w02_sz); DYNALLSTAT(set,w03,w03_sz); DYNALLSTAT(set,w12,w12_sz); DYNALLSTAT(set,w13,w13_sz); DYNALLSTAT(set,w23,w23_sz); DYNALLSTAT(set,pt0,pt0_sz); DYNALLSTAT(set,pt1,pt1_sz); DYNALLSTAT(set,pt2,pt2_sz); DYNALLSTAT(set,wss,wss_sz); #endif /* aproto: header new_nauty_protos.h */ /***************************************************************************** * * * This file contains a number of procedures which compute vertex-invariants * * for stronger partition refinement. Since entirely different * * vertex-invariants seem to work better for different types of graph, we * * cannot do more than give a small collection of representative examples. * * Any serious computations with difficult graphs may well need to use * * specially-written vertex-invariants. The use of vertex-invariants * * procedures is supported by nauty from version 1.5 onwards, via the * * options userinvarproc, mininvarlevel, maxinvarlevel and invararg. * * The meaning of these fields in detail are as follows: * * userinvarproc is the address of the vertex-invariant procedure. If * * no vertex-invariants is required, this field should * * have the value NULL. * * maxinvarlevel The absolute value of this is the maximum level in the * * search tree at which the vertex-invariant will be * * computed. The root of the tree is at level 1, so the * * vertex-invariant will not be invoked at all if * * maxinvarlevel==0. Negative values of maxinvarlevel * * request nauty to not compute the vertex-invariant at * * a level greater than that of the earliest node (if any) * * on the path to the first leaf of the search tree at * * which the vertex-invariant refines the partition. * * mininvarlevel The absolute value of this is the minimum level in the * * search tree at which the vertex-invariant will be * * computed. The root of the tree is at level 1, so there * * is no effective limit if mininvarlevel is -1, 0 or 1. * * Negative values of mininvarlevel request nauty to not * * compute the vertex-invariant at a level less than * * that of the earliest node (if any) on the path to the * * first leaf of the search tree at which the * * vertex-invariant refines the partition. * * invararg is passed to the vertex-invariant procedure via the * * argument of the same name. It can be used by the * * procedure for any purpose. * * Note that negative values of maxinvarlevel and mininvarlevel make the * * canonical labelling invalid, but can speed automorphism group finding. * * Nauty already knows this and takes their absolute values. * * * * A vertex-invariant must be declared thus: * * void invarproc(g,lab,ptn,level,numcells,tvpos,invar,invararg,digraph,m,n) * * All of these arguments must be treated as read-only except for invar. * * g : the graph, exactly as passed to nauty() * * lab,ptn : the current partition nest (see nauty.h for the format) * * level : the level of this node in the search tree. * * numcells : the number of cells in the partition at this node. * * tvpos : the index in (lab,ptn) of one cell in the partition. * * If level <= 1, the cell will be the first fragment of the * * first active cell (as provided by the initial call to nauty), * * or the first cell, if there were no active cells. * * If level > 1, the cell will be the singleton cell which was * * created to make this node of the search tree from its parent. * * invararg : a copy of options.invararg * * digraph : a copy of options.digraph * * m,n : size parameters as passed to nauty() * * invar : an array to return the answer in. The procedure must put in * * each invar[i] (0 <= i < n) an invariant of the 6-tuple * * (,g,,level, * * invararg,digraph) * * Note that invar[] is declared as a permutation. Since the * * absolute value of the invariant is irrelevant, only the * * comparative values, any short, int or long value can be * * assigned to the entries of invar[] without fear. However, * * you should assign a value less than 077777 to ensure machine- * * independence of the canonical labelling. * * * * The refinement procedure has already been called before the invariant * * procedure is called. That means that the partition is equitable if * * digraph==FALSE. * * * *****************************************************************************/ /***************************************************************************** * * * twopaths() assigns to each vertex v the sum of the weights of each vertex * * which can be reached from v along a walk of length two (including itself * * usually). The weight of each vertex w is defined as the ordinal number * * of the cell containing w, starting at 1 for the first cell. * * * *****************************************************************************/ void twopaths(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,v,w; shortish wt; set *gv,*gw; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"twopaths"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"twopaths"); #endif wt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = wt; if (ptn[i] <= level) ++wt; } for (v = 0, gv = (set*)g; v < n; ++v, gv += M) { EMPTYSET(workset,m); w = -1; while ((w = nextelement(gv,M,w)) >= 0) { gw = GRAPHROW(g,w,m); for (i = M; --i >= 0;) UNION(workset[i],gw[i]); } wt = 0; w = -1; while ((w = nextelement(workset,M,w)) >= 0) ACCUM(wt,workshort[w]); invar[v] = wt; } } /***************************************************************************** * * * quadruples() assigns to each vertex v a value depending on the set of * * weights w(v,v1,v2,v3), where w(v,v1,v2,v3) depends on the number of * * vertices adjacent to an odd number of {v,v1,v2,v3}, and to the cells * * that v,v1,v2,v3 belong to. {v,v1,v2,v3} are permitted to range over all * * distinct 4-tuples which contain at least one member in the cell tvpos. * * * *****************************************************************************/ void quadruples(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,pc; setword sw; set *gw; shortish wt; int v,iv,v1,v2,v3; set *gv; long wv,wv1,wv2,wv3; #if !MAXN DYNALLOC1(shortish,workshort,workshort_sz,n+2,"quadruples"); DYNALLOC1(set,ws1,ws1_sz,m,"quadruples"); DYNALLOC1(set,workset,workset_sz,m,"quadruples"); #endif for (i = n; --i >= 0;) invar[i] = 0; wt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = FUZZ2(wt); if (ptn[i] <= level) ++wt; } iv = tvpos - 1; do { v = lab[++iv]; gv = GRAPHROW(g,v,m); wv = workshort[v]; for (v1 = 0; v1 < n-2; ++v1) { wv1 = workshort[v1]; if (wv1 == wv && v1 <= v) continue; wv1 += wv; gw = GRAPHROW(g,v1,m); for (i = M; --i >= 0;) workset[i] = gv[i] ^ gw[i]; for (v2 = v1+1; v2 < n-1; ++v2) { wv2 = workshort[v2]; if (wv2 == wv && v2 <= v) continue; wv2 += wv1; gw = GRAPHROW(g,v2,m); for (i = M; --i >= 0;) ws1[i] = workset[i] ^ gw[i]; for (v3 = v2+1; v3 < n; ++v3) { wv3 = workshort[v3]; 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); wt = (FUZZ1(pc)+wv3) & 077777; wt = FUZZ2(wt); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); ACCUM(invar[v2],wt); ACCUM(invar[v3],wt); } } } } while (ptn[iv] > level); } /***************************************************************************** * * * triples() assigns to each vertex v a value depending on the set of * * weights w(v,v1,v2), where w(v,v1,v2) depends on the number of vertices * * adjacent to an odd number of {v,v1,v2}, and to the cells that * * v,v1,v2 belong to. {v,v1,v2} are permitted to range over all distinct * * triples which contain at least one member in the cell tvpos. * * * *****************************************************************************/ void triples(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,pc; setword sw; set *gw; shortish wt; int v,iv,v1,v2; set *gv; long wv,wv1,wv2; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"triples"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"triples"); #endif for (i = n; --i >= 0;) invar[i] = 0; wt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = FUZZ1(wt); if (ptn[i] <= level) ++wt; } iv = tvpos - 1; do { v = lab[++iv]; gv = GRAPHROW(g,v,m); wv = workshort[v]; for (v1 = 0; v1 < n-1; ++v1) { wv1 = workshort[v1]; if (wv1 == wv && v1 <= v) continue; wv1 += wv; gw = GRAPHROW(g,v1,m); for (i = M; --i >= 0;) workset[i] = gv[i] ^ gw[i]; for (v2 = v1+1; v2 < n; ++v2) { wv2 = workshort[v2]; 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); wt = (FUZZ1(pc)+wv2) & 077777; wt = FUZZ2(wt); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); ACCUM(invar[v2],wt); } } } while (ptn[iv] > level); } /***************************************************************************** * * * adjtriang() assigns to each vertex v a value depending on the numbers * * of common neighbours between each pair {v1,v2} of neighbours of v, and * * which cells v1 and v2 lie in. The vertices v1 and v2 must be adjacent * * if invararg == 0 and not adjacent if invararg == 1. * * * *****************************************************************************/ void adjtriang(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int j,pc; setword sw; set *gi; shortish wt; int i,v1,v2; boolean v1v2; set *gv1,*gv2; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"adjtriang"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"adjtriang"); #endif for (i = n; --i >= 0;) invar[i] = 0; wt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = FUZZ1(wt); if (ptn[i] <= level) ++wt; } for (v1 = 0, gv1 = g; v1 < n; ++v1, gv1 += M) { for (v2 = (digraph ? 0 : v1+1); v2 < n; ++v2) { if (v2 == v1) continue; v1v2 = (ISELEMENT(gv1,v2) != 0); if (invararg == 0 && !v1v2 || invararg == 1 && v1v2) continue; wt = workshort[v1]; ACCUM(wt,workshort[v2]); ACCUM(wt,v1v2); gv2 = GRAPHROW(g,v2,m); for (i = M; --i >= 0;) workset[i] = gv1[i] & gv2[i]; 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 = (pc + wt) & 077777; ACCUM(invar[i],pc); } } } } /***************************************************************************** * * * getbigcells(ptn,level,minsize,bigcells,cellstart,cellsize,n) is an * * auxiliary procedure to make a list of all the large cells in the current * * partition. On entry, ptn, level and n have their usual meanings, * * while minsize is the smallest size of an interesting cell. On return, * * bigcells is the number of cells of size at least minsize, cellstart[0...] * * contains their starting positions in ptn, and cellsize[0...] contain * * their sizes. These two arrays are in increasing order of cell size, * * then position. * * * *****************************************************************************/ void getbigcells(int *ptn, int level, int minsize, int *bigcells, shortish *cellstart, shortish *cellsize, int n) { int cell1,cell2,j; shortish si,st; int bc,i,h; bc = 0; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} if (cell2 >= cell1 + 3) { cellstart[bc] = cell1; cellsize[bc] = cell2 - cell1 + 1; ++bc; } } *bigcells = bc; j = bc / 3; h = 1; do h = 3 * h + 1; while (h < j); do /* shell sort */ { for (i = h; i < bc; ++i) { st = cellstart[i]; si = cellsize[i]; for (j = i; cellsize[j-h] > si || cellsize[j-h] == si && cellstart[j-h] > st; ) { cellsize[j] = cellsize[j-h]; cellstart[j] = cellstart[j-h]; if ((j -= h) < h) break; } cellsize[j] = si; cellstart[j] = st; } h /= 3; } while (h > 0); } /***************************************************************************** * * * celltrips() assigns to each vertex v a value depending on the set of * * weights w(v,v1,v2), where w(v,v1,v2) depends on the number of vertices * * adjacent to an odd number of {v,v1,v2}. {v,v1,v2} are constrained to * * belong to the same cell. We try the cells in increasing order of size, * * and stop as soon as any cell splits. * * * *****************************************************************************/ void celltrips(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,pc; setword sw; set *gw; shortish wt; int v,iv,v1,iv1,v2,iv2; int icell,bigcells,cell1,cell2; shortish *cellstart,*cellsize; set *gv; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"celltrips"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"celltrips"); #endif for (i = n; --i >= 0;) invar[i] = 0; cellstart = workshort; cellsize = workshort + (n/2); getbigcells(ptn,level,3,&bigcells,cellstart,cellsize,n); for (icell = 0; icell < bigcells; ++icell) { cell1 = cellstart[icell]; cell2 = cell1 + cellsize[icell] - 1; for (iv = cell1; iv <= cell2 - 2; ++iv) { v = lab[iv]; gv = GRAPHROW(g,v,m); for (iv1 = iv + 1; iv1 <= cell2 - 1; ++iv1) { v1 = lab[iv1]; gw = GRAPHROW(g,v1,m); for (i = M; --i >= 0;) workset[i] = gv[i] ^ gw[i]; for (iv2 = iv1 + 1; iv2 <= cell2; ++iv2) { 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); wt = FUZZ1(pc); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); ACCUM(invar[v2],wt); } } } wt = invar[lab[cell1]]; for (i = cell1 + 1; i <= cell2; ++i) if (invar[lab[i]] != wt) return; } } /***************************************************************************** * * * cellquads() assigns to each vertex v a value depending on the set of * * weights w(v,v1,v2,v3), where w(v,v1,v2,v3) depends on the number of * * vertices adjacent to an odd number of {v,v1,v2,v3}. {v,v1,v2,v3} are * * constrained to belong to the same cell. We try the cells in increasing * * order of size, and stop as soon as any cell splits. * * * *****************************************************************************/ void cellquads(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,pc; setword sw; set *gw; shortish wt; int v,iv,v1,iv1,v2,iv2,v3,iv3; int icell,bigcells,cell1,cell2; shortish *cellstart,*cellsize; set *gv; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"cellquads"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"cellquads"); DYNALLOC1(set,ws1,ws1_sz,m,"cellquads"); #endif for (i = n; --i >= 0;) invar[i] = 0; cellstart = workshort; cellsize = workshort + (n/2); getbigcells(ptn,level,4,&bigcells,cellstart,cellsize,n); for (icell = 0; icell < bigcells; ++icell) { cell1 = cellstart[icell]; cell2 = cell1 + cellsize[icell] - 1; for (iv = cell1; iv <= cell2 - 3; ++iv) { v = lab[iv]; gv = GRAPHROW(g,v,m); for (iv1 = iv + 1; iv1 <= cell2 - 2; ++iv1) { v1 = lab[iv1]; gw = GRAPHROW(g,v1,m); for (i = M; --i >= 0;) workset[i] = gv[i] ^ gw[i]; for (iv2 = iv1 + 1; iv2 <= cell2 - 1; ++iv2) { v2 = lab[iv2]; gw = GRAPHROW(g,v2,m); for (i = M; --i >= 0;) ws1[i] = workset[i] ^ gw[i]; for (iv3 = iv2 + 1; iv3 <= cell2; ++iv3) { 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); wt = FUZZ1(pc); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); ACCUM(invar[v2],wt); ACCUM(invar[v3],wt); } } } } wt = invar[lab[cell1]]; for (i = cell1 + 1; i <= cell2; ++i) if (invar[lab[i]] != wt) return; } } /***************************************************************************** * * * cellquins() assigns to each vertex v a value depending on the set of * * weights w(v,v1,v2,v3,v4), where w(v,v1,v2,v3,v4) depends on the number * * of vertices adjacent to an odd number of {v,v1,v2,v3,v4}. * * {v,v1,v2,v3,v4} are constrained to belong to the same cell. We try the * * cells in increasing order of size, and stop as soon as any cell splits. * * * *****************************************************************************/ void cellquins(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,pc; setword sw; set *gw; shortish wt; int v,iv,v1,iv1,v2,iv2,v3,iv3,v4,iv4; int icell,bigcells,cell1,cell2; shortish *cellstart,*cellsize; set *gv; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"cellquins"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"cellquins"); DYNALLOC1(set,ws1,ws1_sz,m,"cellquins"); DYNALLOC1(set,ws2,ws2_sz,m,"cellquins"); #endif for (i = n; --i >= 0;) invar[i] = 0; cellstart = workshort; cellsize = workshort + (n/2); getbigcells(ptn,level,5,&bigcells,cellstart,cellsize,n); for (icell = 0; icell < bigcells; ++icell) { cell1 = cellstart[icell]; cell2 = cell1 + cellsize[icell] - 1; for (iv = cell1; iv <= cell2 - 4; ++iv) { v = lab[iv]; gv = GRAPHROW(g,v,m); for (iv1 = iv + 1; iv1 <= cell2 - 3; ++iv1) { v1 = lab[iv1]; gw = GRAPHROW(g,v1,m); for (i = M; --i >= 0;) workset[i] = gv[i] ^ gw[i]; for (iv2 = iv1 + 1; iv2 <= cell2 - 2; ++iv2) { v2 = lab[iv2]; gw = GRAPHROW(g,v2,m); for (i = M; --i >= 0;) ws1[i] = workset[i] ^ gw[i]; for (iv3 = iv2 + 1; iv3 <= cell2 - 1; ++iv3) { v3 = lab[iv3]; gw = GRAPHROW(g,v3,m); for (i = M; --i >= 0;) ws2[i] = ws1[i] ^ gw[i]; for (iv4 = iv3 + 1; iv4 <= cell2; ++iv4) { 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); wt = FUZZ1(pc); ACCUM(invar[v],wt); ACCUM(invar[v1],wt); ACCUM(invar[v2],wt); ACCUM(invar[v3],wt); ACCUM(invar[v4],wt); } } } } } wt = invar[lab[cell1]]; for (i = cell1 + 1; i <= cell2; ++i) if (invar[lab[i]] != wt) return; } } /***************************************************************************** * * * uniqinter(s1,s2,m) returns the number in both sets if it is unique, * * or -1 if there is none or it is not unique. * *****************************************************************************/ static int uniqinter(set *s1, set *s2, int m) { int i,j; setword w; for (i = 0; i < M; ++i) { if ((w = s1[i] & s2[i]) != 0) { j = FIRSTBIT(w); if (w != BITT[j]) return -1; j += TIMESWORDSIZE(i); for (++i; i < M; ++i) if (s1[i] & s2[i]) return -1; return j; } } return -1; } /***************************************************************************** * * * cellfano2() assigns to each vertex v a value depending on the set of * * weights w(v,v1,v2,v3), where w(v,v1,v2,v3) depends on the number of * * fano-plane analogues containing {v,v1,v2,v3}. {v,v1,v2,v3} are * * constrained to belong to the same cell and being independent and * * non-collinear. We try the cells in increasing order of size, and stop * * as soon as any cell splits. * * * *****************************************************************************/ void cellfano2(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,pc; setword sw; shortish wt; int v0,v1,v2,v3,iv0,iv1,iv2,iv3; int icell,bigcells,cell1,cell2; shortish *cellstart,*cellsize; int nw,x01,x02,x03,x12,x13,x23; int pnt0,pnt1,pnt2; set *gv0,*gv1,*gv2,*gv3; set *gp0,*gp1,*gp2; #if !MAXN DYNALLOC1(shortish,workshort,workshort_sz,n+2,"cellfano2"); DYNALLOC1(shortish,vv,vv_sz,n,"cellfano2"); DYNALLOC1(shortish,ww,ww_sz,n,"cellfano2"); #endif for (i = n; --i >= 0;) invar[i] = 0; cellstart = workshort; cellsize = workshort + (n/2); getbigcells(ptn,level,4,&bigcells,cellstart,cellsize,n); for (icell = 0; icell < bigcells; ++icell) { cell1 = cellstart[icell]; cell2 = cell1 + cellsize[icell] - 1; for (iv0 = cell1; iv0 <= cell2 - 3; ++iv0) { v0 = lab[iv0]; gv0 = GRAPHROW(g,v0,m); nw = 0; for (iv1 = iv0 + 1; iv1 <= cell2; ++iv1) { v1 = lab[iv1]; if (ISELEMENT(gv0,v1)) continue; if ((x01 = uniqinter(gv0,GRAPHROW(g,v1,m),m)) < 0) continue; vv[nw] = v1; ww[nw] = x01; ++nw; } for (iv1 = 0; iv1 < nw-2; ++iv1) { v1 = vv[iv1]; gv1 = GRAPHROW(g,v1,m); x01 = ww[iv1]; for (iv2 = iv1 + 1; iv2 < nw-1; ++iv2) { x02 = ww[iv2]; if (x02 == x01) continue; v2 = vv[iv2]; if (ISELEMENT(gv1,v2)) continue; gv2 = GRAPHROW(g,v2,m); if ((x12 = uniqinter(gv1,gv2,m)) < 0) continue; for (iv3 = iv2 + 1; iv3 < nw; ++iv3) { x03 = ww[iv3]; if (x03 == x01 || x03 == x02) continue; v3 = vv[iv3]; if (ISELEMENT(gv1,v3) || ISELEMENT(gv2,v3)) continue; gv3 = GRAPHROW(g,v3,m); if ((x13 = uniqinter(gv1,gv3,m)) < 0) continue; if ((x23 = uniqinter(gv2,gv3,m)) < 0 || x23 == x13) continue; if ((pnt0 = uniqinter(GRAPHROW(g,x01,m), GRAPHROW(g,x23,m),m)) < 0) continue; if ((pnt1 = uniqinter(GRAPHROW(g,x02,m), GRAPHROW(g,x13,m),m)) < 0) continue; if ((pnt2 = uniqinter(GRAPHROW(g,x03,m), GRAPHROW(g,x12,m),m)) < 0) continue; gp0 = GRAPHROW(g,pnt0,m); 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); } wt = FUZZ1(pc); ACCUM(invar[v0],wt); ACCUM(invar[v1],wt); ACCUM(invar[v2],wt); ACCUM(invar[v3],wt); } } } } wt = invar[lab[cell1]]; for (i = cell1 + 1; i <= cell2; ++i) if (invar[lab[i]] != wt) return; } } /***************************************************************************** * * * setnbhd(g,m,n,w,wn) is an auxiliary routine that sets wn to the union * * of the neighbours of the vertices in w. * * * *****************************************************************************/ void setnbhd(graph *g, int m, int n, set *w, set *wn) { int i,j; set *gi; i = nextelement(w,M,-1); if (i < 0) { EMPTYSET(wn,M); return; } gi = GRAPHROW(g,i,M); for (j = M; --j >= 0;) wn[j] = gi[j]; while ((i = nextelement(w,M,i)) >= 0) { gi = GRAPHROW(g,i,M); for (j = M; --j >= 0;) wn[j] |= gi[j]; } } /***************************************************************************** * * * cellfano() assigns to each vertex v a value depending on the set of * * weights w(v,v1,v2,v3), where w(v,v1,v2,v3) depends on the number of * * fano-plane analogues containing {v,v1,v2,v3}. {v,v1,v2,v3} are * * constrained to belong to the same cell and being independent. We try * * the cells in increasing order of size, and stop as soon as any cell * * splits. * * * *****************************************************************************/ void cellfano(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,pc; setword sw; shortish wt; int v0,v1,v2,v3,iv0,iv1,iv2,iv3; int icell,bigcells,cell1,cell2; shortish *cellstart,*cellsize; set *gv0,*gv1,*gv2,*gv3; #if !MAXN DYNALLOC1(shortish,workshort,workshort_sz,n+2,"cellfano"); DYNALLOC1(set,w01,w01_sz,m,"cellfano"); DYNALLOC1(set,w02,w02_sz,m,"cellfano"); DYNALLOC1(set,w03,w03_sz,m,"cellfano"); DYNALLOC1(set,w12,w12_sz,m,"cellfano"); DYNALLOC1(set,w13,w13_sz,m,"cellfano"); DYNALLOC1(set,w23,w23_sz,m,"cellfano"); DYNALLOC1(set,pt0,pt0_sz,m,"cellfano"); DYNALLOC1(set,pt1,pt1_sz,m,"cellfano"); DYNALLOC1(set,pt2,pt2_sz,m,"cellfano"); DYNALLOC1(set,workset,workset_sz,m,"cellfano"); #else #endif for (i = n; --i >= 0;) invar[i] = 0; cellstart = workshort; cellsize = workshort + (n/2); getbigcells(ptn,level,4,&bigcells,cellstart,cellsize,n); for (icell = 0; icell < bigcells; ++icell) { cell1 = cellstart[icell]; cell2 = cell1 + cellsize[icell] - 1; for (iv0 = cell1; iv0 <= cell2 - 3; ++iv0) { v0 = lab[iv0]; gv0 = GRAPHROW(g,v0,m); for (iv1 = iv0 + 1; iv1 <= cell2 - 2; ++iv1) { v1 = lab[iv1]; if (ISELEMENT(gv0,v1)) continue; gv1 = GRAPHROW(g,v1,m); for (i = M; --i >= 0;) workset[i] = gv0[i] & gv1[i]; setnbhd(g,m,n,workset,w01); for (iv2 = iv1 + 1; iv2 <= cell2 - 1; ++iv2) { v2 = lab[iv2]; if (ISELEMENT(gv0,v2) || ISELEMENT(gv1,v2)) continue; gv2 = GRAPHROW(g,v2,m); for (i = M; --i >= 0;) workset[i] = gv0[i] & gv2[i]; setnbhd(g,m,n,workset,w02); for (i = M; --i >= 0;) workset[i] = gv1[i] & gv2[i]; setnbhd(g,m,n,workset,w12); for (iv3 = iv2 + 1; iv3 <= cell2; ++iv3) { v3 = lab[iv3]; if (ISELEMENT(gv0,v3) || ISELEMENT(gv1,v3) || ISELEMENT(gv2,v3)) continue; gv3 = GRAPHROW(g,v3,m); for (i = M; --i >= 0;) workset[i] = gv0[i] & gv3[i]; setnbhd(g,m,n,workset,w03); for (i = M; --i >= 0;) workset[i] = gv1[i] & gv3[i]; setnbhd(g,m,n,workset,w13); for (i = M; --i >= 0;) workset[i] = gv2[i] & gv3[i]; setnbhd(g,m,n,workset,w23); for (i = M; --i >= 0;) workset[i] = w01[i] & w23[i]; setnbhd(g,m,n,workset,pt0); for (i = M; --i >= 0;) workset[i] = w03[i] & w12[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); } wt = FUZZ1(pc); ACCUM(invar[v0],wt); ACCUM(invar[v1],wt); ACCUM(invar[v2],wt); ACCUM(invar[v3],wt); } } } } wt = invar[lab[cell1]]; for (i = cell1 + 1; i <= cell2; ++i) if (invar[lab[i]] != wt) return; } } /***************************************************************************** * * * distances() assigns to each vertex v a value depending on the number of * * vertices at each distance from v, and what cells they lie in. * * If we find any cell which is split in this manner, we don't try any * * further cells. * * * *****************************************************************************/ void distances(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i; set *gw; shortish wt; int d,dlim,cell1,cell2,iv,v,w; boolean success; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"distances"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"distances"); DYNALLOC1(set,ws1,ws1_sz,m,"distances"); DYNALLOC1(set,ws2,ws2_sz,m,"distances"); #endif for (i = n; --i >= 0;) invar[i] = 0; wt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = FUZZ1(wt); if (ptn[i] <= level) ++wt; } if (invararg > n || invararg == 0) dlim = n; else dlim = invararg+1; success = FALSE; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} if (cell2 == cell1) continue; for (iv = cell1; iv <= cell2; ++iv) { v = lab[iv]; EMPTYSET(ws1,m); ADDELEMENT(ws1,v); EMPTYSET(ws2,m); ADDELEMENT(ws2,v); for (d = 1; d < dlim; ++d) { EMPTYSET(workset,m); wt = 0; w = -1; while ((w = nextelement(ws2,M,w)) >= 0) { gw = GRAPHROW(g,w,m); ACCUM(wt,workshort[w]); for (i = M; --i >= 0;) workset[i] |= gw[i]; } if (wt == 0) break; ACCUM(wt,d); wt = FUZZ2(wt); ACCUM(invar[v],wt); for (i = M; --i >= 0;) { ws2[i] = workset[i] & ~ws1[i]; ws1[i] |= ws2[i]; } } if (invar[v] != invar[lab[cell1]]) success = TRUE; } if (success) break; } } /***************************************************************************** * * * indsets() assigns to each vertex v a value depending on which cells the * * vertices which join v in an independent set lie in. The size of the * * independent sets which are used is the smallest of invararg and MAXCLIQUE.* * * *****************************************************************************/ void indsets(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i; shortish wt; set *gv; int ss,setsize; int v[MAXCLIQUE]; long wv[MAXCLIQUE]; set *s0,*s1; #if !MAXN DYNALLOC1(shortish,workshort,workshort_sz,n+2,"indsets"); DYNALLOC2(set,wss,wss_sz,m,MAXCLIQUE-1,"indsets"); #endif for (i = n; --i >= 0;) invar[i] = 0; if (invararg <= 1 || digraph) return; if (invararg > MAXCLIQUE) setsize = MAXCLIQUE; else setsize = invararg; wt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = FUZZ2(wt); if (ptn[i] <= level) ++wt; } for (v[0] = 0; v[0] < n; ++v[0]) { wv[0] = workshort[v[0]]; s0 = (set*)wss; EMPTYSET(s0,m); for (i = v[0]+1; i < n; ++i) ADDELEMENT(s0,i); gv = GRAPHROW(g,v[0],m); for (i = M; --i >= 0;) s0[i] &= ~gv[i]; ss = 1; v[1] = v[0]; while (ss > 0) { if (ss == setsize) { wt = FUZZ1(wv[ss-1]); for (i = ss; --i >= 0;) ACCUM(invar[v[i]],wt); --ss; } else if ((v[ss] = nextelement((set*)wss+M*(ss-1),M,v[ss])) < 0) --ss; else { wv[ss] = wv[ss-1] + workshort[v[ss]]; ++ss; if (ss < setsize) { gv = GRAPHROW(g,v[ss-1],m); s1 = (set*)wss + M*(ss-2); for (i = M; --i >= 0;) s1[i+M] = s1[i] & ~gv[i]; v[ss] = v[ss-1]; } } } } } /***************************************************************************** * * * cliques() assigns to each vertex v a value depending on which cells the * * vertices which join v in a clique lie in. The size of the cliques used * * is the smallest of invararg and MAXCLIQUE. * * * *****************************************************************************/ void cliques(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i; shortish wt; set *gv; int ss,setsize; int v[MAXCLIQUE]; long wv[MAXCLIQUE]; set *ns; #if !MAXN DYNALLOC1(shortish,workshort,workshort_sz,n+2,"cliques"); DYNALLOC2(set,wss,wss_sz,m,MAXCLIQUE-1,"cliques"); #else set wss[MAXCLIQUE-1][MAXM]; #endif for (i = n; --i >= 0;) invar[i] = 0; if (invararg <= 1 || digraph) return; if (invararg > MAXCLIQUE) setsize = MAXCLIQUE; else setsize = invararg; wt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = FUZZ2(wt); if (ptn[i] <= level) ++wt; } for (v[0] = 0; v[0] < n; ++v[0]) { wv[0] = workshort[v[0]]; gv = GRAPHROW(g,v[0],m); ns = (set*)wss; for (i = M; --i >= 0;) ns[i] = gv[i]; ss = 1; v[1] = v[0]; while (ss > 0) { if (ss == setsize) { wt = FUZZ1(wv[ss-1]); for (i = ss; --i >= 0;) ACCUM(invar[v[i]],wt); --ss; } else if ((v[ss] = nextelement((set*)wss+M*(ss-1),M,v[ss])) < 0) --ss; else { wv[ss] = wv[ss-1] + workshort[v[ss]]; ++ss; if (ss < setsize) { gv = GRAPHROW(g,v[ss-1],m); ns = (set*)wss + M*(ss-2); for (i = M; --i >= 0;) ns[i+M] = ns[i] & gv[i]; v[ss] = v[ss-1]; } } } } } /***************************************************************************** * * * cellcliq() assigns to each vertex v a value depending on the number of * * cliques which v lies in and which lie in the same cell as v. The size * * of clique counted is the smallest of invararg and MAXCLIQUE. We try the * * cells in increasing order of size and stop as soon as any cell splits. * * * *****************************************************************************/ void cellcliq(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i; shortish wt; set *gv; int ss,setsize; int v[MAXCLIQUE]; set *ns; shortish *cellstart,*cellsize; int iv,icell,bigcells,cell1,cell2; int pc; setword sw; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"cellcliq"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"cellcliq"); DYNALLOC2(set,wss,wss_sz,m,MAXCLIQUE-1,"cellcliq"); #endif for (i = n; --i >= 0;) invar[i] = 0; if (invararg <= 1 || digraph) return; if (invararg > MAXCLIQUE) setsize = MAXCLIQUE; else setsize = invararg; cellstart = workshort; cellsize = workshort + (n/2); getbigcells(ptn,level,setsize > 6 ? setsize : 6,&bigcells, cellstart,cellsize,n); for (icell = 0; icell < bigcells; ++icell) { cell1 = cellstart[icell]; cell2 = cell1 + cellsize[icell] - 1; EMPTYSET(workset,m); for (iv = cell1; iv <= cell2; ++iv) ADDELEMENT(workset,lab[iv]); for (iv = cell1; iv <= cell2; ++iv) { 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); } if (pc <= 1 || pc >= cellsize[icell] - 2) continue; ss = 1; v[1] = v[0]; while (ss > 0) { if (ss == setsize) { for (i = ss; --i >= 0;) ++invar[v[i]]; --ss; } else if ((v[ss] = nextelement((set*)wss+M*(ss-1),M,v[ss])) < 0) --ss; else { ++ss; if (ss < setsize) { gv = GRAPHROW(g,v[ss-1],m); ns = (set*)wss + M*(ss-2); for (i = M; --i >= 0;) ns[i+M] = ns[i] & gv[i]; v[ss] = v[ss-1]; } } } } wt = invar[lab[cell1]]; for (iv = cell1; iv <= cell2; ++iv) if (invar[lab[iv]] != wt) return; } } /***************************************************************************** * * * cellind() assigns to each vertex v a value depending on the number of * * independent sets which v lies in and which lie in the same cell as v. * * The size of clique counted is the smallest of invararg and MAXCLIQUE. * * We try the cells in increasing order of size and stop as soon as any * * cell splits. * * * *****************************************************************************/ void cellind(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i; shortish wt; set *gv; int ss,setsize; int v[MAXCLIQUE]; set *ns; shortish *cellstart,*cellsize; int iv,icell,bigcells,cell1,cell2; int pc; setword sw; #if !MAXN DYNALLOC1(set,workset,workset_sz,m,"cellind"); DYNALLOC1(shortish,workshort,workshort_sz,n+2,"cellind"); DYNALLOC2(set,wss,wss_sz,m,MAXCLIQUE-1,"cellind"); #endif for (i = n; --i >= 0;) invar[i] = 0; if (invararg <= 1 || digraph) return; if (invararg > MAXCLIQUE) setsize = MAXCLIQUE; else setsize = invararg; cellstart = workshort; cellsize = workshort + (n/2); getbigcells(ptn,level,setsize > 6 ? setsize : 6,&bigcells, cellstart,cellsize,n); for (icell = 0; icell < bigcells; ++icell) { cell1 = cellstart[icell]; cell2 = cell1 + cellsize[icell] - 1; EMPTYSET(workset,m); for (iv = cell1; iv <= cell2; ++iv) ADDELEMENT(workset,lab[iv]); for (iv = cell1; iv <= cell2; ++iv) { 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); } if (pc <= 1 || pc >= cellsize[icell] - 2) continue; ss = 1; v[1] = v[0]; while (ss > 0) { if (ss == setsize) { for (i = ss; --i >= 0;) ++invar[v[i]]; --ss; } else if ((v[ss] = nextelement((set*)wss+M*(ss-1),M,v[ss])) < 0) --ss; else { ++ss; if (ss < setsize) { gv = GRAPHROW(g,v[ss-1],m); ns = (set*)wss + M*(ss-2); for (i = M; --i >= 0;) ns[i+M] = ns[i] & ~gv[i]; v[ss] = v[ss-1]; } } } } wt = invar[lab[cell1]]; for (iv = cell1; iv <= cell2; ++iv) if (invar[lab[iv]] != wt) return; } } /***************************************************************************** * * * adjacencies() assigns to each vertex v a code depending on which cells * * it is joined to and from, and how many times. It is intended to provide * * better partitioning that the normal refinement routine for digraphs. * * It will not help with undirected graphs in nauty at all. * * * *****************************************************************************/ void adjacencies(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int i,v,w; shortish vwt,wwt; set *gv; #if !MAXN DYNALLOC1(shortish,workshort,workshort_sz,n+2,"adjacencies"); #endif vwt = 1; for (i = 0; i < n; ++i) { workshort[lab[i]] = vwt; if (ptn[i] <= level) ++vwt; invar[i] = 0; } for (v = 0, gv = (set*)g; v < n; ++v, gv += M) { vwt = FUZZ1(workshort[v]); wwt = 0; w = -1; while ((w = nextelement(gv,M,w)) >= 0) { ACCUM(wwt,FUZZ2(workshort[w])); ACCUM(invar[w],vwt); } ACCUM(invar[v],wwt); } } /***************************************************************************** * * * nautinv_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void nautinv_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in nautinv.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in nautinv.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in nautinv.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: nautinv.c version mismatch\n"); exit(1); } } /***************************************************************************** * * * nautinv_freedyn() - free the dynamic memory in this module * * * *****************************************************************************/ void nautinv_freedyn(void) { #if !MAXN DYNFREE(workset,workset_sz); DYNFREE(workshort,workshort_sz); DYNFREE(ws1,ws1_sz); DYNFREE(ws2,ws2_sz); DYNFREE(vv,vv_sz); DYNFREE(ww,ww_sz); DYNFREE(w01,w01_sz); DYNFREE(w02,w02_sz); DYNFREE(w03,w03_sz); DYNFREE(w12,w12_sz); DYNFREE(w13,w13_sz); DYNFREE(w23,w23_sz); DYNFREE(pt0,pt0_sz); DYNFREE(pt1,pt1_sz); DYNFREE(pt2,pt2_sz); DYNFREE(wss,wss_sz); #endif } nauty24r2/gtnauty.c0000600000604200001440000005541111274163463013154 0ustar bdmusers/* gtnauty.c : nauty-related routines for gtools. Jan 15, 2001 : Increased graph order limit from 2^16-1 to 2^22-1. Aug 9, 2001 : Added fgroup_inv() and fcanonise_inv() Sep 15, 2004 : Completed prototypes Oct 16, 2004 : DEAFULTOPTIONS_GRAPH Nov 17, 2005 : Added fcanonise_inv_sg() **************************************************************************/ #include "gtools.h" /* which includes naututil.h, nausparse.h, stdio.h */ static boolean issymm; static set *g0; static int gm; static int fuzz2[] = {006532,070236,035523,062437}; #define FUZZ2(x) ((x) ^ fuzz2[(x)&3]) int gt_numorbits; #ifdef REFINE void REFINE(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); #endif /**************************************************************************/ static void /* sort k longwords */ lsort(long *x, int k) { int i,j,h; long iw; j = k / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < k; ++i) { iw = x[i]; for (j = i; x[j-h] > iw; ) { x[j] = x[j-h]; if ((j -= h) < h) break; } x[j] = iw; } h /= 3; } while (h > 0); } /**************************************************************************/ void fcanonise(graph *g, int m, int n, graph *h, char *fmt, boolean digraph) /* canonise g under format fmt; result in h. fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. */ { #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; long x[MAXN]; permutation count[MAXN]; set active[MAXM]; setword workspace[4*MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(long,x,x_sz); DYNALLSTAT(permutation,count,count_sz); DYNALLSTAT(set,active,active_sz); DYNALLSTAT(setword,workspace,workspace_sz); #endif int i; boolean endfmt; int numcells,code; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if MAXN if (n > MAXN || m > MAXM) { fprintf(stderr,">E fcanonise: m or n too large\n"); ABORT(">E fcanonise"); } #else DYNALLOC1(int,lab,lab_sz,n,"fcanonise"); DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise"); DYNALLOC1(int,orbits,orbits_sz,n,"fcanonise"); DYNALLOC1(long,x,x_sz,n,"fcanonise"); DYNALLOC1(permutation,count,count_sz,n,"fcanonise"); DYNALLOC1(set,active,active_sz,m,"fcanonise"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"fcanonise"); #endif EMPTYSET(active,m); ADDELEMENT(active,0); numcells = 1; if (fmt != NULL) { endfmt = FALSE; for (i = 0; i < n; ++i) { if (!endfmt && fmt[i] != '\0') x[i] = ((long)fmt[i] << 22) | i; else { endfmt = TRUE; x[i] = ((long)'z' << 22) | i; } } lsort(x,n); for (i = 0; i < n; ++i) { lab[i] = x[i] & 0x3fffffL; if (i == n-1) ptn[i] = 0; else if ((x[i+1] >> 22) != (x[i] >> 22)) { ++numcells; ADDELEMENT(active,i+1); ptn[i] = 0; } else ptn[i] = 1; } } else { for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n-1] = 0; } if (m == 1) refine1(g,lab,ptn,0,&numcells,count,active,&code,1,n); else refine(g,lab,ptn,0,&numcells,count,active,&code,m,n); if (numcells == n || numcells == n-1 && !digraph) { for (i = 0; i < n; ++i) count[i] = lab[i]; updatecan(g,h,count,0,m,n); gt_numorbits = numcells; } else { options.getcanon = TRUE; options.defaultptn = FALSE; options.digraph = digraph; #ifdef REFINE options.userrefproc = REFINE; #endif EMPTYSET(active,m); nauty(g,lab,ptn,active,orbits,&options,&stats, workspace,4*m,m,n,h); gt_numorbits = stats.numorbits; } } /**************************************************************************/ void fcanonise_inv(graph *g, int m, int n, graph *h, char *fmt, void (*invarproc)(graph*,int*,int*,int,int,int,permutation*,int, boolean,int,int), int mininvarlevel, int maxinvarlevel, int invararg, boolean digraph) /* canonise g under format fmt; result in h. fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. This is like fcanonise() except that a invariant and its arguments can be specified. */ { #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; long x[MAXN]; permutation count[MAXN]; set active[MAXM]; setword workspace[4*MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(long,x,x_sz); DYNALLSTAT(permutation,count,count_sz); DYNALLSTAT(set,active,active_sz); DYNALLSTAT(setword,workspace,workspace_sz); #endif int i; boolean endfmt; int numcells,code; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if MAXN if (n > MAXN || m > MAXM) { fprintf(stderr,">E fcanonise: m or n too large\n"); ABORT(">E fcanonise"); } #else DYNALLOC1(int,lab,lab_sz,n,"fcanonise"); DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise"); DYNALLOC1(int,orbits,orbits_sz,n,"fcanonise"); DYNALLOC1(long,x,x_sz,n,"fcanonise"); DYNALLOC1(permutation,count,count_sz,n,"fcanonise"); DYNALLOC1(set,active,active_sz,m,"fcanonise"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"fcanonise"); #endif EMPTYSET(active,m); ADDELEMENT(active,0); numcells = 1; if (fmt != NULL) { endfmt = FALSE; for (i = 0; i < n; ++i) { if (!endfmt && fmt[i] != '\0') x[i] = ((long)fmt[i] << 22) | i; else { endfmt = TRUE; x[i] = ((long)'z' << 22) | i; } } lsort(x,n); for (i = 0; i < n; ++i) { lab[i] = x[i] & 0x3fffffL; if (i == n-1) ptn[i] = 0; else if ((x[i+1] >> 22) != (x[i] >> 22)) { ++numcells; ADDELEMENT(active,i+1); ptn[i] = 0; } else ptn[i] = 1; } } else { for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n-1] = 0; } if (m == 1) refine1(g,lab,ptn,0,&numcells,count,active,&code,1,n); else refine(g,lab,ptn,0,&numcells,count,active,&code,m,n); if (numcells == n || !digraph && numcells >= n-1) { for (i = 0; i < n; ++i) count[i] = lab[i]; updatecan(g,h,count,0,m,n); gt_numorbits = numcells; } else { options.getcanon = TRUE; options.digraph = digraph; options.defaultptn = FALSE; if (invarproc) { options.invarproc = invarproc; options.mininvarlevel = mininvarlevel; options.maxinvarlevel = maxinvarlevel; options.invararg = invararg; } #ifdef REFINE options.userrefproc = REFINE; #endif EMPTYSET(active,m); nauty(g,lab,ptn,active,orbits,&options,&stats, workspace,4*m,m,n,h); gt_numorbits = stats.numorbits; } } /**************************************************************************/ void fcanonise_inv_sg(sparsegraph *g, int m, int n, sparsegraph *h, char *fmt, void (*invarproc)(graph*,int*,int*,int,int,int,permutation*,int, boolean,int,int), int mininvarlevel, int maxinvarlevel, int invararg, boolean digraph) /* canonise g under format fmt; result in h. fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. This is like fcanonise() except that a invariant and its arguments can be specified. Version for sparse graphs. */ { #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; long x[MAXN]; permutation count[MAXN]; set active[MAXM]; setword workspace[4*MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(long,x,x_sz); DYNALLSTAT(permutation,count,count_sz); DYNALLSTAT(set,active,active_sz); DYNALLSTAT(setword,workspace,workspace_sz); #endif int i; boolean endfmt; int numcells,code; statsblk stats; static DEFAULTOPTIONS_SPARSEGRAPH(options); #if MAXN if (n > MAXN || m > MAXM) { fprintf(stderr,">E fcanonise: m or n too large\n"); ABORT(">E fcanonise"); } #else DYNALLOC1(int,lab,lab_sz,n,"fcanonise"); DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise"); DYNALLOC1(int,orbits,orbits_sz,n,"fcanonise"); DYNALLOC1(long,x,x_sz,n,"fcanonise"); DYNALLOC1(permutation,count,count_sz,n,"fcanonise"); DYNALLOC1(set,active,active_sz,m,"fcanonise"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"fcanonise"); #endif EMPTYSET(active,m); ADDELEMENT(active,0); numcells = 1; if (fmt != NULL) { endfmt = FALSE; for (i = 0; i < n; ++i) { if (!endfmt && fmt[i] != '\0') x[i] = ((long)fmt[i] << 22) | i; else { endfmt = TRUE; x[i] = ((long)'z' << 22) | i; } } lsort(x,n); for (i = 0; i < n; ++i) { lab[i] = x[i] & 0x3fffffL; if (i == n-1) ptn[i] = 0; else if ((x[i+1] >> 22) != (x[i] >> 22)) { ++numcells; ADDELEMENT(active,i+1); ptn[i] = 0; } else ptn[i] = 1; } } else { for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n-1] = 0; } refine_sg((graph*)g,lab,ptn,0,&numcells,count,active,&code,1,n); if (numcells == n || !digraph && numcells == n-1) { for (i = 0; i < n; ++i) count[i] = lab[i]; updatecan_sg((graph*)g,(graph*)h,count,0,m,n); gt_numorbits = numcells; } else { options.getcanon = TRUE; options.digraph = digraph; options.defaultptn = FALSE; if (invarproc) { options.invarproc = invarproc; options.mininvarlevel = mininvarlevel; options.maxinvarlevel = maxinvarlevel; options.invararg = invararg; } #ifdef REFINE options.userrefproc = REFINE; #endif EMPTYSET(active,m); nauty((graph*)g,lab,ptn,active,orbits,&options,&stats, workspace,4*m,m,n,(graph*)h); gt_numorbits = stats.numorbits; } } /**************************************************************************/ void fgroup(graph *g, int m, int n, char *fmt, int *orbits, int *numorbits) /* Find the orbits of undirected graph g stabilised by format fmt. The orbits are put into orbits[] and the number of them into *numorbits fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. */ { #if MAXN int lab[MAXN],ptn[MAXN]; long x[MAXN]; permutation count[MAXN]; set active[MAXM]; setword workspace[4*MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(long,x,x_sz); DYNALLSTAT(permutation,count,count_sz); DYNALLSTAT(set,active,active_sz); DYNALLSTAT(setword,workspace,workspace_sz); #endif int i,j; int orbrep; boolean endfmt; int numcells,code; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if MAXN if (n > MAXN || m > MAXM) { fprintf(stderr,">E fcanonise: m or n too large\n"); ABORT(">E fcanonise"); } #else DYNALLOC1(int,lab,lab_sz,n,"fcanonise"); DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise"); DYNALLOC1(long,x,x_sz,n,"fcanonise"); DYNALLOC1(permutation,count,count_sz,n,"fcanonise"); DYNALLOC1(set,active,active_sz,m,"fcanonise"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"fcanonise"); #endif EMPTYSET(active,m); ADDELEMENT(active,0); numcells = 1; if (fmt != NULL) { endfmt = FALSE; for (i = 0; i < n; ++i) { if (!endfmt && fmt[i] != '\0') x[i] = ((long)fmt[i] << 22) | i; else { endfmt = TRUE; x[i] = ((long)'z' << 22) | i; } } lsort(x,n); for (i = 0; i < n; ++i) { lab[i] = x[i] & 0xffff; if (i == n-1) ptn[i] = 0; else if ((x[i+1] >> 22) != (x[i] >> 22)) { ++numcells; ADDELEMENT(active,i+1); ptn[i] = 0; } else ptn[i] = 1; } } else { for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n-1] = 0; } if (m == 1) refine1(g,lab,ptn,0,&numcells,count,active,&code,1,n); else refine(g,lab,ptn,0,&numcells,count,active,&code,m,n); if (cheapautom(ptn,0,FALSE,n)) { for (i = 0; i < n; ) { if (ptn[i] == 0) { orbits[lab[i]] = lab[i]; ++i; } else { orbrep = n; j = i; do { if (lab[j] < orbrep) orbrep = lab[j]; } while (ptn[j++] != 0); for (; i < j; ++i) orbits[lab[i]] = orbrep; } } *numorbits = gt_numorbits = numcells; } else { options.getcanon = FALSE; options.defaultptn = FALSE; #ifdef REFINE options.userrefproc = REFINE; #endif EMPTYSET(active,m); nauty(g,lab,ptn,active,orbits,&options,&stats, workspace,4*m,m,n,NULL); *numorbits = gt_numorbits = stats.numorbits; } } /**************************************************************************/ void fgroup_inv(graph *g, int m, int n, char *fmt, int *orbits, int *numorbits, void (*invarproc)(graph*,int*,int*,int,int,int,permutation*,int, boolean,int,int), int mininvarlevel, int maxinvarlevel, int invararg) /* Find the orbits of undirected graph g stabilised by format fmt. The orbits are put into orbits[] and the number of them into *numorbits fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. This is like fgroup() except that a invariant and its arguments can be specified. */ { #if MAXN int lab[MAXN],ptn[MAXN]; long x[MAXN]; permutation count[MAXN]; set active[MAXM]; setword workspace[4*MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(long,x,x_sz); DYNALLSTAT(permutation,count,count_sz); DYNALLSTAT(set,active,active_sz); DYNALLSTAT(setword,workspace,workspace_sz); #endif int i,j; int orbrep; boolean endfmt; int numcells,code; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if MAXN if (n > MAXN || m > MAXM) { fprintf(stderr,">E fcanonise: m or n too large\n"); ABORT(">E fcanonise"); } #else DYNALLOC1(int,lab,lab_sz,n,"fcanonise"); DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise"); DYNALLOC1(long,x,x_sz,n,"fcanonise"); DYNALLOC1(permutation,count,count_sz,n,"fcanonise"); DYNALLOC1(set,active,active_sz,m,"fcanonise"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"fcanonise"); #endif EMPTYSET(active,m); ADDELEMENT(active,0); numcells = 1; if (fmt != NULL) { endfmt = FALSE; for (i = 0; i < n; ++i) { if (!endfmt && fmt[i] != '\0') x[i] = ((long)fmt[i] << 22) | i; else { endfmt = TRUE; x[i] = ((long)'z' << 22) | i; } } lsort(x,n); for (i = 0; i < n; ++i) { lab[i] = x[i] & 0xffff; if (i == n-1) ptn[i] = 0; else if ((x[i+1] >> 22) != (x[i] >> 22)) { ++numcells; ADDELEMENT(active,i+1); ptn[i] = 0; } else ptn[i] = 1; } } else { for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n-1] = 0; } if (m == 1) refine1(g,lab,ptn,0,&numcells,count,active,&code,1,n); else refine(g,lab,ptn,0,&numcells,count,active,&code,m,n); if (cheapautom(ptn,0,FALSE,n)) { for (i = 0; i < n; ) { if (ptn[i] == 0) { orbits[lab[i]] = lab[i]; ++i; } else { orbrep = n; j = i; do { if (lab[j] < orbrep) orbrep = lab[j]; } while (ptn[j++] != 0); for (; i < j; ++i) orbits[lab[i]] = orbrep; } } *numorbits = gt_numorbits = numcells; } else { options.getcanon = FALSE; options.defaultptn = FALSE; if (invarproc) { options.invarproc = invarproc; options.mininvarlevel = mininvarlevel; options.maxinvarlevel = maxinvarlevel; options.invararg = invararg; } #ifdef REFINE options.userrefproc = REFINE; #endif EMPTYSET(active,m); nauty(g,lab,ptn,active,orbits,&options,&stats, workspace,4*m,m,n,NULL); *numorbits = gt_numorbits = stats.numorbits; } } /**************************************************************************/ static void userlevel(int *lab, int *ptn, int level, int *orbits, statsblk *stats, int tv, int index, int tcellsize, int numcells, int cc, int n) { int i0,i; if (level != 2) return; issymm = TRUE; i0 = nextelement(g0,gm,-1); if (i0 >= 0) for (i = i0; (i = nextelement(g0,gm,i)) >= 0;) if (orbits[i] != i0) { issymm = FALSE; return; } } /*******************************************************************/ /* istransitive(g,m,n,h) g is an input graph with m,n of standard meaning. h is a place to put an output graph. If g is transitive, return 1 or 2 and put a canonically labelled version of g into h. The value is 2 for symmetric graphs, and 1 for other transitive graphs. If g is not transitive, return 0. In that case h may or may not have something in it. */ int istransitive(graph *g, int m, int n, graph *h) { int i,inv; set *gw; short wt; int d,inv0,v,w; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; long x[MAXN]; permutation count[MAXN]; setword workspace[4*MAXM]; set workset[MAXM]; set sofar[MAXM],frontier[MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(long,x,x_sz); DYNALLSTAT(permutation,count,count_sz); DYNALLSTAT(setword,workspace,workspace_sz); DYNALLSTAT(set,workset,workset_sz); DYNALLSTAT(set,sofar,sofar_sz); DYNALLSTAT(set,frontier,frontier_sz); #endif #if MAXN if (m > MAXM || n > MAXN) { fprintf(stderr, ">E istransitive: bad input parameters (n=%d m=%d)\n",n,m); exit(1); } #else DYNALLOC1(int,lab,lab_sz,n,"istransitive"); DYNALLOC1(int,ptn,ptn_sz,n,"istransitive"); DYNALLOC1(int,orbits,orbits_sz,n,"istransitive"); DYNALLOC1(long,x,x_sz,n,"istransitive"); DYNALLOC1(permutation,count,count_sz,n,"istransitive"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"istransitive"); DYNALLOC1(set,workset,workset_sz,m,"istransitive"); DYNALLOC1(set,sofar,sofar_sz,m,"istransitive"); DYNALLOC1(set,frontier,frontier_sz,m,"istransitive"); #endif for (v = 0; v < n; ++v) { inv = 0; EMPTYSET(sofar,m); ADDELEMENT(sofar,v); EMPTYSET(frontier,m); ADDELEMENT(frontier,v); for (d = 1; d < n; ++d) { EMPTYSET(workset,m); wt = 0; for (w = -1; (w = nextelement(frontier,m,w)) >= 0;) { ++wt; gw = GRAPHROW(g,w,m); for (i = m; --i >= 0;) workset[i] |= gw[i]; } if (wt == 0) break; wt += 0x73 ^ d; wt = FUZZ2(wt); inv += wt; for (i = m; --i >= 0;) { frontier[i] = workset[i] & ~sofar[i]; sofar[i] |= frontier[i]; } } if (v == 0) inv0 = inv; else if (inv != inv0) return 0; } options.getcanon = TRUE; options.userlevelproc = userlevel; #ifdef REFINE options.userrefproc = REFINE; #endif issymm = TRUE; g0 = (set*) g; gm = m; nauty(g,lab,ptn,NULL,orbits,&options,&stats,workspace,4*m,m,n,h); if (stats.numorbits != 1) return 0; else if (!issymm) return 1; else return 2; } /**************************************************************************/ void tg_canonise(graph *g, graph *h, int m, int n) /* Canonise vertex-transitive graph */ { int i; #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; set active[MAXM]; setword workspace[4*MAXM]; #else DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(set,active,active_sz); DYNALLSTAT(setword,workspace,workspace_sz); #endif statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if MAXN if (n > MAXN || m > MAXM) { fprintf(stderr,">E tg_canonise: m or n too large\n"); ABORT(">E tg_canonise"); } #else DYNALLOC1(int,lab,lab_sz,n,"tg_canonise"); DYNALLOC1(int,ptn,ptn_sz,n,"tg_canonise"); DYNALLOC1(int,orbits,orbits_sz,n,"tg_canonise"); DYNALLOC1(set,active,active_sz,m,"tg_canonise"); DYNALLOC1(setword,workspace,workspace_sz,4*m,"tg_canonise"); #endif options.getcanon = TRUE; options.defaultptn = FALSE; #ifdef REFINE options.userrefproc = REFINE; #endif for (i = 0; i < n; ++i) { lab[i] = i; ptn[i] = 1; } ptn[0] = ptn[n-1] = 0; EMPTYSET(active,m); ADDELEMENT(active,0); nauty(g,lab,ptn,active,orbits,&options,&stats,workspace,4*m,m,n,h); } nauty24r2/nautil.c0000600000604200001440000006420511405400302012734 0ustar bdmusers/***************************************************************************** * * * Auxiliary source file for version 2.4 of nauty. * * * * Copyright (1984-2010) Brendan McKay. All rights reserved. * * Subject to waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 10-Nov-87 : final changes for version 1.2 * * 5-Dec-87 : renamed to version 1.3 (no changes to this file) * * 28-Sep-88 : renamed to version 1.4 (no changes to this file) * * 23-Mar-89 : changes for version 1.5 : * * - added procedure refine1() * * - changed type of ptn from int* to nvector* in fmptn() * * - declared level in breakout() * * - changed char[] to char* in a few places * * - minor rearrangement in bestcell() * * 31-Mar-89 : - added procedure doref() * * 5-Apr-89 : - changed MAKEEMPTY uses to EMPTYSET * * 12-Apr-89 : - changed writeperm() and fmperm() to not use MARKing * * 5-May-89 : - redefined MASH to gain about 8% efficiency * * 18-Oct-90 : changes for version 1.6 : * * - improved line breaking in writeperm() * * 10-Nov-90 : - added dummy routine nautil_null() * * 27-Aug-92 : changes for version 1.7 : * * - made linelength <= 0 mean no line breaks * * 5-Jun-93 : renamed to version 1.7+ (no changes to this file) * * 18-Aug-93 : renamed to version 1.8 (no changes to this file) * * 17-Sep-93 : renamed to version 1.9 (no changes to this file) * * 29-Jun-95 : changes for version 1.10 : * * - replaced loop in nextelement() to save reference past * * end of array (thanks to Kevin Maylsiak) * * 11-Jul-96 : changes for version 2.0 : * * - added alloc_error() * * - added dynamic allocation * * 21-Oct-98 : use 077777 in place of INFINITY for CLEANUP() * * 9-Jan-00 : added nautil_check() * * 12-Feb-00 : did a little formating of the code * * 28-May-00 : added nautil_freedyn() * * 16-Aug-00 : added OLDNAUTY behaviour * * 16-Nov-00 : moved graph-specific things to naugraph.c * * use function prototypes, remove UPROC, nvector * * 22-Apr-01 : added code for compilation into Magma * * removed nautil_null() * * removed EXTDEFS and included labelorg * * 21-Nov-01 : use NAUTYREQUIRED in nautil_check() * * 26-Jun-02 : revised permset() to avoid fetch past the end of * * the array (thanks to Jan Kieffer) * * 17-Nov-03 : changed INFINITY to NAUTY_INFINITY * * 14-Sep-04 : extended prototypes to recursive functions * * 23-Nov-06 : replave targetcell() by maketargetcell() * * 10-Dec-06 : remove BIGNAUTY * * * *****************************************************************************/ #define ONE_WORD_SETS #include "nauty.h" #ifdef NAUTY_IN_MAGMA #include "io.e" #endif /* macros for hash-codes: */ /* Don't use NAUTY_INFINITY here as that would make the canonical * labelling depend on whether BIGNAUTY is in operation */ #define MASH(l,i) ((((l) ^ 065435) + (i)) & 077777) /* : expression whose long value depends only on long l and int/long i. Anything goes, preferably non-commutative. */ #define CLEANUP(l) ((int)((l) % 077777)) /* : expression whose value depends on long l and is less than 077777 when converted to int then short. Anything goes. */ #if MAXM==1 #define M 1 #else #define M m #endif #if !MAXN DYNALLSTAT(permutation,workperm,workperm_sz); #else static permutation workperm[MAXN]; #endif int labelorg = 0; /* aproto: header new_nauty_protos.h */ /***************************************************************************** * * * nextelement(set1,m,pos) = the position of the first element in set set1 * * which occupies a position greater than pos. If no such element exists, * * the value is -1. pos can have any value less than n, including negative * * values. * * * * GLOBALS ACCESSED: none * * * *****************************************************************************/ int nextelement(set *set1, int m, int pos) { setword setwd; int w; #if MAXM==1 if (pos < 0) setwd = set1[0]; else setwd = set1[0] & BITMASK(pos); if (setwd == 0) return -1; else return FIRSTBIT(setwd); #else if (pos < 0) { w = 0; setwd = set1[0]; } else { w = SETWD(pos); setwd = set1[w] & BITMASK(SETBT(pos)); } for (;;) { if (setwd != 0) return TIMESWORDSIZE(w) + FIRSTBIT(setwd); if (++w == m) return -1; setwd = set1[w]; } #endif } /***************************************************************************** * * * permset(set1,set2,m,perm) defines set2 to be the set * * {perm[i] | i in set1}. * * * * GLOBALS ACCESSED: bit,leftbit * * * *****************************************************************************/ void permset(set *set1, set *set2, int m, permutation *perm) { setword setw; int pos,w,b; EMPTYSET(set2,m); #if MAXM==1 setw = set1[0]; while (setw != 0) { TAKEBIT(b,setw); pos = perm[b]; ADDELEMENT(set2,pos); } #else for (w = 0; w < m; ++w) { setw = set1[w]; while (setw != 0) { TAKEBIT(b,setw); pos = perm[TIMESWORDSIZE(w)+b]; ADDELEMENT(set2,pos); } } #endif } /***************************************************************************** * * * putstring(f,s) writes the nul-terminated string s to file f. * * * *****************************************************************************/ void putstring(FILE *f, char *s) { while (*s != '\0') { PUTC(*s,f); ++s; } } /***************************************************************************** * * * itos(i,s) converts the int i to a nul-terminated decimal character * * string s. The value returned is the number of characters excluding * * the nul. * * * * GLOBALS ACCESSED: NONE * * * *****************************************************************************/ int itos(int i, char *s) { int digit,j,k; char c; int ans; if (i < 0) { k = 0; i = -i; j = 1; s[0] = '-'; } else { k = -1; j = 0; } do { digit = i % 10; i = i / 10; s[++k] = digit + '0'; } while (i); s[k+1] = '\0'; ans = k + 1; for (; j < k; ++j, --k) { c = s[j]; s[j] = s[k]; s[k] = c; } return ans; } /***************************************************************************** * * * orbits represents a partition of {0,1,...,n-1}, by orbits[i] = the * * smallest element in the same cell as i. orbjoin(orbits,autom,n) updates * * the partition orbits to the join of its current value and the cycle * * partition of perm. The function value returned is the new number of * * cells. * * * * GLOBALS ACCESSED: NONE * * * *****************************************************************************/ int orbjoin(int *orbits, permutation *perm, int n) { int i,j1,j2; for (i = 0; i < n; ++i) { j1 = orbits[i]; while (orbits[j1] != j1) j1 = orbits[j1]; j2 = orbits[perm[i]]; while (orbits[j2] != j2) j2 = orbits[j2]; if (j1 < j2) orbits[j2] = j1; else if (j1 > j2) orbits[j1] = j2; } j1 = 0; for (i = 0; i < n; ++i) if ((orbits[i] = orbits[orbits[i]]) == i) ++j1; return j1; } /***************************************************************************** * * * writeperm(f,perm,cartesian,linelength,n) writes the permutation perm to * * the file f. The cartesian representation (i.e. perm itself) is used if * * cartesian != FALSE; otherwise the cyclic representation is used. No * * more than linelength characters (not counting '\n') are written on each * * line, unless linelength is ridiculously small. linelength<=0 causes no * * line breaks at all to be made. The global int labelorg is added to each * * vertex number. * * * * GLOBALS ACCESSED: itos(),putstring() * * * *****************************************************************************/ void writeperm(FILE *f, permutation *perm, boolean cartesian, int linelength, int n) { int i,k,l,curlen,intlen; char s[30]; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"writeperm"); #endif /* CONDNL(x) writes end-of-line and 3 spaces if x characters won't fit on the current line. */ #define CONDNL(x) if (linelength>0 && curlen+(x)>linelength)\ {putstring(f,"\n ");curlen=3;} curlen = 0; if (cartesian) { for (i = 0; i < n; ++i) { intlen = itos(perm[i]+labelorg,s); CONDNL(intlen+1); PUTC(' ',f); putstring(f,s); curlen += intlen + 1; } PUTC('\n',f); } else { for (i = n; --i >= 0;) workperm[i] = 0; for (i = 0; i < n; ++i) { if (workperm[i] == 0 && perm[i] != i) { l = i; intlen = itos(l+labelorg,s); if (curlen > 3) CONDNL(2*intlen+4); PUTC('(',f); do { putstring(f,s); curlen += intlen + 1; k = l; l = perm[l]; workperm[k] = 1; if (l != i) { intlen = itos(l+labelorg,s); CONDNL(intlen+2); PUTC(' ',f); } } while (l != i); PUTC(')',f); ++curlen; } } if (curlen == 0) putstring(f,"(1)\n"); else PUTC('\n',f); } } /***************************************************************************** * * * fmperm(perm,fix,mcr,m,n) uses perm to construct fix and mcr. fix * * contains those points are fixed by perm, while mcr contains the set of * * those points which are least in their orbits. * * * * GLOBALS ACCESSED: bit * * * *****************************************************************************/ void fmperm(permutation *perm, set *fix, set *mcr, int m, int n) { int i,k,l; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"writeperm"); #endif EMPTYSET(fix,m); EMPTYSET(mcr,m); for (i = n; --i >= 0;) workperm[i] = 0; for (i = 0; i < n; ++i) if (perm[i] == i) { ADDELEMENT(fix,i); ADDELEMENT(mcr,i); } else if (workperm[i] == 0) { l = i; do { k = l; l = perm[l]; workperm[k] = 1; } while (l != i); ADDELEMENT(mcr,i); } } /***************************************************************************** * * * fmptn(lab,ptn,level,fix,mcr,m,n) uses the partition at the specified * * level in the partition nest (lab,ptn) to make sets fix and mcr. fix * * represents the points in trivial cells of the partition, while mcr * * represents those points which are least in their cells. * * * * GLOBALS ACCESSED: bit * * * *****************************************************************************/ void fmptn(int *lab, int *ptn, int level, set *fix, set *mcr, int m, int n) { int i,lmin; EMPTYSET(fix,m); EMPTYSET(mcr,m); for (i = 0; i < n; ++i) if (ptn[i] <= level) { ADDELEMENT(fix,lab[i]); ADDELEMENT(mcr,lab[i]); } else { lmin = lab[i]; do if (lab[++i] < lmin) lmin = lab[i]; while (ptn[i] > level); ADDELEMENT(mcr,lmin); } } /***************************************************************************** * * * doref(g,lab,ptn,level,numcells,qinvar,invar,active,code,refproc, * * invarproc,mininvarlev,maxinvarlev,invararg,digraph,m,n) * * is used to perform a refinement on the partition at the given level in * * (lab,ptn). The number of cells is *numcells both for input and output. * * The input active is the active set for input to the refinement procedure * * (*refproc)(), which must have the argument list of refine(). * * active may be arbitrarily changed. invar is used for working storage. * * First, (*refproc)() is called. Then, if invarproc!=NULL and * * |mininvarlev| <= level <= |maxinvarlev|, the routine (*invarproc)() is * * used to compute a vertex-invariant which may refine the partition * * further. If it does, (*refproc)() is called again, using an active set * * containing all but the first fragment of each old cell. Unless g is a * * digraph, this guarantees that the final partition is equitable. The * * arguments invararg and digraph are passed to (*invarproc)() * * uninterpretted. The output argument code is a composite of the codes * * from all the calls to (*refproc)(). The output argument qinvar is set * * to 0 if (*invarproc)() is not applied, 1 if it is applied but fails to * * refine the partition, and 2 if it succeeds. * * See the file nautinv.c for a further discussion of vertex-invariants. * * Note that the dreadnaut I command generates a call to this procedure * * with level = mininvarlevel = maxinvarlevel = 0. * * * *****************************************************************************/ void doref(graph *g, int *lab, int *ptn, int level, int *numcells, int *qinvar, permutation *invar, set *active, int *code, void (*refproc)(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int), void (*invarproc)(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int), int mininvarlev, int maxinvarlev, int invararg, boolean digraph, int m, int n) { int j,h; permutation pw; int iw; int i,cell1,cell2,nc,tvpos,minlev,maxlev; long longcode; boolean same; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"doref"); #endif if ((tvpos = nextelement(active,M,-1)) < 0) tvpos = 0; (*refproc)(g,lab,ptn,level,numcells,invar,active,code,M,n); minlev = (mininvarlev < 0 ? -mininvarlev : mininvarlev); maxlev = (maxinvarlev < 0 ? -maxinvarlev : maxinvarlev); if (invarproc != NULL && *numcells < n && level >= minlev && level <= maxlev) { (*invarproc)(g,lab,ptn,level,*numcells,tvpos,invar,invararg, digraph,M,n); EMPTYSET(active,m); for (i = n; --i >= 0;) workperm[i] = invar[lab[i]]; nc = *numcells; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { pw = workperm[cell1]; same = TRUE; for (cell2 = cell1; ptn[cell2] > level; ++cell2) if (workperm[cell2+1] != pw) same = FALSE; if (same) continue; j = (cell2 - cell1 + 1) / 3; h = 1; do h = 3 * h + 1; while (h < j); do /* shell sort */ { for (i = cell1 + h; i <= cell2; ++i) { iw = lab[i]; pw = workperm[i]; for (j = i; workperm[j-h] > pw; ) { workperm[j] = workperm[j-h]; lab[j] = lab[j-h]; if ((j -= h) < cell1 + h) break; } workperm[j] = pw; lab[j] = iw; } h /= 3; } while (h > 0); for (i = cell1 + 1; i <= cell2; ++i) if (workperm[i] != workperm[i-1]) { ptn[i-1] = level; ++*numcells; ADDELEMENT(active,i); } } if (*numcells > nc) { *qinvar = 2; longcode = *code; (*refproc)(g,lab,ptn,level,numcells,invar,active,code,M,n); longcode = MASH(longcode,*code); *code = CLEANUP(longcode); } else *qinvar = 1; } else *qinvar = 0; } /***************************************************************************** * * * maketargetcell(g,lab,ptn,level,tcell,tcellsize,&cellpos, * * tc_level,digraph,hint,targetcell,m,n) * * calls targetcell() to determine the target cell at the specified level * * in the partition nest (lab,ptn). It must be a nontrivial cell (if not, * * the first cell. The intention of hint is that, if hint >= 0 and there * * is a suitable non-trivial cell starting at position hint in lab, * * that cell is chosen. * * tc_level and digraph are input options. * * When a cell is chosen, tcell is set to its contents, *tcellsize to its * * size, and cellpos to its starting position in lab. * * * * GLOBALS ACCESSED: bit * * * *****************************************************************************/ void maketargetcell(graph *g, int *lab, int *ptn, int level, set *tcell, int *tcellsize, int *cellpos, int tc_level, boolean digraph, int hint, int (*targetcell)(graph*,int*,int*,int,int,boolean,int,int,int), int m, int n) { int i,j,k; i = (*targetcell)(g,lab,ptn,level,tc_level,digraph,hint,m,n); for (j = i + 1; ptn[j] > level; ++j) {} *tcellsize = j - i + 1; EMPTYSET(tcell,m); for (k = i; k <= j; ++k) ADDELEMENT(tcell,lab[k]); *cellpos = i; } /***************************************************************************** * * * shortprune(set1,set2,m) ANDs the contents of set set2 into set set1. * * * * GLOBALS ACCESSED: NONE * * * *****************************************************************************/ void shortprune(set *set1, set *set2, int m) { int i; for (i = 0; i < M; ++i) INTERSECT(set1[i],set2[i]); } /***************************************************************************** * * * breakout(lab,ptn,level,tc,tv,active,m) operates on the partition at * * the specified level in the partition nest (lab,ptn). It finds the * * element tv, which is in the cell C starting at index tc in lab (it had * * better be) and splits C in the two cells {tv} and C\{tv}, in that order. * * It also sets the set active to contain just the element tc. * * * * GLOBALS ACCESSED: bit * * * *****************************************************************************/ void breakout(int *lab, int *ptn, int level, int tc, int tv, set *active, int m) { int i,prev,next; EMPTYSET(active,m); ADDELEMENT(active,tc); i = tc; prev = tv; do { next = lab[i]; lab[i++] = prev; prev = next; } while (prev != tv); ptn[tc] = level; } /***************************************************************************** * * * longprune(tcell,fix,bottom,top,m) removes zero or elements of the set * * tcell. It is assumed that addresses bottom through top-1 contain * * contiguous pairs of sets (f1,m1),(f2,m2), ... . tcell is intersected * * with each mi such that fi is a subset of fix. * * * * GLOBALS ACCESSED: NONE * * * *****************************************************************************/ void longprune(set *tcell, set *fix, set *bottom, set *top, int m) { int i; while (bottom < top) { for (i = 0; i < M; ++i) if (NOTSUBSET(fix[i],bottom[i])) break; bottom += M; if (i == M) for (i = 0; i < M; ++i) INTERSECT(tcell[i],bottom[i]); bottom += M; } } /***************************************************************************** * * * nautil_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void nautil_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in nautil.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in nautil.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in nautil.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: nautil.c version mismatch\n"); exit(1); } } /***************************************************************************** * * * alloc_error() writes a message and exits. Used by DYNALLOC? macros. * * * *****************************************************************************/ void alloc_error(char *s) { fprintf(ERRFILE,"Dynamic allocation failed: %s\n",s); exit(2); } /***************************************************************************** * * * nautil_freedyn() - free the dynamic memory in this module * * * *****************************************************************************/ void nautil_freedyn(void) { #if !MAXN DYNFREE(workperm,workperm_sz); #endif } nauty24r2/nautinv.h0000600000604200001440000000534611274163463013154 0ustar bdmusers/***************************************************************************** * This is the header file for versions 2.2 of nautinv.c. * * * * Copyright (1984-2002) Brendan McKay. All rights reserved. * * Subject to the waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 20-Apr-01 : initial creation out of naututil.h * * * *****************************************************************************/ #include "nauty.h" /* which includes stdio.h */ #ifdef __cplusplus extern "C" { #endif extern void adjacencies(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void adjtriang(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void cellcliq(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void cellfano(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void cellfano2(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void cellind(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void cellquads(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void cellquins(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void celltrips(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void cellstarts(int*,int,set*,int,int); extern void cliques(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void distances(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void getbigcells(int*,int,int,int*,shortish*,shortish*,int); extern void indsets(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void nautinv_check(int,int,int,int); extern void nautinv_freedyn(void); extern void quadruples(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void setnbhd(graph*,int,int,set*,set*); extern void triples(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); extern void twopaths(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); #ifdef __cplusplus } #endif nauty24r2/gtools-h.in0000600000604200001440000001641611405400216013365 0ustar bdmusers/***************************************************************************** * This is the main header file for gtools. nauty version 2.4. * * @configure_input@ *****************************************************************************/ /* The parts between the ==== lines are modified by configure when creating gtools.h out of gtools-h.in. If configure is not being used, it is necessary to check they are correct. ====================================================================*/ #ifndef _GTOOLS_H_ /* only process this file once */ #define _GTOOLS_H_ #define HAVE_ERRNO_H @header_errno_h@ /* exists */ #define HAVE_PERROR @have_perror@ /* perror() exists */ #define HAVE_PIPE @have_pipe@ /* pipe() exists */ #define HAVE_WAIT @have_wait@ /* wait() exists */ #define HAVE_POPEN @have_popen@ /* popen() and pclose() exist */ #define POPEN_DEC @popen_dec@ /* popen() is declared in stdio.h */ #define FTELL_DEC @ftell_dec@ /* ftell() is declared in stdio.h */ #define FDOPEN_DEC @fdopen_dec@ /* fdopen() is declared in stdio.h */ #define SORTPROG "@sort_prog@" /* name of sort program */ #define SORT_NEWKEY @sort_newparams_ok@ /* if -k is supported */ #define HAVE_PID_T @have_pid_t@ /* pid_t is defined */ #define PUTENV_DEC @putenv_dec@ /* putenv() is declared in stdlib.h */ #define SETENV_DEC @setenv_dec@ /* setenv() is declared in stdlib.h */ #define HAVE_PUTENV @have_putenv@ /* putenv() exists */ #define HAVE_SETENV @have_setenv@ /* setenv() exists */ /* @edit_msg@ */ /*==================================================================*/ #ifndef MAXN #define MAXN 0 #endif #define SIZELEN(n) ((n)<=SMALLN?1:((n)<=SMALLISHN?4:8)) /* length of size code in bytes */ #define G6LEN(n) (((n)*((n)-1)/2+5)/6+SIZELEN(n)) /* exactly graph6 string length excluding \n\0 */ #include "naututil.h" /* which includes stdio.h */ #include "nausparse.h" #if HAVE_ERRNO_H #include #else extern int errno; #endif #if HAVE_PERROR #define ABORT(msg) do {if (errno != 0) perror(msg); exit(1);} while(0) #else #define ABORT(msg) do {exit(1);} while(0) #endif #if PUTENV_DEC && HAVE_PUTENV #define SET_C_COLLATION putenv("LC_COLLATE=C") #elif SETENV_DEC && HAVE_SETENV #define SET_C_COLLATION setenv("LC_COLLATE","C",1) #elif HAVE_PUTENV int putenv(char*); #define SET_C_COLLATION putenv("LC_COLLATE=C") #elif HAVE_SETENV int setenv(const char*,const char*,int); #define SET_C_COLLATION setenv("LC_COLLATE","C",1) #else #define SET_C_COLLATION #endif #if HAS_STDIO_UNLOCK && !defined(NAUTY_IN_MAGMA) && !defined(IS_JAVA) #define FLOCKFILE(f) flockfile(f) #define FUNLOCKFILE(f) funlockfile(f) #define GETC(f) getc_unlocked(f) #undef PUTC #define PUTC(c,f) putc_unlocked(c,f) #else #define FLOCKFILE(f) #define FUNLOCKFILE(f) #define GETC(f) getc(f) #undef PUTC #define PUTC(c,f) putc(c,f) #endif #define BIAS6 63 #define MAXBYTE 126 #define SMALLN 62 #define SMALLISHN 258047 #define TOPBIT6 32 #define C6MASK 63 #define GRAPH6_HEADER ">>graph6<<" #define SPARSE6_HEADER ">>sparse6<<" #define PLANARCODE_HEADER ">>planar_code<<" #define PLANARCODELE_HEADER ">>planar_code le<<" #define PLANARCODEBE_HEADER ">>planar_code be<<" #define EDGECODE_HEADER ">>edge_code<<" #define GRAPH6 1 #define SPARSE6 2 #define PLANARCODE 4 #define PLANARCODELE 8 #define PLANARCODEBE 16 #define EDGECODE 32 #define PLANARCODEANY (PLANARCODE|PLANARCODELE|PLANARCODEBE) #define UNKNOWN_TYPE 256 #define HAS_HEADER 512 #define ARG_OK 0 #define ARG_MISSING 1 #define ARG_TOOBIG 2 #define ARG_ILLEGAL 3 #define MAXARG 2000000000L #define NOLIMIT (MAXARG+31L) #define SWBOOLEAN(c,bool) if (sw==c) bool=TRUE; #define SWINT(c,bool,val,id) if (sw==c) \ {bool=TRUE;arg_int(&arg,&val,id);} #define SWLONG(c,bool,val,id) if (sw==c) \ {bool=TRUE;arg_long(&arg,&val,id);} #define SWRANGE(c,sep,bool,val1,val2,id) if (sw==c) \ {bool=TRUE;arg_range(&arg,sep,&val1,&val2,id);} #ifdef HELPTEXT2 #define PUTHELPTEXT printf("\nUsage: %s\n\n%s",USAGE,HELPTEXT1);\ printf("%s",HELPTEXT2); #else #define PUTHELPTEXT printf("\nUsage: %s\n\n%s",USAGE,HELPTEXT) #endif #define HELP if (argc > 1 && (strcmp(argv[1],"-help")==0 \ || strcmp(argv[1],"/?")==0 \ || strcmp(argv[1],"--help")==0)) \ { PUTHELPTEXT; return 0;} #define GETHELP \ fprintf(stderr," Use %s -help to see more detailed instructions.\n",argv[0]) #define alloc_error gt_abort #define CATMSG0(fmt) sprintf(msg+strlen(msg),fmt) #define CATMSG1(fmt,x1) sprintf(msg+strlen(msg),fmt,x1) #define CATMSG2(fmt,x1,x2) sprintf(msg+strlen(msg),fmt,x1,x2) #define CATMSG3(fmt,x1,x2,x3) sprintf(msg+strlen(msg),fmt,x1,x2,x3) #define CATMSG4(fmt,x1,x2,x3,x4) sprintf(msg+strlen(msg),fmt,x1,x2,x3,x4) #define CATMSG5(fmt,x1,x2,x3,x4,x5) sprintf(msg+strlen(msg),fmt,x1,x2,x3,x4,x5) #define CATMSG6(fmt,x1,x2,x3,x4,x5,x6) \ sprintf(msg+strlen(msg),fmt,x1,x2,x3,x4,x5,x6) /************************************************************************/ #ifdef __cplusplus extern "C" { #endif extern void gtools_check(int,int,int,int); extern FILE *opengraphfile(char*,int*,boolean,long); extern void writeline(FILE*,char*); extern char *gtools_getline(FILE*); extern int graphsize(char*); extern void stringcounts(char*,int*,size_t*); extern void stringtograph(char*,graph*,int); extern size_t edgecount(char*); extern graph *readg(FILE*,graph*,int,int*,int*); extern char *ntog6(graph*,int,int); extern char *ntos6(graph*,int,int); extern char *sgtos6(sparsegraph*); extern void writeg6(FILE*,graph*,int,int); extern void writes6(FILE*,graph*,int,int); extern void writes6_sg(FILE*,sparsegraph*); extern void writepc_sg(FILE*,sparsegraph*); extern void stringtosparsegraph(char*,sparsegraph*,int*); extern sparsegraph *read_sg(FILE*,sparsegraph*); extern sparsegraph *read_sg_loops(FILE*,sparsegraph*,int*); extern sparsegraph *readpc_sg(FILE*,sparsegraph*); extern sparsegraph *readpcle_sg(FILE*,sparsegraph*); extern sparsegraph *read_ec(FILE*,sparsegraph*); extern void writeec_sg(FILE*,sparsegraph*); extern void writelast(FILE*); extern int longval(char**,long*); extern void arg_int(char**,int*,char*); extern void arg_long(char**,long*,char*); extern void arg_range(char**,char*,long*,long*,char*); extern void writerange(FILE*,int,long,long); extern void gt_abort(char*); extern char *stringcopy(char*); extern boolean strhaschar(char*,int); extern void fcanonise(graph*,int,int,graph*,char*,boolean); extern void fcanonise_inv (graph*,int,int,graph*,char*,void(*)(graph*,int*,int*,int, int,int,permutation*,int,boolean,int,int),int,int,int,boolean); extern void fcanonise_inv_sg (sparsegraph*,int,int,sparsegraph*,char*,void(*)(graph*,int*,int*, int,int,int,permutation*,int,boolean,int,int),int,int,int,boolean); extern void fgroup(graph*,int,int,char*,int*,int*); extern void fgroup_inv (graph*,int,int,char*,int*,int*,void(*)(graph*,int*,int*,int, int,int,permutation*,int,boolean,int,int),int,int,int); extern int istransitive(graph*,int,int,graph*); extern void tg_canonise(graph*,graph*,int,int); extern int readg_code; extern char *readg_line; extern size_t ogf_linelen; extern boolean is_pipe; #ifdef __cplusplus } #endif #ifdef CPUDEFS CPUDEFS #endif /* @edit_msg@ */ #endif /* _GTOOLS_H_ */ nauty24r2/makefile.basic0000600000604200001440000004052711405400565014070 0ustar bdmusers# makefile for nauty 2.4, including gtools # makefile. Generated from makefile.in by configure. SHELL=/bin/sh CC=gcc CFLAGS=-O3 SAFECFLAGS= -O3 LDFLAGS= LOK=1 # 0 if no 64-bit integers TESTPROGS=dreadtest dreadtestS dreadtestS1 dreadtest4K dreadtest1 dreadtestW1 dreadtestL1 dreadtestL EXEEXT= BIGTEST=1 # set to 0 if less than 512MB is available SMALL=-DMAXN=WORDSIZE L1=-DMAXN=WORDSIZE -DWORDSIZE=64 W1=-DMAXN=WORDSIZE -DWORDSIZE=32 S1=-DMAXN=WORDSIZE -DWORDSIZE=16 S=-DWORDSIZE=16 L=-DWORDSIZE=64 FOURK=-DMAXN=4096 all : nauty gtools ; nauty : dreadnaut ; gtools : copyg listg labelg dretog amtog geng complg shortg showg NRswitchg \ biplabg addedgeg deledgeg countg pickg genrang newedgeg catg genbg directg \ multig planarg gentourng ; rng.o: rng.c ${CC} -c ${CFLAGS} rng.c dreadnaut: dreadnaut.c naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${CC} -o dreadnaut ${SAFECFLAGS} dreadnaut.c \ naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${LDFLAGS} naututil.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} naututil.c nautil.o: nauty.h nautil.c ${CC} -c ${CFLAGS} nautil.c nauty.o: nauty.h nauty.c ${CC} -c ${CFLAGS} nauty.c nautinv.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} nautinv.c nautaux.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} nautaux.c naugraph.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} naugraph.c nausparse.o : nauty.h nausparse.h nausparse.c ${CC} -c ${CFLAGS} nausparse.c dreadnaut1: dreadnaut.c naututil1.o nauty1.o nautil1.o \ nautinv1.o naugraph1.o rng.o ${CC} -o dreadnaut1 ${SAFECFLAGS} ${SMALL} dreadnaut.c naututil1.o \ nauty1.o nautil1.o nautinv1.o naugraph1.o rng.o ${LDFLAGS} naututil1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${SMALL} -o naututil1.o naututil.c nautil1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${SMALL} -o nautil1.o nautil.c nauty1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${SMALL} -o nauty1.o nauty.c nautinv1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${SMALL} -o nautinv1.o nautinv.c nautaux1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${SMALL} -o nautaux1.o nautaux.c naugraph1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${SMALL} -o naugraph1.o naugraph.c dreadnaut4K: dreadnaut.c naututil4K.o nauty4K.o nautil4K.o \ nautinv4K.o naugraph4K.o rng.o ${CC} -o dreadnaut4K ${SAFECFLAGS} ${FOURK} dreadnaut.c naututil4K.o \ nauty4K.o nautil4K.o nautinv4K.o naugraph4K.o rng.o ${LDFLAGS} naututil4K.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${FOURK} -o naututil4K.o naututil.c nautil4K.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${FOURK} -o nautil4K.o nautil.c nauty4K.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${FOURK} -o nauty4K.o nauty.c nautinv4K.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${FOURK} -o nautinv4K.o nautinv.c nautaux4K.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${FOURK} -o nautaux4K.o nautaux.c naugraph4K.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${FOURK} -o naugraph4K.o naugraph.c dreadnautL1: dreadnaut.c naututilL1.o nautyL1.o nautilL1.o nautinvL1.o \ naugraphL1.o rng.o ${CC} -o dreadnautL1 ${SAFECFLAGS} ${L1} dreadnaut.c naututilL1.o \ nautyL1.o nautilL1.o nautinvL1.o naugraphL1.o rng.o ${LDFLAGS} naututilL1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${L1} -o naututilL1.o naututil.c nautilL1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${L1} -o nautilL1.o nautil.c nautyL1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${L1} -o nautyL1.o nauty.c nautinvL1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${L1} -o nautinvL1.o nautinv.c nautauxL1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${L1} -o nautauxL1.o nautaux.c naugraphL1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${L1} -o naugraphL1.o naugraph.c dreadnautW1: dreadnaut.c naututilW1.o nautyW1.o nautilW1.o nautinvW1.o \ naugraphW1.o rng.o ${CC} -o dreadnautW1 ${SAFECFLAGS} ${W1} dreadnaut.c naututilW1.o \ nautyW1.o nautilW1.o nautinvW1.o naugraphW1.o rng.o ${LDFLAGS} naututilW1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${W1} -o naututilW1.o naututil.c nautilW1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${W1} -o nautilW1.o nautil.c nautyW1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${W1} -o nautyW1.o nauty.c nautinvW1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${W1} -o nautinvW1.o nautinv.c nautauxW1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${W1} -o nautauxW1.o nautaux.c naugraphW1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${W1} -o naugraphW1.o naugraph.c gtoolsW1.o : gtools.h gtools.c ${CC} -c ${CFLAGS} ${W1} -o gtoolsW1.o gtools.c dreadnautS1: dreadnaut.c naututilS1.o nautyS1.o nautilS1.o nautinvS1.o \ naugraphS1.o rng.o ${CC} -o dreadnautS1 ${SAFECFLAGS} ${S1} dreadnaut.c naututilS1.o \ nautyS1.o nautilS1.o nautinvS1.o naugraphS1.o rng.o ${LDFLAGS} naututilS1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${S1} -o naututilS1.o naututil.c nautilS1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${S1} -o nautilS1.o nautil.c nautyS1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${S1} -o nautyS1.o nauty.c nautinvS1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${S1} -o nautinvS1.o nautinv.c nautauxS1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${S1} -o nautauxS1.o nautaux.c naugraphS1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${S1} -o naugraphS1.o naugraph.c dreadnautL: dreadnaut.c naututilL.o nautyL.o nautilL.o nautinvL.o \ naugraphL.o rng.o ${CC} -o dreadnautL ${SAFECFLAGS} ${L} dreadnaut.c naututilL.o \ nautyL.o nautilL.o nautinvL.o naugraphL.o rng.o ${LDFLAGS} naututilL.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${L} -o naututilL.o naututil.c nautilL.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${L} -o nautilL.o nautil.c nautyL.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${L} -o nautyL.o nauty.c nautinvL.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${L} -o nautinvL.o nautinv.c nautauxL.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${L} -o nautauxL.o nautaux.c naugraphL.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${L} -o naugraphL.o naugraph.c dreadnautS: dreadnaut.c naututilS.o nautyS.o nautilS.o nautinvS.o \ naugraphS.o rng.o ${CC} -o dreadnautS ${SAFECFLAGS} ${S} dreadnaut.c naututilS.o \ nautyS.o nautilS.o nautinvS.o naugraphS.o rng.o ${LDFLAGS} naututilS.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${S} -o naututilS.o naututil.c nautilS.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${S} -o nautilS.o nautil.c nautyS.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${S} -o nautyS.o nauty.c nautinvS.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${S} -o nautinvS.o nautinv.c nautauxS.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${S} -o nautauxS.o nautaux.c naugraphS.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${S} -o naugraphS.o naugraph.c clean: rm -f *.o config.log config.cache config.status rm -f dreadtest${EXEEXT} dreadtestL${EXEEXT} \ dreadtestS${EXEEXT} dreadtestS1${EXEEXT} \ dreadtest4K${EXEEXT} dreadtest1${EXEEXT} \ dreadtestL1${EXEEXT} dreadtestW1${EXEEXT} gtools.h : nauty.h naututil.h nausparse.h touch gtools.h gtools.o : gtools.h gtools.c ${CC} -c ${CFLAGS} gtools.c gtnauty.o : gtools.h gtnauty.c ${CC} -c ${CFLAGS} gtnauty.c gutil1.o : gtools.h gutils.h gutil1.c ${CC} -c ${CFLAGS} gutil1.c gutil2.o : gtools.h gutils.h gutil2.c ${CC} -c ${CFLAGS} gutil2.c catg : gtools.h catg.c gtools.o ${CC} -o catg ${CFLAGS} catg.c gtools.o ${LDFLAGS} copyg : gtools.h copyg.c gtools.o ${CC} -o copyg ${CFLAGS} copyg.c gtools.o ${LDFLAGS} listg : gtools.h listg.c gtools.o nautil.o ${CC} -o listg ${CFLAGS} listg.c gtools.o nautil.o ${LDFLAGS} labelg : gtools.h naututil.h labelg.c gtools.o gtnauty.o nauty.o \ nautil.o naugraph.o nautinv.o nausparse.h nausparse.o \ gutils.h gutil2.o ${CC} -o labelg ${SAFECFLAGS} labelg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nautinv.o nausparse.o \ gutil2.o ${LDFLAGS} shortg : gtools.h shortg.c gtools.o gtnauty.o nauty.o nautil.o naugraph.o \ nausparse.h nausparse.o gutils.h gutil2.o nautinv.h nautinv.o ${CC} -o shortg ${CFLAGS} shortg.c gtools.o gtnauty.o nautinv.o \ nauty.o nautil.o naugraph.o nausparse.o gutil2.o ${LDFLAGS} dretog : gtools.h dretog.c gtools.o naututil.o nautil.o naugraph.o rng.o ${CC} -o dretog ${CFLAGS} dretog.c \ gtools.o naututil.o nautil.o rng.o naugraph.o ${LDFLAGS} amtog : gtools.h amtog.c gtools.o ${CC} -o amtog ${CFLAGS} amtog.c gtools.o ${LDFLAGS} genbg : gtools.h genbg.c gtoolsW1.o nautyW1.o nautilW1.o naugraphW1.o ${CC} -o genbg ${CFLAGS} ${W1} genbg.c gtoolsW1.o \ nautyW1.o nautilW1.o naugraphW1.o ${LDFLAGS} genbgL : gtools.h genbg.c gtoolsL1.o nautyL1.o nautilL1.o naugraphL1.o ${CC} -o genbgL ${CFLAGS} ${L1} -DMAXN1=30 genbg.c gtoolsL1.o \ nautyL1.o nautilL1.o naugraphL1.o ${LDFLAGS} geng : gtools.h geng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o geng ${CFLAGS} -DMAXN=32 geng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} geng16 : gtools.h geng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o geng16 ${CFLAGS} -DMAXN=16 geng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} geng24 : gtools.h geng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o geng24 ${CFLAGS} -DMAXN=24 geng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} gentourng : gtools.h gentourng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o gentourng ${CFLAGS} -DMAXN=24 gentourng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} genrang : gtools.h genrang.c gtools.o naututil.o nautil.o naugraph.o \ rng.o nausparse.o ${CC} -o genrang ${CFLAGS} genrang.c nausparse.o \ gtools.o nautil.o naututil.o naugraph.o rng.o ${LDFLAGS} complg : gtools.h complg.c gtools.o gtnauty.o nauty.o nautil.o \ naugraph.o nausparse.o ${CC} -o complg ${CFLAGS} complg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} biplabg : gtools.h biplabg.c gtools.o nautil.o naugraph.o gutil1.o ${CC} -o biplabg ${CFLAGS} biplabg.c \ gtools.o nautil.o naugraph.o gutil1.o ${LDFLAGS} NRswitchg : gtools.h NRswitchg.c gtools.o gtnauty.o nauty.o nautil.o \ nausparse.o naugraph.o ${CC} -o NRswitchg ${CFLAGS} NRswitchg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} deledgeg : gtools.h deledgeg.c gtools.o gtnauty.o nauty.o nautil.o \ naugraph.o nausparse.o ${CC} -o deledgeg ${CFLAGS} deledgeg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} addedgeg : gtools.h addedgeg.c gtools.o gtnauty.o nauty.o nautil.o \ naugraph.o gutil1.o nausparse.o ${CC} -o addedgeg ${CFLAGS} addedgeg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o gutil1.o nausparse.o ${LDFLAGS} newedgeg : gtools.h newedgeg.c nausparse.o \ gtools.o gtnauty.o nauty.o nautil.o naugraph.o ${CC} -o newedgeg ${CFLAGS} newedgeg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} pickg : gtools.h testg.c splay.c nausparse.o \ gtools.o gtnauty.o nauty.o nautil.o naugraph.o gutil1.o gutil2.o ${CC} -o pickg ${SAFECFLAGS} testg.c gtools.o gtnauty.o gutil1.o \ gutil2.o nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} countg : gtools.h testg.c splay.c nausparse.o \ gtools.o gtnauty.o nauty.o nautil.o naugraph.o gutil1.o gutil2.o ${CC} -o countg ${SAFECFLAGS} testg.c gtools.o gtnauty.o gutil1.o \ gutil2.o nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} directg : gtools.h naugroup.h directg.c \ gtools.o nauty.o nautil.o naugraph.o naugroup.o ${CC} -o directg ${CFLAGS} directg.c gtools.o \ nauty.o nautil.o naugraph.o naugroup.o ${LDFLAGS} multig : gtools.h naugroup.h multig.c \ gtools.o nauty.o nautil.o naugraph.o naugroup.o ${CC} -o multig ${CFLAGS} multig.c gtools.o \ nauty.o nautil.o naugraph.o naugroup.o ${LDFLAGS} planarg : gtools.h planarg.c gtools.o planarity.c ${CC} -o planarg ${CFLAGS} \ planarg.c planarity.c gtools.o ${LDFLAGS} showg : showg.c ${CC} -o showg ${CFLAGS} showg.c ${LDFLAGS} readg : echo "*** readg is now called showg ***" make showg gtoolsL1.o : gtools.h gtools.c ${CC} -c ${CFLAGS} ${L1} -o gtoolsL1.o gtools.c gtnautyL1.o : gtools.h gtnauty.c ${CC} -c ${CFLAGS} ${L1} -o gtnautyL1.o gtnauty.c sumlines : sumlines.c ${CC} -o sumlines ${CFLAGS} sumlines.c ${LDFLAGS} -lgmp nautyex1 : nauty.h nauty.o nautil.o naugraph.o nautyex1.c ${CC} -o nautyex1 ${CFLAGS} nautyex1.c nauty.o nautil.o \ naugraph.o ${LDFLAGS} nautyex2 : nauty.h nauty.o nautil.o naugraph.o nautyex2.c ${CC} -o nautyex2 ${CFLAGS} \ nautyex2.c nauty.o nautil.o naugraph.o ${LDFLAGS} naugroup.o : nauty.h naugroup.h naugroup.c ${CC} -c ${CFLAGS} naugroup.c nautyex3 : nauty.h nauty.o nautil.o naugraph.o naugroup.o nautyex3.c ${CC} -o nautyex3 ${CFLAGS} \ nautyex3.c nauty.o nautil.o naugraph.o naugroup.o ${LDFLAGS} nautyex4 : nauty.h nausparse.h nauty.o nautil.o \ nausparse.o naugroup.o nautyex4.c ${CC} -o nautyex4 ${CFLAGS} \ nautyex4.c nauty.o nautil.o nausparse.o naugroup.o ${LDFLAGS} nautyex5 : nauty.h nausparse.h nauty.o nautil.o \ nausparse.o naugroup.o nautyex5.c ${CC} -o nautyex5 ${CFLAGS} \ nautyex5.c nauty.o nautil.o nausparse.o naugroup.o ${LDFLAGS} dreadtest: dreadtest.c naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${CC} -o dreadtest ${SAFECFLAGS} dreadtest.c \ naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${LDFLAGS} ./dreadtest : specify an upper bound for the maximum degree. The value of the upper bound must be adjacent to the "d". Example: -d6 -v : display counts by number of edges -l : canonically label output graphs -u : do not output any graphs, just generate and count them -g : use graph6 output (default) -s : use sparse6 output -n : use nauty format instead of graph6 format for output -y : use the obsolete y-format instead of graph6 format -h : for graph6 or sparse6 format, write a header too -q : suppress auxiliary output (except from -v) -x : specify a parameter that determines how evenly the res/mod facility splits the graphs into subsets. High values mean more even splitting at slight cost to the total time. The default is 20*mod, and the the legal minimum is 3*mod. More information is given under "res/mod" above. -X : move the initial splitting level higher by , in order to force more even splitting at the cost of speed. Default is -X0. More information is given under "res/mod" above. Output formats. The output format is determined by the mutually exclusive switches -u, -n, -y, -g and -s. The default is -g. -u suppresses output of graphs completely. -s and -g specify sparse6 and graph6 format, defined elsewhere. In this case a header is also written if -h is present. If -y is present, graphs will be written in y-format. y-format is obsolete and only provided for backwards compatibility. Each graph occupies one line with a terminating newline. Except for the newline, each byte has the format 01xxxxxx, where each "x" represents one bit of data. First byte: xxxxxx is the number of vertices n Other ceiling(n(n-1)/12) bytes: These contain the upper triangle of the adjacency matrix in column major order. That is, the entries appear in the order (0,1),(0,2),(1,2),(0,3),(1,3),(2,3),(0,4),... . The bits are used in left to right order within each byte. Any unused bits on the end are set to zero. If -n is present, any output graphs are written in nauty format. For a graph of n vertices, the output consists of one int giving the number of vertices, and n setwords containing the adjacency matrix. Note that this is system dependent (i.e. don't use it). It will not work properly if the output is to stdout and your system distinguishes binary and text files. OUTPROC feature. By defining the C preprocessor variable OUTPROC at compile time (for Unix the syntax is -DOUTPROC=procname on the cc command), geng can be made to call a procedure of your manufacture with each output graph instead of writing anything. Your procedure needs to have type void and the argument list (FILE *f, graph *g, int n). f is a stream open for writing, g is the graph in nauty format, and n is the number of vertices. Your procedure can be in a separate file so long as it is linked with geng. The global variables nooutput, nautyformat, yformat and canonise (all type boolean) can be used to test for the presence of the flags -u, -n, -y and -l, respectively. If -l is present, the group size and similar details can be found in the global variable nauty_stats. PRUNE feature. By defining the C preprocessor variable PRUNE at compile time, geng can be made to call int PRUNE(graph *g,int n,int maxn) for each intermediate (and final) graph, and reject it if the value returned is nonzero. The arguments are: g = the graph in nauty format (m=1) n = the number of vertices in g maxn = the number of vertices for output (the value you gave on the command line to geng) geng constructs the graph starting with vertex 0, then adding vertices 1,2,3,... in that order. Each graph in the sequence is an induced subgraph of all later graphs in the sequence. A call is made for all orders from 1 to maxn. In testing for a uniform property (such as a forbidden subgraph or forbidden induced subgraph) it might save time to notice that a call to PRUNE for n implies that the call for n-1 already passed. For very fast tests, it might be worthwhile using PREPRUNE as well. It has the same meaning but is applied earlier and more often. SUMMARY If the C preprocessor variable SUMMARY is defined at compile time, the procedure SUMMARY(bigint nout, double cpu) is called just before the program exits. The purpose is to allow reporting of statistics collected by PRUNE or OUTPROC. The values nout and cpu are the output count and cpu time reported on the >Z line. Output should be written to stderr. INSTRUMENT feature. If the C preprocessor variable INSTRUMENT is defined at compile time, extra code is inserted to collect statistics during execution, and more information is written to stderr at termination. CALLING FROM A PROGRAM It is possible to call geng from another program instead of using it as a stand-alone program. The main requirement is to change the name of the main program to be other than "main". This is done by defining the preprocessor variable GENG_MAIN. You might also like to define OUTPROC to be the name of a procedure to receive the graphs. To call the program you need to define an argument list argv[] consistent with the usual one; don't forget that argv[0] is the command name and not the first argument. The value of argc is the number of strings in argv[]; that is, one more than the number of arguments. See the sample program callgeng.c. ************************************************************************** Sample performance statistics. Here we give some graph counts and execution times on a Linux Pentium III running at 550 MHz. Times are with the -u option (generate but don't write); add 3-5 microseconds per graph for output to a file. Add another 0.2-0.3 microseconds per graph if you specify connectivity (-c), or 0.6-0.7 microseconds per graph if you specific biconnectivity (-C). General Graphs C3-free Graphs (-t) 1 1 1 1 2 2 2 2 3 4 3 3 4 11 4 7 5 34 5 14 6 156 6 38 7 1044 7 107 8 12346 0.11 sec 8 410 9 274668 1.77 sec 9 1897 10 12005168 1.22 min 10 12172 0.21 sec 11 1018997864 1.72 hr 11 105071 1.49 sec 12 165091172592 285 hr 12 1262180 15.9 sec 13 50502031367952 ~10 years 13 20797002 4.08 min These can be done in about half 14 467871369 1.50 hr the time by setting the edge limit 15 14232552452 45.6 hr half way then adding complements. 16 581460254001 79 days C4-free Graphs (-f) (C3,C4)-free Graphs (-tf) 1 1 1 1 2 2 2 2 3 4 3 3 4 8 4 6 5 18 5 11 6 44 6 23 7 117 7 48 8 351 8 114 9 1230 9 293 10 5069 0.11 sec 10 869 11 25181 0.48 sec 11 2963 0.10 sec 12 152045 2.67 sec 12 12066 0.36 sec 13 1116403 18.0 sec 13 58933 1.50 sec 14 9899865 2.50 min 14 347498 7.76 sec 15 104980369 25.7 min 15 2455693 50.9 sec 16 1318017549 5.33 hr 16 20592932 6.79 min 17 19427531763 82.6 hr 17 202724920 1.11 hr 18 333964672216 62 days 18 2322206466 12.7 hr 19 30743624324 168 hr 20 468026657815 110 days Old value was wrong: 18 2142368552 (The program was ok, but somehow we tabulated the answer incorrectly.) Bipartite Graphs (-b) C4-free Bipartite Graphs (-bf) 1 1 1 1 2 2 2 2 3 3 3 3 4 7 4 6 5 13 5 10 6 35 6 21 7 88 7 39 8 303 8 86 9 1119 9 182 10 5479 0.11 sec 10 440 11 32303 0.59 sec 11 1074 12 251135 3.99 sec 12 2941 0.15 sec 13 2527712 35.1 sec 13 8424 0.43 sec 14 33985853 7.22 min 14 26720 1.37 sec 15 611846940 2.05 hr 15 90883 4.30 sec 16 14864650924 48.9 hr 16 340253 14.9 sec 17 488222721992 70 days 17 1384567 57.1 sec 18 6186907 4.01 min 19 30219769 18.4 min 20 161763233 1.57 hr 21 946742190 8.85 hr 22 6054606722 56.2 hr 23 42229136988 16.6 days 24 320741332093 121 days If you know any more of these counts, please tell me. ************************************************************************** Hints: To make all the graphs of order n, without restriction on type, it is fastest to make them up to binomial(n,2)/2 edges and append the complement of those with strictly less than binomial(n,2)/2 edges. If it is necessary to split the computation into pieces, it is more efficient to use the res/mod feature than to split by numbers of edges. The memory requirements are exponential in n if no maxdeg is given. For maxdeg=D, the requirements are still exponential (but smaller) for general graphs, but O(n^D) for other graphs. Use -m to reduce the memory requirements to O(n^D) for general graphs too, at the cost of a small increase in cpu time. ************************************************************************** Author: B. D. McKay, Sep 1991 and Jan 1997. Copyright B. McKay (1991-1997). All rights reserved. This software is subject to the conditions and waivers detailed in the file nauty.h. Changes: Nov 18, 1991 : added -d switch fixed operation for n=16 Nov 26, 1991 : added OUTPROC feature Nov 29, 1991 : -c implies mine >= n-1 Jan 8, 1992 : make writeny() not static Jan 10, 1992 : added -n switch Feb 9, 1992 : fixed case of n=1 Feb 16, 1992 : changed mine,maxe,maxdeg testing Feb 19, 1992 : added -b, -t and -u options documented OUTPROC and added external declaration for it. Feb 20, 1992 : added -v option Feb 22, 1992 : added INSTRUMENT compile-time option Feb 23, 1992 : added xbnds() for more effective pruning Feb 24, 1992 : added -l option Feb 25, 1992 : changed writenauty() to use fwrite() Mar 11, 1992 : completely revised many parts, incl new refinement procedure for fast rejection, distance invariant for regular graphs May 19, 1992 : modified userautomproc slightly. xorb[] is no longer idempotent but it doesn't matter. Speed-up of 2-5% achieved. June 5, 1993 : removed ";" after "CPUDEFS" to avoid illegal empty declaration. Nov 24, 1994 : tested for 0 <= res < mod Apr 13, 1996 : Major overhaul. Renamed "geng". Changed argument syntax. Removed 16-vertex limit. Added -s, -m, -x. Allowed combinations. Replaced code for non-general graphs. Very many small changes. Jul 12, 1996 : Changed semantics of -x and res/mod. Changed >A line and added fflush()/ All switches can be concatenated or not. Aug 16, 1996 : Added -X switch and PRUNE() feature. Fixed case of argument 0-0. Sep 22, 1996 : Improved 1-2% by tweaking refinex(). Jan 21, 1997 : Renamed to geng. Changed -s to -f, and added -sghq. Sep 7, 1997 : Fixed WORDSIZE=16 problems. Sep 22, 1997 : Use "wb" open for nautyformat. Jan 26, 1998 : Added SUMMARY feature. Mar 4, 1998 : Added -C. Mar 12, 1998 : Moved stats to nauty_stats. Jan 1, 2000 : Changed -d to -D and added -d. Feb 24, 2000 : Raised limit to 32 vertices. Mar 3, 2000 : Made some counts into unsigned long. (Includes first arg to SUMMARY.) Mar 12, 2000 : Used bigint for counts that may exceed 2^32. Now all counts from very long runs are ok. Oct 12, 2000 : Changed maxef[32] to 92 after confirmation from Yang Yuansheng. The old value of 93 was valid but 92 is slightly more efficient. Nov 16, 2000 : Used fuction prototypes. Jul 31, 2001 : Added PREPRUNE May 7, 2004 : Complete all function prototypes Nov 24, 2004 : Force -m for very large sizes Add -bf automatically if generating trees Apr 1, 2007 : Write >A in one fputs() to try to reduce mixing of outputs in multi-process pipes. Sep 19, 2007 : Force -m for n > 28 regardless of word size. Nov 29, 2008 : Slightly improved connectivity testing. **************************************************************************/ #define NAUTY_PGM 1 /* 1 = geng, 2 = genbg, 3 = gentourng */ #ifndef MAXN #define MAXN 32 /* not more than max(32,WORDSIZE) */ #endif #if MAXN > 32 #error "Can't have MAXN greater than 32" #endif #define ONE_WORD_SETS #include "gtools.h" /* which includes nauty.h and stdio.h */ #if MAXN < 32 typedef int xword; /* Must be as large as MAXN bits, and must be unsigned if equal to MAXN bits */ #else typedef unsigned int xword; #endif static void (*outproc)(FILE*,graph*,int); static FILE *outfile; /* file for output graphs */ static int connec; /* 1 for -c, 2 for -C, 0 for neither */ static boolean bipartite; /* presence of -b */ static boolean trianglefree; /* presence of -t */ static boolean squarefree; /* presence of -f */ static boolean savemem; /* presence of -m */ static boolean verbose; /* presence of -v */ boolean nautyformat; /* presence of -n */ boolean yformat; /* presence of -y */ boolean graph6; /* presence of -g */ boolean sparse6; /* presence of -s */ boolean nooutput; /* presence of -u */ boolean canonise; /* presence of -l */ boolean quiet; /* presence of -q */ boolean header; /* presence of -h */ statsblk nauty_stats; static int mindeg,maxdeg,maxn,mine,maxe,mod,res; #define PRUNEMULT 20 /* bigger -> more even split at greater cost */ static int min_splitlevel,odometer,splitlevel,multiplicity; static graph gcan[MAXN]; #if MAXN <= 16 static xword xbit[] = {0x0001,0x0002,0x0004,0x0008, 0x0010,0x0020,0x0040,0x0080, 0x0100,0x0200,0x0400,0x0800, 0x1000,0x2000,0x4000,0x8000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : 15-leftbit[((x)>>8)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] + bytecount[(x)&0xFF]) #elif MAXN <= 24 static xword xbit[] = {0x000001,0x000002,0x000004,0x000008, 0x000010,0x000020,0x000040,0x000080, 0x000100,0x000200,0x000400,0x000800, 0x001000,0x002000,0x004000,0x008000, 0x010000,0x020000,0x040000,0x080000, 0x100000,0x200000,0x400000,0x800000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : \ (x)&0xFF00 ? 15-leftbit[((x)>>8)&0xFF] : 23-leftbit[((x)>>16)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] \ + bytecount[((x)>>16)&0xFF] + bytecount[(x)&0xFF]) #else static xword xbit[] = {0x00000001,0x00000002,0x00000004,0x00000008, 0x00000010,0x00000020,0x00000040,0x00000080, 0x00000100,0x00000200,0x00000400,0x00000800, 0x00001000,0x00002000,0x00004000,0x00008000, 0x00010000,0x00020000,0x00040000,0x00080000, 0x00100000,0x00200000,0x00400000,0x00800000, 0x01000000,0x02000000,0x04000000,0x08000000, 0x10000000,0x20000000,0x40000000,0x80000000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : \ (x)&0xFF00 ? 15-leftbit[((x)>>8)&0xFF] : \ (x)&0xFF0000 ? 23-leftbit[((x)>>16)&0xFF] : \ 31-leftbit[((x)>>24)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] \ + bytecount[((x)>>16)&0xFF] + \ + bytecount[((x)>>24)&0xFF] + bytecount[(x)&0xFF]) #endif typedef struct { int ne,dmax; /* values used for xlb,xub calculation */ int xlb,xub; /* saved bounds on extension degree */ xword lo,hi; /* work purposes for orbit calculation */ xword xstart[MAXN+1]; /* index into xset[] for each cardinality */ xword *xset; /* array of all x-sets in card order */ xword *xcard; /* cardinalities of all x-sets */ xword *xinv; /* map from x-set to index in xset */ xword *xorb; /* min orbit representative */ xword *xx; /* (-b, -t, -s, -m) candidate x-sets */ /* note: can be the same as xcard */ xword xlim; /* number of x-sets in xx[] */ } leveldata; /* The program is so fast that the count of output graphs can quickly overflow a 32-bit integer. Therefore, we use two long values for each count, with a ratio of 10^9 between them. The macro ADDBIG adds a small number to one of these big numbers. BIGTODOUBLE converts a big number to a double (approximately). SUMBIGS adds a second big number into a first big number. SUBBIGS subtracts one big number from a second. PRINTBIG prints a big number in decimal. ZEROBIG sets the value of a big number to 0. ISZEROBIG tests if the value is 0. SETBIG sets a big number to a value at most 10^9-1. ISEQBIG tests if two big numbers are equal. ISASBIG tests if a big number is at least as a value at most 10^9-1. */ typedef struct { long hi,lo; } bigint; #define ZEROBIG(big) big.hi = big.lo = 0L #define ISZEROBIG(big) (big.lo == 0 && big.hi == 0) #define SETBIG(big,value) {big.hi = 0L; big.lo = (value);} #define ADDBIG(big,extra) if ((big.lo += (extra)) >= 1000000000L) \ { ++big.hi; big.lo -= 1000000000L;} #define PRINTBIG(file,big) if (big.hi == 0) \ fprintf(file,"%ld",big.lo); else fprintf(file,"%ld%09ld",big.hi,big.lo) #define BIGTODOUBLE(big) (big.hi * 1000000000.0 + big.lo) #define SUMBIGS(big1,big2) {if ((big1.lo += big2.lo) >= 1000000000L) \ {big1.lo -= 1000000000L; big1.hi += big2.hi + 1L;} \ else big1.hi += big2.hi;} #define SUBBIGS(big1,big2) {if ((big1.lo -= big2.lo) < 0L) \ {big1.lo += 1000000000L; big1.hi -= big2.hi + 1L;} \ else big1.hi -= big2.hi;} /* Note: SUBBIGS must not allow the value to go negative. SUMBIGS and SUBBIGS both permit big1 and big2 to be the same bigint. */ #define ISEQBIG(big1,big2) (big1.lo == big2.lo && big1.hi == big2.hi) #define ISASBIG(big,value) (big.hi > 0 || big.lo >= (value)) static leveldata data[MAXN]; /* data[n] is data for n -> n+1 */ static bigint ecount[1+MAXN*(MAXN-1)/2]; /* counts by number of edges */ static bigint nodes[MAXN]; /* nodes at each level */ #ifdef INSTRUMENT static unsigned long rigidnodes[MAXN],fertilenodes[MAXN]; static unsigned long a1calls,a1nauty,a1succs; static unsigned long a2calls,a2nauty,a2uniq,a2succs; #endif /* The numbers below are actual maximum edge counts. The apparently anomolous value of 92 for maxef[32] has been confirmed independently by Yang Yuansheng (as well as all the smaller maxef[] values). geng works correctly with any upper bounds. To extend an upper bound upwards: (n-1, E) -> (n, E + floor(2*E/(n-2))). */ static int maxeb[] = /* max edges for -b */ {0,0,1,2,4, 6,9,12,16,20, 25,30,36,42,49, 56,64,72,81,90, 100,110,121,132,144, 156,169,182,196,210, 225,240,256}; static int maxet[] = /* max edges for -t */ {0,0,1,2,4, 6,9,12,16,20, 25,30,36,42,49, 56,64,72,81,90, 100,110,121,132,144, 156,169,182,196,210, 225,240,256}; static int maxef[] = /* max edges for -f */ {0,0,1,3,4, 6,7,9,11,13, 16,18,21,24,27, 30,33,36,39,42, 46,50,52,56,59, 63,67,71,76,80, 85,90,92}; static int maxeft[] = /* max edges for -ft */ {0,0,1,2,3, 5,6,8,10,12, 15,16,18,21,23, 26,28,31,34,38, 41,44,47,50,54, 57,61,65,68,72, 76,80,85}; static int maxebf[] = /* max edges for -bf */ {0,0,1,2,3, 4,6,7,9,10, 12,14,16,18,21, 22,24,26,29,31, 34,36,39,42,45, 48,52,53,56,58, 61,64,67}; #ifdef PLUGIN #include PLUGIN #endif #ifdef OUTPROC extern void OUTPROC(FILE*,graph*,int); #endif #ifdef PRUNE extern int PRUNE(graph*,int,int); #endif #ifdef PREPRUNE extern int PREPRUNE(graph*,int,int); #endif #ifdef SUMMARY extern void SUMMARY(bigint,double); #endif /************************************************************************/ void writeny(FILE *f, graph *g, int n) /* write graph g (n vertices) to file f in y format */ { static char ybit[] = {32,16,8,4,2,1}; char s[(MAXN*(MAXN-1)/2 + 5)/6 + 4]; int i,j,k; char y,*sp; sp = s; *(sp++) = 0x40 | n; y = 0x40; k = -1; for (j = 1; j < n; ++j) for (i = 0; i < j; ++i) { if (++k == 6) { *(sp++) = y; y = 0x40; k = 0; } if (g[i] & bit[j]) y |= ybit[k]; } if (n >= 2) *(sp++) = y; *(sp++) = '\n'; *sp = '\0'; if (fputs(s,f) == EOF || ferror(f)) { fprintf(stderr,">E writeny : error on writing file\n"); exit(2); } } /************************************************************************/ void writeg6x(FILE *f, graph *g, int n) /* write graph g (n vertices) to file f in graph6 format */ { writeg6(f,g,1,n); } /************************************************************************/ void writes6x(FILE *f, graph *g, int n) /* write graph g (n vertices) to file f in sparse6 format */ { writes6(f,g,1,n); } /***********************************************************************/ static void nullwrite(FILE *f, graph *g, int n) /* don't write graph g (n vertices) to file f */ { } /***********************************************************************/ void writenauty(FILE *f, graph *g, int n) /* write graph g (n vertices) to file f in nauty format */ { int nn; nn = n; if (fwrite((char *)&nn,sizeof(int),(size_t)1,f) != 1 || fwrite((char*)g,sizeof(setword),(size_t)n,f) != n) { fprintf(stderr,">E writenauty : error on writing file\n"); exit(2); } } /*********************************************************************/ static boolean isconnected(graph *g, int n) /* test if g is connected */ { setword seen,expanded,toexpand,allbits; int i; allbits = ALLMASK(n); expanded = bit[n-1]; seen = expanded | g[n-1]; while (seen != allbits && (toexpand = (seen & ~expanded))) /* not == */ { i = FIRSTBIT(toexpand); expanded |= bit[i]; seen |= g[i]; } return seen == allbits; } /**********************************************************************/ static boolean isbiconnected(graph *g, int n) /* test if g is biconnected */ { int sp,v,w; setword sw; setword visited; int numvis,num[MAXN],lp[MAXN],stack[MAXN]; if (n <= 2) return FALSE; visited = bit[0]; stack[0] = 0; num[0] = 0; lp[0] = 0; numvis = 1; sp = 0; v = 0; for (;;) { if ((sw = g[v] & ~visited)) /* not "==" */ { w = v; v = FIRSTBIT(sw); /* visit next child */ stack[++sp] = v; visited |= bit[v]; lp[v] = num[v] = numvis++; sw = g[v] & visited & ~bit[w]; while (sw) { w = FIRSTBIT(sw); sw &= ~bit[w]; if (num[w] < lp[v]) lp[v] = num[w]; } } else { w = v; /* back up to parent */ if (sp <= 1) return numvis == n; v = stack[--sp]; if (lp[w] >= num[v]) return FALSE; if (lp[w] < lp[v]) lp[v] = lp[w]; } } } /**********************************************************************/ static void gcomplement(graph *g, graph *gc, int n) /* Take the complement of g and put it in gc */ { int i; setword all; all = ~(setword)BITMASK(n-1); for (i = 0; i < n; ++i) gc[i] = g[i] ^ all ^ bit[i]; } /**********************************************************************/ static boolean distinvar(graph *g, int *invar, int n) /* make distance invariant return FALSE if n-1 not maximal else return TRUE */ { int w; setword workset,frontier; setword sofar; int inv,d,v; for (v = n-1; v >= 0; --v) { inv = 0; sofar = frontier = bit[v]; for (d = 1; frontier != 0; ++d) { workset = 0; inv += POPCOUNT(frontier) ^ (0x57 + d); while (frontier) { w = FIRSTBIT(frontier); frontier ^= bit[w]; workset |= g[w]; } frontier = workset & ~sofar; sofar |= frontier; } invar[v] = inv; if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; } /**************************************************************************/ static void makexgraph(graph *g, xword *h, int n) /* make x-format graph from nauty format graph */ { setword gi; int i,j; xword hi; for (i = 0; i < n; ++i) { hi = 0; gi = g[i]; while (gi) { j = FIRSTBIT(gi); gi ^= bit[j]; hi |= xbit[j]; } h[i] = hi; } } /**************************************************************************/ static void make0graph(graph *g, xword *h, int n) /* make x-format graph without edges */ { int i; for (i = 0; i < n; ++i) h[i] = 0; } /**************************************************************************/ static void makebgraph(graph *g, xword *h, int n) /* make x-format graph of different colour graph */ { setword seen1,seen2,expanded,w; setword restv; xword xseen1,xseen2; int i; restv = 0; for (i = 0; i < n; ++i) restv |= bit[i]; seen1 = seen2 = 0; expanded = 0; while (TRUE) { if ((w = ((seen1 | seen2) & ~expanded)) == 0) { xseen1 = 0; w = seen1; while (w) { i = FIRSTBIT(w); w ^= bit[i]; xseen1 |= xbit[i]; } xseen2 = 0; w = seen2; while (w) { i = FIRSTBIT(w); w ^= bit[i]; xseen2 |= xbit[i]; } w = seen1; while (w) { i = FIRSTBIT(w); w ^= bit[i]; h[i] = xseen2; } w = seen2; while (w) { i = FIRSTBIT(w); w ^= bit[i]; h[i] = xseen1; } restv &= ~(seen1 | seen2); if (restv == 0) return; i = FIRSTBIT(restv); seen1 = bit[i]; seen2 = 0; } else i = FIRSTBIT(w); expanded |= bit[i]; if (bit[i] & seen1) seen2 |= g[i]; else seen1 |= g[i]; } } /**************************************************************************/ static void makeb6graph(graph *g, xword *h, int n) /* make x-format bipartite girth 6 graph */ { setword w,x; xword hi; int i,j; makebgraph(g,h,n); for (i = 0; i < n; ++i) { w = g[i]; x = 0; while (w) { j = FIRSTBIT(w); w ^= bit[j]; x |= g[j]; } x &= ~bit[i]; hi = h[i]; while (x) { j = FIRSTBIT(x); x ^= bit[j]; hi |= xbit[j]; } h[i] = hi; } } /**************************************************************************/ static void makesgraph(graph *g, xword *h, int n) /* make x-format square graph */ { setword w,x; xword hi; int i,j; for (i = 0; i < n; ++i) { w = g[i]; x = 0; while (w) { j = FIRSTBIT(w); w ^= bit[j]; x |= g[j]; } x &= ~bit[i]; hi = 0; while (x) { j = FIRSTBIT(x); x ^= bit[j]; hi |= xbit[j]; } h[i] = hi; } } /**************************************************************************/ static void makeg5graph(graph *g, xword *h, int n) /* make x-format girth-5 graph */ { setword w,x; xword hi; int i,j; for (i = 0; i < n; ++i) { w = g[i]; x = g[i]; while (w) { j = FIRSTBIT(w); w ^= bit[j]; x |= g[j]; } x &= ~bit[i]; hi = 0; while (x) { j = FIRSTBIT(x); x ^= bit[j]; hi |= xbit[j]; } h[i] = hi; } } /**************************************************************************/ static void makeleveldata(boolean restricted) /* make the level data for each level */ { long h; int n,nn; long ncj; leveldata *d; xword *xcard,*xinv; xword *xset,xw,tttn,nxsets; xword cw; xword i,j; for (n = 1; n < maxn; ++n) { nn = maxdeg <= n ? maxdeg : n; ncj = nxsets = 1; for (j = 1; j <= nn; ++j) { ncj = (ncj * (n - j + 1)) / j; nxsets += ncj; } tttn = 1L << n; d = &data[n]; d->ne = d->dmax = d->xlb = d->xub = -1; if (restricted) { d->xorb = (xword*) calloc(nxsets,sizeof(xword)); d->xx = (xword*) calloc(nxsets,sizeof(xword)); if (d->xorb == NULL || d->xx == NULL) { fprintf(stderr, ">E geng: calloc failed in makeleveldata()\n"); exit(2); } continue; /* <--- NOTE THIS! */ } d->xset = xset = (xword*) calloc(nxsets,sizeof(xword)); d->xcard = xcard = (xword*) calloc(nxsets,sizeof(xword)); d->xinv = xinv = (xword*) calloc(tttn,sizeof(xword)); d->xorb = (xword*) calloc(nxsets,sizeof(xword)); d->xx = d->xcard; if (xset==NULL || xcard==NULL || xinv==NULL || d->xorb==NULL) { fprintf(stderr,">E geng: calloc failed in makeleveldata()\n"); exit(2); } j = 0; for (i = 0;; ++i) { if ((h = XPOPCOUNT(i)) <= maxdeg) { xset[j] = i; xcard[j] = h; ++j; } if (i == (xword)((1L<E geng: j=%d mxsets=%u\n", j,(unsigned)nxsets); exit(2); } h = 1; do h = 3 * h + 1; while (h < nxsets); do { for (i = h; i < nxsets; ++i) { xw = xset[i]; cw = xcard[i]; for (j = i; xcard[j-h] > cw || xcard[j-h] == cw && xset[j-h] > xw; ) { xset[j] = xset[j-h]; xcard[j] = xcard[j-h]; if ((j -= h) < h) break; } xset[j] = xw; xcard[j] = cw; } h /= 3; } while (h > 0); for (i = 0; i < nxsets; ++i) xinv[xset[i]] = i; d->xstart[0] = 0; for (i = 1; i < nxsets; ++i) if (xcard[i] > xcard[i-1]) d->xstart[xcard[i]] = i; d->xstart[xcard[nxsets-1]+1] = nxsets; } } /**************************************************************************/ static void userautomproc(int count, permutation *p, int *orbits, int numorbits, int stabvertex, int n) /* form orbits on powerset of VG called by nauty; operates on data[n] */ { xword i,j1,j2,moved,pi,pxi; xword lo,hi; xword *xorb,*xinv,*xset,w; xorb = data[n].xorb; xset = data[n].xset; xinv = data[n].xinv; lo = data[n].lo; hi = data[n].hi; if (count == 1) /* first automorphism */ for (i = lo; i < hi; ++i) xorb[i] = i; moved = 0; for (i = 0; i < n; ++i) if (p[i] != i) moved |= xbit[i]; for (i = lo; i < hi; ++i) { if ((w = xset[i] & moved) == 0) continue; pxi = xset[i] & ~moved; while (w) { j1 = XNEXTBIT(w); w ^= xbit[j1]; pxi |= xbit[p[j1]]; } pi = xinv[pxi]; j1 = xorb[i]; while (xorb[j1] != j1) j1 = xorb[j1]; j2 = xorb[pi]; while (xorb[j2] != j2) j2 = xorb[j2]; if (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1; else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2; } } /**************************************************************************/ static void userautomprocb(int count, permutation *p, int *orbits, int numorbits, int stabvertex, int n) /* form orbits on powerset of VG called by nauty; operates on data[n] */ { xword j1,j2,moved,pi,pxi,lo,hi,x; xword i,*xorb,*xx,w,xlim,xlb; xorb = data[n].xorb; xx = data[n].xx; xlim = data[n].xlim; if (count == 1) /* first automorphism */ { j1 = 0; xlb = data[n].xlb; for (i = 0; i < xlim; ++i) { x = xx[i]; if (XPOPCOUNT(x) >= xlb) { xx[j1] = x; xorb[j1] = j1; ++j1; } } data[n].xlim = xlim = j1; } moved = 0; for (i = 0; i < n; ++i) if (p[i] != i) moved |= xbit[i]; for (i = 0; i < xlim; ++i) { if ((w = xx[i] & moved) == 0) continue; pxi = xx[i] & ~moved; while (w) { j1 = XNEXTBIT(w); w ^= xbit[j1]; pxi |= xbit[p[j1]]; } /* pi = position of pxi */ lo = 0; hi = xlim - 1; for (;;) { pi = (lo + hi) >> 1; if (xx[pi] == pxi) break; else if (xx[pi] < pxi) lo = pi + 1; else hi = pi - 1; } j1 = xorb[i]; while (xorb[j1] != j1) j1 = xorb[j1]; j2 = xorb[pi]; while (xorb[j2] != j2) j2 = xorb[j2]; if (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1; else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2; } } /***************************************************************************** * * * refinex(g,lab,ptn,level,numcells,count,active,goodret,code,m,n) is a * * custom version of refine() which can exit quickly if required. * * * * Only use at level==0. * * goodret : whether to do an early return for code 1 * * 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, permutation *count, set *active, boolean goodret, int *code, int m, int n) { int i,c1,c2,labc1; setword x,lact; int split1,split2,cell1,cell2; int cnt,bmin,bmax; set *gptr; setword workset; int workperm[MAXN]; int bucket[MAXN+2]; if (n == 1) { *code = 1; return; } *code = 0; lact = *active; split1 = -1; while (*numcells < n && lact) { TAKEBIT(split1,lact); for (split2 = split1; ptn[split2] > 0; ++split2) {} if (split1 == split2) /* trivial splitting cell */ { gptr = GRAPHROW(g,lab[split1],1); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; c1 = cell1; c2 = cell2; while (c1 <= c2) { labc1 = lab[c1]; if (ISELEMENT1(gptr,labc1)) ++c1; else { lab[c1] = lab[c2]; lab[c2] = labc1; --c2; } } if (c2 >= cell1 && c1 <= cell2) { ptn[c2] = 0; ++*numcells; lact |= bit[c1]; } } } else /* nontrivial splitting cell */ { workset = 0; for (i = split1; i <= split2; ++i) workset |= bit[lab[i]]; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; i = cell1; if ((x = workset & g[lab[i]]) != 0) cnt = POPCOUNT(x); else cnt = 0; count[i] = bmin = bmax = cnt; bucket[cnt] = 1; while (++i <= cell2) { if ((x = workset & g[lab[i]]) != 0) cnt = POPCOUNT(x); else cnt = 0; while (bmin > cnt) bucket[--bmin] = 0; while (bmax < cnt) bucket[++bmax] = 0; ++bucket[cnt]; count[i] = cnt; } if (bmin == bmax) continue; c1 = cell1; for (i = bmin; i <= bmax; ++i) if (bucket[i]) { c2 = c1 + bucket[i]; bucket[i] = c1; if (c1 != cell1) { lact |= bit[c1]; ++*numcells; } if (c2 <= cell2) ptn[c2-1] = 0; c1 = c2; } for (i = cell1; i <= cell2; ++i) workperm[bucket[count[i]]++] = lab[i]; for (i = cell1; i <= cell2; ++i) lab[i] = workperm[i]; } } if (ptn[n-2] == 0) { if (lab[n-1] == n-1) { *code = 1; if (goodret) return; } else { *code = -1; return; } } else { i = n - 1; while (TRUE) { if (lab[i] == n-1) break; --i; if (ptn[i] == 0) { *code = -1; return; } } } } } /**************************************************************************/ static void makecanon(graph *g, graph *gcan, int n) /* gcan := canonise(g) */ { int lab[MAXN],ptn[MAXN],orbits[MAXN]; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; options.getcanon = TRUE; nauty(g,lab,ptn,NULL,orbits,&options,&nauty_stats, workspace,50,1,n,gcan); } /**************************************************************************/ static 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; int lab[MAXN],ptn[MAXN],orbits[MAXN]; permutation count[MAXN]; graph h[MAXN]; xword xw; int nx,numcells,code; int i0,i1,degn; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a1calls; #endif nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; gx[n] = 0; deg[n] = degn = XPOPCOUNT(x); xw = x; while (xw) { i = XNEXTBIT(xw); xw ^= xbit[i]; gx[i] |= bit[n]; gx[n] |= bit[i]; ++deg[i]; } #ifdef PREPRUNE if (PREPRUNE(gx,n+1,maxn)) return FALSE; #endif i0 = 0; i1 = n; for (i = 0; i < nx; ++i) { if (deg[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == 0) { numcells = 1; active[0] = bit[0]; } else { numcells = 2; active[0] = bit[0] | bit[i1+1]; ptn[i1] = 0; } refinex(gx,lab,ptn,0,&numcells,count,active,FALSE,&code,1,nx); if (code < 0) return FALSE; if (numcells == nx) { *rigid = TRUE; #ifdef INSTRUMENT ++a1succs; #endif return TRUE; } options.getcanon = TRUE; options.defaultptn = FALSE; options.userautomproc = userautomproc; active[0] = 0; #ifdef INSTRUMENT ++a1nauty; #endif 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 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)) /* decide if n in theta(g+x) -- version for n+1 < maxn */ { int i,v; xword z,hv,bitv,ixx; int lab[MAXN],ptn[MAXN],orbits[MAXN]; permutation count[MAXN]; graph gc[MAXN]; xword h[MAXN],xw,jxx,kxx,*xx; int nx,numcells,code; int i0,i1,degn,xubx; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a1calls; #endif nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; gx[n] = 0; deg[n] = degn = XPOPCOUNT(x); xw = x; while (xw) { i = XNEXTBIT(xw); xw ^= xbit[i]; gx[i] |= bit[n]; gx[n] |= bit[i]; ++deg[i]; } #ifdef PREPRUNE if (PREPRUNE(gx,n+1,maxn)) return FALSE; #endif i0 = 0; i1 = n; for (i = 0; i < nx; ++i) { if (deg[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == 0) { numcells = 1; active[0] = bit[0]; } else { numcells = 2; active[0] = bit[0] | bit[i1+1]; ptn[i1] = 0; } refinex(gx,lab,ptn,0,&numcells,count,active,FALSE,&code,1,nx); if (code < 0) return FALSE; (*makeh)(gx,h,nx); xx = data[nx].xx; xubx = data[nx].xub; xx[0] = 0; kxx = 1; for (v = 0; v < nx; ++v) { bitv = xbit[v]; hv = h[v]; jxx = kxx; for (ixx = 0; ixx < jxx; ++ixx) if ((hv & xx[ixx]) == 0) { z = xx[ixx] | bitv; if (XPOPCOUNT(z) <= xubx) xx[kxx++] = z; } } data[nx].xlim = kxx; if (numcells == nx) { *rigid = TRUE; #ifdef INSTRUMENT ++a1succs; #endif return TRUE; } options.getcanon = TRUE; options.defaultptn = FALSE; options.userautomproc = userautomprocb; active[0] = 0; #ifdef INSTRUMENT ++a1nauty; #endif 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 return TRUE; } else return FALSE; } /**************************************************************************/ static 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; int lab[MAXN],ptn[MAXN],orbits[MAXN]; int degx[MAXN],invar[MAXN]; setword vmax,gv; int qn,qv; permutation count[MAXN]; xword xw; int nx,numcells,code; int degn,i0,i1,j,j0,j1; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; boolean cheapacc; #ifdef INSTRUMENT ++a2calls; if (nuniq) ++a2uniq; #endif nx = n + 1; for (i = 0; i < n; ++i) { gx[i] = g[i]; degx[i] = deg[i]; } gx[n] = 0; degx[n] = degn = XPOPCOUNT(x); xw = x; while (xw) { i = XNEXTBIT(xw); xw ^= xbit[i]; gx[i] |= bit[n]; gx[n] |= bit[i]; ++degx[i]; } #ifdef PREPRUNE if (PREPRUNE(gx,n+1,maxn)) return FALSE; #endif if (nuniq) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } i0 = 0; i1 = n; for (i = 0; i < nx; ++i) { if (degx[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == 0) { numcells = 1; active[0] = bit[0]; if (!distinvar(gx,invar,nx)) return FALSE; qn = invar[n]; j0 = 0; j1 = n; while (j0 <= j1) { j = lab[j0]; qv = invar[j]; if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > 0) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } else { numcells = 2; ptn[i1] = 0; active[0] = bit[0] | bit[i1+1]; vmax = 0; for (i = i1+1; i < nx; ++i) vmax |= bit[lab[i]]; gv = gx[n] & vmax; qn = POPCOUNT(gv); j0 = i1+1; j1 = n; while (j0 <= j1) { j = lab[j0]; gv = gx[j] & vmax; qv = POPCOUNT(gv); if (qv > qn) return FALSE; else if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > i1+1) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } refinex(gx,lab,ptn,0,&numcells,count,active,TRUE,&code,1,nx); if (code < 0) return FALSE; cheapacc = FALSE; if (code > 0 || numcells >= nx-4) cheapacc = TRUE; else if (numcells == nx-5) { for (j1 = nx-2; j1 >= 0 && ptn[j1] > 0; --j1) {} if (nx - j1 != 5) cheapacc = TRUE; } else { j1 = nx; j0 = 0; for (i1 = 0; i1 < nx; ++i1) { --j1; if (ptn[i1] > 0) { ++j0; while (ptn[++i1] > 0) {} } } if (j1 <= j0 + 1) cheapacc = TRUE; } if (cheapacc) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } options.getcanon = TRUE; options.defaultptn = FALSE; active[0] = 0; #ifdef INSTRUMENT ++a2nauty; #endif nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan); if (orbits[lab[n]] == orbits[n]) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } else return FALSE; } /**************************************************************************/ static void xbnds(int n, int ne, int dmax) /* find bounds on extension degree; store answer in data[*].* */ { int xlb,xub,d,nn,m,xc; xlb = n == 1 ? 0 : (dmax > (2*ne + n - 2)/(n - 1) ? dmax : (2*ne + n - 2)/(n - 1)); xub = n < maxdeg ? n : maxdeg; for (xc = xub; xc >= xlb; --xc) { d = xc; m = ne + d; for (nn = n+1; nn < maxn; ++nn) { if (d < (2*m + nn - 2)/(nn - 1)) d = (2*m + nn - 2)/(nn - 1); m += d; } if (d > maxdeg || m > maxe) xub = xc - 1; else break; } if (ne + xlb < mine) for (xc = xlb; xc <= xub; ++xc) { m = ne + xc; for (nn = n + 1; nn < maxn; ++nn) m += maxdeg < nn ? maxdeg : nn; if (m < mine) xlb = xc + 1; else break; } data[n].ne = ne; data[n].dmax = dmax; data[n].xlb = xlb; data[n].xub = xub; } /**************************************************************************/ static 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; xword xlim,*xorb; int xc,nx,i,j,dmax,dcrit,xlbx,xubx; graph gx[MAXN]; xword *xx,ixx; int degx[MAXN]; boolean rigidx; #ifdef INSTRUMENT boolean haschild; haschild = FALSE; if (rigid) ++rigidnodes[n]; #endif ADDBIG(nodes[n],1); nx = n + 1; dmax = deg[n-1]; dcrit = mindeg - maxn + n; d = dlow = 0; for (i = 0; i < n; ++i) { if (deg[i] == dmax) d |= xbit[i]; if (deg[i] == dcrit) dlow |= xbit[i]; } if (xlb == dmax && XPOPCOUNT(d) + dmax > n) ++xlb; if (nx == maxn && xlb < mindeg) xlb = mindeg; if (xlb > xub) return; #ifdef PRUNE if (PRUNE(g,n,maxn)) return; #endif xorb = data[n].xorb; xx = data[n].xx; xlim = data[n].xlim; if (nx == maxn) { for (ixx = 0; ixx < xlim; ++ixx) { x = xx[ixx]; xc = XPOPCOUNT(x); if (xc < xlb || xc > xub) continue; if ((rigid || xorb[ixx] == ixx) && (xc > dmax || xc == dmax && (x & d) == 0) && (dlow & ~x) == 0) { if (accept2(g,n,x,gx,deg, xc > dmax+1 || xc == dmax+1 && (x & d) == 0) && (!connec || connec==1 && isconnected(gx,nx) || connec>1 && isbiconnected(gx,nx))) { #ifdef PRUNE if (!PRUNE(gx,nx,maxn)) #endif { #ifdef INSTRUMENT haschild = TRUE; #endif ADDBIG(ecount[ne+xc],1); (*outproc)(outfile,canonise ? gcan : gx,nx); } } } } } else { for (ixx = 0; ixx < xlim; ++ixx) { if (nx == splitlevel) { if (odometer-- != 0) continue; odometer = mod - 1; } x = xx[ixx]; xc = XPOPCOUNT(x); if (xc < xlb || xc > xub) continue; if ((rigid || xorb[ixx] == ixx) && (xc > dmax || xc == dmax && (x & d) == 0) && (dlow & ~x) == 0) { for (j = 0; j < n; ++j) degx[j] = deg[j]; if (data[nx].ne != ne+xc || data[nx].dmax != xc) xbnds(nx,ne+xc,xc); xlbx = data[nx].xlb; xubx = data[nx].xub; if (xlbx <= xubx && accept1b(g,n,x,gx,degx,&rigidx,makeh)) { #ifdef INSTRUMENT haschild = TRUE; #endif spaextend(gx,nx,degx,ne+xc,rigidx,xlbx,xubx,makeh); } } } if (n == splitlevel - 1 && n >= min_splitlevel && ISASBIG(nodes[n],multiplicity)) --splitlevel; } #ifdef INSTRUMENT if (haschild) ++fertilenodes[n]; #endif } /**************************************************************************/ static 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; xword *xset,*xcard,*xorb; xword i,imin,imax; int nx,xc,j,dmax,dcrit; int xlbx,xubx; graph gx[MAXN]; int degx[MAXN]; boolean rigidx; #ifdef INSTRUMENT boolean haschild; haschild = FALSE; if (rigid) ++rigidnodes[n]; #endif ADDBIG(nodes[n],1); nx = n + 1; dmax = deg[n-1]; dcrit = mindeg - maxn + n; d = dlow = 0; for (i = 0; i < n; ++i) { if (deg[i] == dmax) d |= xbit[i]; if (deg[i] == dcrit) dlow |= xbit[i]; } if (xlb == dmax && XPOPCOUNT(d) + dmax > n) ++xlb; if (nx == maxn && xlb < mindeg) xlb = mindeg; if (xlb > xub) return; #ifdef PRUNE if (PRUNE(g,n,maxn)) return; #endif imin = data[n].xstart[xlb]; imax = data[n].xstart[xub+1]; xset = data[n].xset; xcard = data[n].xcard; xorb = data[n].xorb; if (nx == maxn) for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if (xc == dmax && (x & d) != 0) continue; if ((dlow & ~x) != 0) continue; if (accept2(g,n,x,gx,deg, xc > dmax+1 || xc == dmax+1 && (x & d) == 0)) if (!connec || connec==1 && isconnected(gx,nx) || connec>1 && isbiconnected(gx,nx)) { #ifdef PRUNE if (!PRUNE(gx,nx,maxn)) #endif { #ifdef INSTRUMENT haschild = TRUE; #endif ADDBIG(ecount[ne+xc],1); (*outproc)(outfile,canonise ? gcan : gx,nx); } } } else for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if (xc == dmax && (x & d) != 0) continue; if ((dlow & ~x) != 0) continue; if (nx == splitlevel) { if (odometer-- != 0) continue; odometer = mod - 1; } for (j = 0; j < n; ++j) degx[j] = deg[j]; if (data[nx].ne != ne+xc || data[nx].dmax != xc) xbnds(nx,ne+xc,xc); xlbx = data[nx].xlb; xubx = data[nx].xub; if (xlbx > xubx) continue; data[nx].lo = data[nx].xstart[xlbx]; data[nx].hi = data[nx].xstart[xubx+1]; if (accept1(g,n,x,gx,degx,&rigidx)) { #ifdef INSTRUMENT haschild = TRUE; #endif genextend(gx,nx,degx,ne+xc,rigidx,xlbx,xubx); } } if (n == splitlevel-1 && n >= min_splitlevel && ISASBIG(nodes[n],multiplicity)) --splitlevel; #ifdef INSTRUMENT if (haschild) ++fertilenodes[n]; #endif } /**************************************************************************/ /**************************************************************************/ int #ifdef GENG_MAIN GENG_MAIN(int argc, char *argv[]) #else main(int argc, char *argv[]) #endif { char *arg; boolean badargs,gote,gotmr,gotf,gotd,gotD,gotx,gotX; boolean secret,connec1,connec2,safe,sparse; char *outfilename,sw; int i,j,argnum; graph g[1]; int tmaxe,deg[1]; bigint nout; int splitlevinc; xword testxword; double t1,t2; char msg[201]; HELP; nauty_check(WORDSIZE,1,MAXN,NAUTYVERSIONID); testxword = (xword)(-1); if (MAXN > 32 || MAXN > WORDSIZE || MAXN > 8*sizeof(xword) || (MAXN == 8*sizeof(xword) && testxword < 0)) { fprintf(stderr,"geng: incompatible MAXN, WORDSIZE, or xword\n"); fprintf(stderr,"--See notes in program source\n"); exit(1); } badargs = FALSE; trianglefree = FALSE; bipartite = FALSE; squarefree = FALSE; verbose = FALSE; nautyformat = FALSE; yformat = FALSE; graph6 = FALSE; sparse6 = FALSE; savemem = FALSE; nooutput = FALSE; canonise = FALSE; header = FALSE; outfilename = NULL; secret = FALSE; safe = FALSE; connec1 = connec2 = FALSE; maxdeg = MAXN; mindeg = 0; gotX = gotx = gotd = gotD = gote = gotmr = gotf = FALSE; argnum = 0; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('n',nautyformat) else SWBOOLEAN('u',nooutput) else SWBOOLEAN('g',graph6) else SWBOOLEAN('s',sparse6) else SWBOOLEAN('t',trianglefree) else SWBOOLEAN('f',squarefree) else SWBOOLEAN('b',bipartite) else SWBOOLEAN('v',verbose) else SWBOOLEAN('l',canonise) else SWBOOLEAN('y',yformat) else SWBOOLEAN('h',header) else SWBOOLEAN('m',savemem) else SWBOOLEAN('c',connec1) else SWBOOLEAN('C',connec2) else SWBOOLEAN('q',quiet) else SWBOOLEAN('$',secret) else SWBOOLEAN('S',safe) else SWINT('d',gotd,mindeg,"geng -d") else SWINT('D',gotD,maxdeg,"geng -D") else SWINT('x',gotx,multiplicity,"geng -x") else SWINT('X',gotX,splitlevinc,"geng -X") #ifdef PLUGIN_SWITCHES PLUGIN_SWITCHES #endif else badargs = TRUE; } } else if (arg[0] == '-' && arg[1] == '\0') gotf = TRUE; else { if (argnum == 0) { if (sscanf(arg,"%d",&maxn) != 1) badargs = TRUE; ++argnum; } else if (gotf) badargs = TRUE; else { if (!gotmr) { if (sscanf(arg,"%d/%d",&res,&mod) == 2) { gotmr = TRUE; continue; } } if (!gote) { if (sscanf(arg,"%d:%d",&mine,&maxe) == 2 || sscanf(arg,"%d-%d",&mine,&maxe) == 2) { gote = TRUE; if (maxe == 0 && mine > 0) maxe = MAXN*(MAXN-1)/2; continue; } else if (sscanf(arg,"%d",&mine) == 1) { gote = TRUE; maxe = mine; continue; } } if (!gotf) { outfilename = arg; gotf = TRUE; continue; } } } } if (argnum == 0) badargs = TRUE; else if (maxn < 1 || maxn > MAXN) { fprintf(stderr,">E geng: n must be in the range 1..%d\n",MAXN); badargs = TRUE; } if (!gotmr) { mod = 1; res = 0; } if (!gote) { mine = 0; maxe = (maxn*maxn - maxn) / 2; } if (connec1 && mindeg < 1 && maxn > 1) mindeg = 1; if (connec2 && mindeg < 2 && maxn > 2) mindeg = 2; if (maxdeg >= maxn) maxdeg = maxn - 1; if (maxe > maxn*maxdeg / 2) maxe = maxn*maxdeg / 2; if (maxdeg > maxe) maxdeg = maxe; if (mindeg < 0) mindeg = 0; if (mine < (maxn*mindeg+1) / 2) mine = (maxn*mindeg+1) / 2; if (!badargs && (mine > maxe || maxe < 0 || maxdeg < 0)) { fprintf(stderr, ">E geng: impossible mine,maxe,mindeg,maxdeg values\n"); badargs = TRUE; } if (!badargs && (res < 0 || res >= mod)) { fprintf(stderr,">E geng: must have 0 <= res < mod\n"); badargs = TRUE; } if (connec2) connec = 2; else if (connec1) connec = 1; else connec = 0; if (connec && mine < maxn-1) mine = maxn - 2 + connec; if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if ((nautyformat!=0) + (yformat!=0) + (graph6!=0) + (sparse6!=0) + (nooutput!=0) > 1) gt_abort(">E geng: -uyngs are incompatible\n"); #ifdef OUTPROC outproc = OUTPROC; #else if (nautyformat) outproc = writenauty; else if (yformat) outproc = writeny; else if (nooutput) outproc = nullwrite; else if (sparse6) outproc = writes6x; else outproc = writeg6x; #endif #ifdef PLUGIN_INIT PLUGIN_INIT #endif for (i = 0; i <= maxe; ++i) ZEROBIG(ecount[i]); for (i = 0; i < maxn; ++i) ZEROBIG(nodes[i]); if (nooutput) outfile = stdout; else if (!gotf || outfilename == NULL) { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename, nautyformat ? "wb" : "w")) == NULL) { fprintf(stderr, ">E geng: can't open %s for writing\n",outfilename); gt_abort(NULL); } if (bipartite) if (squarefree) tmaxe = maxebf[maxn]; else tmaxe = maxeb[maxn]; else if (trianglefree) if (squarefree) tmaxe = maxeft[maxn]; else tmaxe = maxet[maxn]; else if (squarefree) tmaxe = maxef[maxn]; else tmaxe = (maxn*maxn - maxn) / 2; if (safe) ++tmaxe; if (maxe > tmaxe) maxe = tmaxe; if (gotx) { if (multiplicity < 3 * mod || multiplicity > 999999999) gt_abort(">E geng: -x value must be in [3*mod,10^9-1]\n"); } else multiplicity = PRUNEMULT * mod; if (!gotX) splitlevinc = 0; /* if (!quiet) { fprintf(stderr,">A %s -%s%s%s%s%s%s",argv[0], connec2 ? "C" : connec1 ? "c" : "", trianglefree ? "t" : "", squarefree ? "f" : "", bipartite ? "b" : "", canonise ? "l" : "", savemem ? "m" : ""); if (mod > 1) fprintf(stderr,"X%dx%d",splitlevinc,multiplicity); fprintf(stderr,"d%dD%d n=%d e=%d",mindeg,maxdeg,maxn,mine); if (maxe > mine) fprintf(stderr,"-%d",maxe); if (mod > 1) fprintf(stderr," class=%d/%d",res,mod); fprintf(stderr,"\n"); fflush(stderr); } */ if (!quiet) { msg[0] = '\0'; if (strlen(argv[0]) > 75) fprintf(stderr,">A %s",argv[0]); else CATMSG1(">A %s",argv[0]); CATMSG6(" -%s%s%s%s%s%s", connec2 ? "C" : connec1 ? "c" : "", trianglefree ? "t" : "", squarefree ? "f" : "", bipartite ? "b" : "", canonise ? "l" : "", savemem ? "m" : ""); if (mod > 1) CATMSG2("X%dx%d",splitlevinc,multiplicity); CATMSG4("d%dD%d n=%d e=%d",mindeg,maxdeg,maxn,mine); if (maxe > mine) CATMSG1("-%d",maxe); if (mod > 1) CATMSG2(" class=%d/%d",res,mod); CATMSG0("\n"); fputs(msg,stderr); fflush(stderr); } g[0] = 0; deg[0] = 0; sparse = bipartite || squarefree || trianglefree || savemem; t1 = CPUTIME; if (header) { if (sparse6) { writeline(outfile,SPARSE6_HEADER); fflush(outfile); } else if (!yformat && !nautyformat && !nooutput) { writeline(outfile,GRAPH6_HEADER); fflush(outfile); } } if (maxn == 1) { if (res == 0) { ADDBIG(ecount[0],1); (*outproc)(outfile,g,1); } } else { if (maxn > 28 || maxn+4 > 8*sizeof(xword)) savemem = sparse = TRUE; if (maxn == maxe+1 && connec) bipartite = squarefree = sparse = TRUE; /* trees */ makeleveldata(sparse); if (maxn >= 14 && mod > 1) splitlevel = maxn - 4; else if (maxn >= 6 && mod > 1) splitlevel = maxn - 3; else splitlevel = -1; splitlevel += splitlevinc; if (splitlevel > maxn - 1) splitlevel = maxn - 1; if (splitlevel < 3) splitlevel = -1; min_splitlevel = 6; odometer = secret ? -1 : res; if (maxe >= mine && (mod <= 1 || mod > 1 && (splitlevel > 2 || res == 0))) { xbnds(1,0,0); if (sparse) { data[1].xx[0] = 0; if (maxdeg > 0) data[1].xx[1] = xbit[0]; data[1].xlim = data[1].xub + 1; } if (bipartite) if (squarefree) spaextend(g,1,deg,0,TRUE, data[1].xlb,data[1].xub,makeb6graph); else spaextend(g,1,deg,0,TRUE, data[1].xlb,data[1].xub,makebgraph); else if (trianglefree) if (squarefree) spaextend(g,1,deg,0,TRUE, data[1].xlb,data[1].xub,makeg5graph); else spaextend(g,1,deg,0,TRUE, data[1].xlb,data[1].xub,makexgraph); else if (squarefree) spaextend(g,1,deg,0,TRUE, data[1].xlb,data[1].xub,makesgraph); else if (savemem) spaextend(g,1,deg,0,TRUE, data[1].xlb,data[1].xub,make0graph); else genextend(g,1,deg,0,TRUE,data[1].xlb,data[1].xub); } } t2 = CPUTIME; ZEROBIG(nout); for (i = 0; i <= maxe; ++i) SUMBIGS(nout,ecount[i]); if (verbose) { for (i = 0; i <= maxe; ++i) if (!ISZEROBIG(ecount[i])) { fprintf(stderr,">C "); PRINTBIG(stderr,ecount[i]); fprintf(stderr," graphs with %d edges\n",i); } } #ifdef INSTRUMENT fprintf(stderr,"\n>N node counts\n"); for (i = 1; i < maxn; ++i) { fprintf(stderr," level %2d: \n",i); PRINTBIG(stderr,nodes[i]); fprintf(stderr," (%lu rigid, %lu fertile)\n", rigidnodes[i],fertilenodes[i]); } fprintf(stderr,">A1 %lu calls to accept1, %lu nauty, %lu succeeded\n", a1calls,a1nauty,a1succs); fprintf(stderr, ">A2 %lu calls to accept2, %lu nuniq, %lu nauty, %lu succeeded\n", a2calls,a2uniq,a2nauty,a2succs); fprintf(stderr,"\n"); #endif #ifdef SUMMARY SUMMARY(nout,t2-t1); #endif if (!quiet) { fprintf(stderr,">Z "); PRINTBIG(stderr,nout); fprintf(stderr," graphs generated in %3.2f sec\n",t2-t1); } #ifdef GENG_MAIN for (i = 1; i < maxn; ++i) if (sparse) { free(data[i].xorb); free(data[i].xx); } else { free(data[i].xorb); free(data[i].xset); free(data[i].xinv); free(data[i].xcard); } return 0; #else exit(0); #endif } nauty24r2/labelg.c0000600000604200001440000002100111274163463012673 0ustar bdmusers/* labelg.c version 1.3; B D McKay, July 2008 */ #define USAGE "labelg [-qsg] [-fxxx] [-S] [-i# -I#:# -K#] [infile [outfile]]" #define HELPTEXT \ " Canonically label a file of graphs.\n\ \n\ -s force output to sparse6 format\n\ -g force output to graph6 format\n\ If neither -s or -g are given, the output format is\n\ determined by the header or, if there is none, by the\n\ format of the first input graph. Also see -S. \n\ -S Use sparse representation internally.\n\ Note that this changes the canonical labelling.\n\ Only sparse6 output is supported in this case.\n\ Multiple edges are not supported. One loop per vertex is ok.\n\ \n\ The output file will have a header if and only if the input file does.\n\ \n\ -fxxx Specify a partition of the point set. xxx is any\n\ string of ASCII characters except nul. This string is\n\ considered extended to infinity on the right with the\n\ character 'z'. One character is associated with each point,\n\ in the order given. The labelling used obeys these rules:\n\ (1) the new order of the points is such that the associated\n\ characters are in ASCII ascending order\n\ (2) if two graphs are labelled using the same string xxx,\n\ the output graphs are identical iff there is an\n\ associated-character-preserving isomorphism between them.\n\ No option can be concatenated to the right of -f.\n\ \n\ -i# select an invariant (1 = twopaths, 2 = adjtriang(K), 3 = triples,\n\ 4 = quadruples, 5 = celltrips, 6 = cellquads, 7 = cellquins,\n\ 8 = distances(K), 9 = indsets(K), 10 = cliques(K), 11 = cellcliq(K),\n\ 12 = cellind(K), 13 = adjacencies, 14 = cellfano, 15 = cellfano2)\n\ -I#:# select mininvarlevel and maxinvarlevel (default 1:1)\n\ -K# select invararg (default 3)\n\ \n\ -q suppress auxiliary information\n" /*************************************************************************/ #include "gtools.h" #include "nautinv.h" #include "gutils.h" static struct invarrec { void (*entrypoint)(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); char *name; } invarproc[] = {{NULL, "none"}, {twopaths, "twopaths"}, {adjtriang, "adjtriang"}, {triples, "triples"}, {quadruples, "quadruples"}, {celltrips, "celltrips"}, {cellquads, "cellquads"}, {cellquins, "cellquins"}, {distances, "distances"}, {indsets, "indsets"}, {cliques, "cliques"}, {cellcliq, "cellcliq"}, {cellind, "cellind"}, {adjacencies, "adjacencies"}, {cellfano, "cellfano"}, {cellfano2, "cellfano2"}}; #define NUMINVARS ((int)(sizeof(invarproc)/sizeof(struct invarrec))) static nauty_counter orbtotal; static double unorbtotal; extern int gt_numorbits; /**************************************************************************/ int main(int argc, char *argv[]) { graph *g; sparsegraph sg,sh; int m,n,codetype; int argnum,j,outcode; char *arg,sw,*fmt; boolean badargs; boolean sswitch,gswitch,qswitch,fswitch,Oswitch; boolean iswitch,Iswitch,Kswitch,Mswitch,Sswitch; boolean uswitch; int inv,mininvarlevel,maxinvarlevel,invararg; long minil,maxil; double t; char *infilename,*outfilename; FILE *infile,*outfile; nauty_counter nin; int ii,secret,loops; #if MAXN graph h[MAXN*MAXM]; #else DYNALLSTAT(graph,h,h_sz); #endif HELP; nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); sswitch = gswitch = qswitch = FALSE; fswitch = Oswitch = Mswitch = FALSE; iswitch = Iswitch = Kswitch = FALSE; uswitch = Sswitch = FALSE; infilename = outfilename = NULL; inv = 0; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('s',sswitch) else SWBOOLEAN('g',gswitch) else SWBOOLEAN('u',uswitch) else SWBOOLEAN('q',qswitch) else SWBOOLEAN('O',Oswitch) else SWBOOLEAN('S',Sswitch) else SWINT('i',iswitch,inv,"labelg -i") else SWINT('K',Kswitch,invararg,"labelg -K") else SWRANGE('k',":-",Iswitch,minil,maxil,"labelg -k") else SWRANGE('I',":-",Iswitch,minil,maxil,"labelg -I") else if (sw == 'f') { fswitch = TRUE; fmt = arg; break; } else SWINT('M',Mswitch,secret,"labelg -M") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (sswitch && gswitch) gt_abort(">E labelg: -s and -g are incompatible\n"); if (!Sswitch && iswitch && (inv > 15)) gt_abort(">E labelg: -i value must be 0..15\n"); if (Sswitch && iswitch && (inv != 8)) gt_abort(">E labelg: only distances (-i8) is available with -S"); if (iswitch && inv == 0) iswitch = FALSE; if (iswitch) { if (Iswitch) { mininvarlevel = minil; maxinvarlevel = maxil; } else mininvarlevel = maxinvarlevel = 1; if (!Kswitch) invararg = 3; } if (!Mswitch) secret = 1; if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!qswitch) { fprintf(stderr,">A labelg"); if (sswitch || gswitch || fswitch || iswitch || Sswitch) fprintf(stderr," -"); if (sswitch) fprintf(stderr,"s"); if (gswitch) fprintf(stderr,"g"); if (Sswitch) fprintf(stderr,"S"); if (iswitch) fprintf(stderr,"i=%s[%d:%d,%d]",invarproc[inv].name, mininvarlevel,maxinvarlevel,invararg); if (fswitch) fprintf(stderr,"f%s",fmt); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (uswitch) outcode = 0; else if (sswitch || Sswitch || !gswitch && (codetype&SPARSE6)) outcode = SPARSE6; else outcode = GRAPH6; if (!fswitch) fmt = NULL; if (!uswitch && (codetype&HAS_HEADER)) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } nin = 0; orbtotal = 0; unorbtotal = 0.0; t = CPUTIME; if (Sswitch) { SG_INIT(sg); SG_INIT(sh); while (TRUE) { if (read_sg_loops(infile,&sg,&loops) == NULL) break; ++nin; n = sg.nv; m = (n + WORDSIZE - 1) / WORDSIZE; SG_ALLOC(sh,n,sg.nde,"labelg"); for (ii = 0; ii < secret; ++ii) fcanonise_inv_sg(&sg,m,n,&sh,fmt,iswitch?distances_sg:NULL, mininvarlevel,maxinvarlevel,invararg,loops>0); sortlists_sg(&sh); orbtotal += gt_numorbits; unorbtotal += 1.0 / gt_numorbits; if (outcode == SPARSE6) writes6_sg(outfile,&sh); if (outcode == GRAPH6) gt_abort(">E labelg: sparse graph6 output not available"); } } else { while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"labelg"); #endif loops = loopcount(g,m,n); for (ii = 0; ii < secret; ++ii) fcanonise_inv(g,m,n,h,fmt,invarproc[inv].entrypoint, mininvarlevel,maxinvarlevel,invararg,loops>0); orbtotal += gt_numorbits; unorbtotal += 1.0 / gt_numorbits; if (outcode == SPARSE6) writes6(outfile,h,m,n); if (outcode == GRAPH6) writeg6(outfile,h,m,n); FREES(g); } } t = CPUTIME - t; #if LONG_LONG_COUNTERS if (Oswitch) fprintf(stderr,">C orbit totals = %lld %15.8f\n", orbtotal,unorbtotal); if (!qswitch) fprintf(stderr, ">Z %lld graphs labelled from %s to %s in %3.2f sec.\n", nin,infilename,outfilename,t); #else if (Oswitch) fprintf(stderr,">C orbit totals = %ld %15.8f\n", orbtotal,unorbtotal); if (!qswitch) fprintf(stderr, ">Z %ld graphs labelled from %s to %s in %3.2f sec.\n", nin,infilename,outfilename,t); #endif exit(0); } nauty24r2/nautest.c0000600000604200001440000000467611274163463013153 0ustar bdmusers/* Test for basic nauty functions (but not nauty itself) */ #include "nauty.h" int main(int argc, char *argv[]) { int i,j,bad; setword w; printf("NAUTYVERSION=%s NAUTYVERSIONID=%d\n", NAUTYVERSION,NAUTYVERSIONID); printf("MAXN=%d MAXM=%d WORDSIZE=%d NAUTY_INFINITY=%d\n", MAXN,MAXM,WORDSIZE,NAUTY_INFINITY); printf("sizes: short=%d int=%d long=%d double=%d\n", (int)sizeof(short),(int)sizeof(int),(int)sizeof(long), (int)sizeof(double)); printf("sizes: boolean=%d setword=%d shortish=%d\n", (int)sizeof(boolean),(int)sizeof(setword), (int)sizeof(shortish)); #ifdef SETWORD_LONGLONG printf("sizeof(long long)=%d\n",sizeof(long long)); #endif printf("defined:"); #ifdef __STDC__ printf(" __STDC__"); #endif #ifdef BIGNAUTY printf(" BIGNAUTY"); #endif #ifdef SYS_UNIX printf(" SYS_UNIX"); #endif #ifdef SYS_CRAY printf(" SYS_CRAY"); #endif #ifdef SETWORD_SHORT printf(" SETWORD_SHORT"); #endif #ifdef SETWORD_INT printf(" SETWORD_INT"); #endif #ifdef SETWORD_LONG printf(" SETWORD_LONG"); #endif #ifdef SETWORD_LONGLONG printf(" SETWORD_LONGLONG"); #endif printf("\n"); bad = 0; if (8*sizeof(setword) != WORDSIZE) { printf("\n ***** NOTE: WORDSIZE mismatch *****\n\n"); ++bad; } for (i = 0; i < WORDSIZE; ++i) { w = ALLMASK(i); if (POPCOUNT(w) != i) { printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i); ++bad; } } for (i = 0; i < WORDSIZE; ++i) { w = BITMASK(i); if (POPCOUNT(w) != WORDSIZE-i-1) { printf("\n ***** POPCOUNT(BITMASK) error %d *****\n\n",i); ++bad; } } for (i = 0; i < WORDSIZE; ++i) if (POPCOUNT(ALLMASK(i)) != i) { printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i); ++bad; } for (i = 0; i < WORDSIZE; ++i) if (FIRSTBIT(BITT[i]) != i) { printf("\n ***** FIRSTBIT(BITT) error %d *****\n\n",i); ++bad; } for (i = 0; i < WORDSIZE; ++i) if (POPCOUNT(BITT[i]) != 1) { printf("\n ***** POPCOUNT(BITT) error %d *****\n\n",i); ++bad; } for (i = 0; i < WORDSIZE; ++i) { w = 0; for (j = 1; j <= WORDSIZE; ++j) { w |= BITT[(j*97+i)%WORDSIZE]; if (POPCOUNT(w) != j) { printf("\n ***** POPCOUNT(w) error %d %d *****\n\n",i,j); ++bad; } } } if (!bad) printf("\nNo errors found\n"); else printf("\nXXXXXXX %d errors found XXXXXXX\n",bad); exit(0); } nauty24r2/testM.dre0000600000604200001440000012726511274163463013114 0ustar bdmusers!A25 n=25 $=1 g 1 : 11 12 13 14 15 16; 2 : 11 12 17 18 19 20; 3 : 11 13 17 21 22 23; 4 : 11 14 18 21 24 25; 5 : 12 13 19 22 24 25; 6 : 12 15 20 21 23 24; 7 : 13 16 18 20 23 25; 8 : 14 15 17 19 23 25; 9 : 14 16 17 20 22 24; 10 : 15 16 18 19 21 22; 11 : 1 2 3 4; 12 : 1 2 5 6; 13 : 1 3 5 7; 14 : 1 4 8 9; 15 : 1 6 8 10; 16 : 1 7 9 10; 17 : 2 3 8 9; 18 : 2 4 7 10; 19 : 2 5 8 10; 20 : 2 6 7 9; 21 : 3 4 6 10; 22 : 3 5 9 10; 23 : 3 6 7 8; 24 : 4 5 6 9; 25 : 4 5 7 8; $$ x a=67c5f67 o=eebbe52 cx b=52659d4 jcx a=feba7f1 o=1ef70b3 b=b5d70ff !B25 n=25 $=1 g 1 : 11 12 13 14 15 16; 2 : 11 12 17 18 19 20; 3 : 11 13 17 21 22 23; 4 : 11 14 18 21 24 25; 5 : 12 13 19 22 24 25; 6 : 12 15 20 21 23 24; 7 : 13 16 18 20 23 25; 8 : 14 15 17 19 23 25; 9 : 14 16 19 20 21 22; 10 : 15 16 17 18 22 24; 11 : 1 2 3 4; 12 : 1 2 5 6; 13 : 1 3 5 7; 14 : 1 4 8 9; 15 : 1 6 8 10; 16 : 1 7 9 10; 17 : 2 3 8 10; 18 : 2 4 7 10; 19 : 2 5 8 9; 20 : 2 6 7 9; 21 : 3 4 6 9; 22 : 3 5 9 10; 23 : 3 6 7 8; 24 : 4 5 6 10; 25 : 4 5 7 8; $$ x a=cd91459 o=1dacc5f cx b=5980601 jcx a=38904ce o=3bc8a2a b=e70138 !A35 n=35 $=1 g 1 : 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35; 2 : 10 11 12 13 16 17 18 19 28 29 30 31 32 33 34 35; 3 : 10 11 12 13 14 15 18 19 21 22 23 25 26 27 34 35; 4 : 8 9 12 13 15 16 17 19 20 22 23 24 27 30 33 35; 5 : 8 9 12 13 14 16 17 18 20 21 25 26 27 28 29 31; 6 : 8 9 10 11 14 15 17 19 21 23 24 25 29 30 31 32; 7 : 8 9 10 11 14 15 16 18 20 22 24 26 28 32 33 34; 8 : 4 5 6 7 15 17 18 19 25 26 27 31 32 33 34 35; 9 : 4 5 6 7 14 16 18 19 21 22 23 28 29 30 34 35; 10 : 2 3 6 7 15 16 17 18 20 21 23 26 27 29 30 33; 11 : 2 3 6 7 14 16 17 19 20 22 24 25 27 28 31 35; 12 : 2 3 4 5 14 15 17 18 21 22 24 25 28 30 32 33; 13 : 2 3 4 5 14 15 16 19 20 23 24 26 29 31 32 34; 14 : 3 5 6 7 9 11 12 13 24 26 27 29 30 32 33 35; 15 : 3 4 6 7 8 10 12 13 20 21 22 28 29 31 32 35; 16 : 2 4 5 7 9 10 11 13 21 22 23 25 27 31 32 33; 17 : 2 4 5 6 8 10 11 12 22 23 24 26 27 28 29 34; 18 : 2 3 5 7 8 9 10 12 20 23 24 25 30 31 34 35; 19 : 2 3 4 6 8 9 11 13 20 21 25 26 28 30 33 34; 20 : 1 4 5 7 10 11 13 15 18 19 24 25 27 28 29 30; 21 : 1 3 5 6 9 10 12 15 16 19 24 27 28 31 33 34; 22 : 1 3 4 7 9 11 12 15 16 17 25 26 29 30 31 34; 23 : 1 3 4 6 9 10 13 16 17 18 24 25 26 28 32 35; 24 : 1 4 6 7 11 12 13 14 17 18 20 21 23 31 33 34; 25 : 1 3 5 6 8 11 12 16 18 19 20 22 23 29 32 33; 26 : 1 3 5 7 8 10 13 14 17 19 22 23 28 30 31 33; 27 : 1 3 4 5 8 10 11 14 16 17 20 21 30 32 34 35; 28 : 1 2 5 7 9 11 12 15 17 19 20 21 23 26 32 35; 29 : 1 2 5 6 9 10 13 14 15 17 20 22 25 33 34 35; 30 : 1 2 4 6 9 10 12 14 18 19 20 22 26 27 31 32; 31 : 1 2 5 6 8 11 13 15 16 18 21 22 24 26 30 35; 32 : 1 2 6 7 8 12 13 14 15 16 23 25 27 28 30 34; 33 : 1 2 4 7 8 10 12 14 16 19 21 24 25 26 29 35; 34 : 1 2 3 7 8 9 13 17 18 19 21 22 24 27 29 32; 35 : 1 2 3 4 8 9 11 14 15 18 23 27 28 29 31 33; $$ *=10 k=1 1 K=4 x a=1 o=eda74c0 cx b=6e93242 jcx b=fe4cd57 !B35 n=35 $=1 g 1 : 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35; 2 : 10 11 12 13 16 17 18 19 28 29 30 31 32 33 34 35; 3 : 10 11 12 13 14 15 18 19 21 22 23 25 26 27 34 35; 4 : 8 9 12 13 15 16 17 19 21 22 23 24 27 30 32 33; 5 : 8 9 12 13 14 16 17 18 20 23 25 26 27 28 29 31; 6 : 8 9 10 11 14 15 17 19 20 22 24 25 29 30 31 35; 7 : 8 9 10 11 14 15 16 18 20 21 24 26 28 32 33 34; 8 : 4 5 6 7 15 17 18 19 25 26 27 31 32 33 34 35; 9 : 4 5 6 7 14 16 18 19 21 22 23 28 29 30 34 35; 10 : 2 3 6 7 15 16 17 18 20 22 23 26 27 29 30 33; 11 : 2 3 6 7 14 16 17 19 21 23 24 25 27 28 31 32; 12 : 2 3 4 5 14 15 17 18 20 21 24 25 28 30 33 35; 13 : 2 3 4 5 14 15 16 19 20 22 24 26 29 31 32 34; 14 : 3 5 6 7 9 11 12 13 24 26 27 29 30 32 33 35; 15 : 3 4 6 7 8 10 12 13 20 21 23 28 29 31 32 35; 16 : 2 4 5 7 9 10 11 13 20 21 22 25 27 31 33 35; 17 : 2 4 5 6 8 10 11 12 21 22 24 26 27 28 29 34; 18 : 2 3 5 7 8 9 10 12 22 23 24 25 30 31 32 34; 19 : 2 3 4 6 8 9 11 13 20 23 25 26 28 30 33 34; 20 : 1 5 6 7 10 12 13 15 16 19 24 25 27 28 30 34; 21 : 1 3 4 7 9 11 12 15 16 17 25 26 29 30 31 34; 22 : 1 3 4 6 9 10 13 16 17 18 24 25 26 28 32 35; 23 : 1 3 4 5 9 10 11 15 18 19 24 27 28 29 31 33; 24 : 1 4 6 7 11 12 13 14 17 18 20 22 23 31 33 34; 25 : 1 3 5 6 8 11 12 16 18 19 20 21 22 29 32 33; 26 : 1 3 5 7 8 10 13 14 17 19 21 22 28 30 31 33; 27 : 1 3 4 5 8 10 11 14 16 17 20 23 30 32 34 35; 28 : 1 2 5 7 9 11 12 15 17 19 20 22 23 26 32 35; 29 : 1 2 5 6 9 10 13 14 15 17 21 23 25 32 33 34; 30 : 1 2 4 6 9 10 12 14 18 19 20 21 26 27 31 32; 31 : 1 2 5 6 8 11 13 15 16 18 21 23 24 26 30 35; 32 : 1 2 4 7 8 11 13 14 15 18 22 25 27 28 29 30; 33 : 1 2 4 7 8 10 12 14 16 19 23 24 25 26 29 35; 34 : 1 2 3 7 8 9 13 17 18 19 20 21 24 27 29 35; 35 : 1 2 3 6 8 9 12 14 15 16 22 27 28 31 33 34; $$ *=10 k=1 1 K=4 x a=1 o=eda74c0 cx b=ea3e30e jcx b=a44f4af !A52 n=52 $=1 g 1 : 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26; 2 : 1 3 4 5 6 7 8 9 10 11 12 13 14 41 42 43 44 45 46 47 48 49 50 51 52; 3 : 1 2 4 5 12 13 14 15 16 17 18 19 20 32 33 34 35 36 37 47 48 49 50 51 52; 4 : 1 2 3 5 6 7 8 15 17 20 21 23 25 35 36 37 38 39 40 42 44 45 48 50 52; 5 : 1 2 3 4 6 7 8 16 18 19 22 24 26 35 36 37 38 39 40 41 43 46 47 49 51; 6 : 1 2 4 5 10 11 14 15 18 21 23 24 26 29 33 34 35 38 39 42 43 45 46 48 51; 7 : 1 2 4 5 9 11 13 16 17 22 23 24 25 29 32 34 36 38 40 41 44 45 46 47 52; 8 : 1 2 4 5 9 10 12 19 20 21 22 25 26 29 32 33 37 39 40 41 42 43 44 49 50; 9 : 1 2 7 8 10 11 14 15 17 18 19 22 25 29 30 31 32 38 39 42 46 47 49 50 52; 10 : 1 2 6 8 9 11 13 16 17 18 20 21 26 29 30 31 33 38 40 41 45 48 49 50 51; 11 : 1 2 6 7 9 10 12 15 16 19 20 23 24 29 30 31 34 39 40 43 44 47 48 51 52; 12 : 1 2 3 8 11 13 14 19 20 21 22 23 24 30 31 32 33 35 36 41 42 43 44 51 52; 13 : 1 2 3 7 10 12 14 16 17 21 24 25 26 30 31 32 34 35 37 41 44 45 46 48 49; 14 : 1 2 3 6 9 12 13 15 18 22 23 25 26 30 31 33 34 36 37 42 43 45 46 47 50; 15 : 1 3 4 6 9 11 14 17 19 20 24 25 26 28 31 33 34 36 38 39 42 44 47 48 49; 16 : 1 3 5 7 10 11 13 18 19 20 23 25 26 28 30 32 34 35 38 40 41 43 47 48 50; 17 : 1 3 4 7 9 10 13 15 18 20 21 22 24 28 31 32 34 37 38 40 42 45 49 51 52; 18 : 1 3 5 6 9 10 14 16 17 19 21 22 23 28 30 33 34 37 38 39 41 46 50 51 52; 19 : 1 3 5 8 9 11 12 15 16 18 21 24 25 28 30 32 33 36 39 40 43 46 48 49 52; 20 : 1 3 4 8 10 11 12 15 16 17 22 23 26 28 31 32 33 35 39 40 44 45 47 50 51; 21 : 1 4 6 8 10 12 13 17 18 19 23 24 25 28 29 31 33 35 37 40 41 42 46 48 52; 22 : 1 5 7 8 9 12 14 17 18 20 23 24 26 28 29 30 32 36 37 39 41 42 45 47 51; 23 : 1 4 6 7 11 12 14 16 18 20 21 22 25 28 29 31 34 35 36 39 41 43 45 50 52; 24 : 1 5 6 7 11 12 13 15 17 19 21 22 26 28 29 30 34 35 36 40 42 44 46 49 51; 25 : 1 4 7 8 9 13 14 15 16 19 21 23 26 28 29 31 32 36 37 38 43 44 46 48 50; 26 : 1 5 6 8 10 13 14 15 16 20 22 24 25 28 29 30 33 35 37 38 43 44 45 47 49; 27 : 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52; 28 : 15 16 17 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40; 29 : 6 7 8 9 10 11 21 22 23 24 25 26 27 28 30 31 38 39 40 41 42 43 44 45 46; 30 : 9 10 11 12 13 14 16 18 19 22 24 26 27 28 29 31 32 33 34 41 43 46 47 49 51; 31 : 9 10 11 12 13 14 15 17 20 21 23 25 27 28 29 30 32 33 34 42 44 45 48 50 52; 32 : 3 7 8 9 12 13 16 17 19 20 22 25 27 28 30 31 36 37 40 41 44 47 49 50 52; 33 : 3 6 8 10 12 14 15 18 19 20 21 26 27 28 30 31 35 37 39 42 43 48 49 50 51; 34 : 3 6 7 11 13 14 15 16 17 18 23 24 27 28 30 31 35 36 38 45 46 47 48 51 52; 35 : 3 4 5 6 12 13 16 20 21 23 24 26 27 28 33 34 36 37 40 41 43 44 45 48 51; 36 : 3 4 5 7 12 14 15 19 22 23 24 25 27 28 32 34 35 37 39 42 43 44 46 47 52; 37 : 3 4 5 8 13 14 17 18 21 22 25 26 27 28 32 33 35 36 38 41 42 45 46 49 50; 38 : 4 5 6 7 9 10 15 16 17 18 25 26 27 28 29 34 37 39 40 45 46 47 48 49 50; 39 : 4 5 6 8 9 11 15 18 19 20 22 23 27 28 29 33 36 38 40 42 43 47 50 51 52; 40 : 4 5 7 8 10 11 16 17 19 20 21 24 27 28 29 32 35 38 39 41 44 48 49 51 52; 41 : 2 5 7 8 10 12 13 16 18 21 22 23 27 29 30 32 35 37 40 43 45 46 50 51 52; 42 : 2 4 6 8 9 12 14 15 17 21 22 24 27 29 31 33 36 37 39 44 45 46 49 51 52; 43 : 2 5 6 8 11 12 14 16 19 23 25 26 27 29 30 33 35 36 39 41 44 46 47 48 50; 44 : 2 4 7 8 11 12 13 15 20 24 25 26 27 29 31 32 35 36 40 42 43 45 47 48 49; 45 : 2 4 6 7 10 13 14 17 20 22 23 26 27 29 31 34 35 37 38 41 42 44 47 50 51; 46 : 2 5 6 7 9 13 14 18 19 21 24 25 27 29 30 34 36 37 38 41 42 43 48 49 52; 47 : 2 3 5 7 9 11 14 15 16 20 22 26 27 30 32 34 36 38 39 43 44 45 49 50 51; 48 : 2 3 4 6 10 11 13 15 16 19 21 25 27 31 33 34 35 38 40 43 44 46 49 50 52; 49 : 2 3 5 8 9 10 13 15 17 19 24 26 27 30 32 33 37 38 40 42 44 46 47 48 51; 50 : 2 3 4 8 9 10 14 16 18 20 23 25 27 31 32 33 37 38 39 41 43 45 47 48 52; 51 : 2 3 5 6 10 11 12 17 18 20 22 24 27 30 33 34 35 39 40 41 42 45 47 49 52; 52 : 2 3 4 7 9 11 12 17 18 19 21 23 27 31 32 34 36 39 40 41 42 46 48 50 51; $$ *=10 k=1 1 K=5 -c x a=e2832a5 o=284a5be jcx a=200e58f o=c78c890 b=25d3f3f !B52 n=52 $=1 g 1 : 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26; 2 : 1 5 10 11 12 13 14 17 18 20 24 25 26 29 30 32 33 34 35 41 42 45 47 48 49; 3 : 1 7 10 11 12 15 16 17 19 21 23 24 25 28 30 31 32 34 35 39 40 44 46 48 52; 4 : 1 5 6 8 12 15 16 17 20 21 22 25 26 28 29 33 35 36 37 39 40 44 45 49 50; 5 : 1 2 4 8 12 13 15 17 18 19 22 23 24 29 32 33 35 36 37 40 42 46 47 51 52; 6 : 1 4 9 11 12 14 16 18 20 21 22 23 24 28 29 31 33 34 36 39 41 43 45 51 52; 7 : 1 3 8 9 13 14 15 17 20 21 23 24 26 28 30 31 32 36 37 38 42 44 45 48 51; 8 : 1 4 5 7 13 14 16 18 19 21 23 25 26 28 29 32 35 36 37 38 41 43 46 48 50; 9 : 1 6 7 10 13 15 16 18 19 20 22 24 26 28 29 30 31 34 37 38 40 43 47 49 51; 10 : 1 2 3 9 12 14 15 18 19 21 22 25 26 30 31 32 33 34 37 39 42 43 46 49 50; 11 : 1 2 3 6 13 14 16 17 19 20 22 23 25 30 31 33 34 35 36 38 41 44 47 50 52; 12 : 1 2 3 4 5 6 10 19 20 21 23 24 26 33 34 35 37 39 40 41 42 43 44 48 51; 13 : 1 2 5 7 8 9 11 19 20 21 22 24 25 29 30 32 36 38 40 41 42 43 44 49 52; 14 : 1 2 6 7 8 10 11 17 18 21 22 23 26 29 30 31 35 38 39 41 42 45 46 50 51; 15 : 1 3 4 5 7 9 10 17 18 20 22 23 25 28 32 34 37 38 39 40 42 45 47 50 52; 16 : 1 3 4 6 8 9 11 17 18 19 24 25 26 28 31 33 36 38 39 40 41 46 47 48 49; 17 : 1 2 3 4 5 7 11 14 15 16 22 24 26 32 34 35 36 38 39 44 45 46 47 49 51; 18 : 1 2 5 6 8 9 10 14 15 16 23 24 25 29 30 33 37 38 39 43 45 46 47 48 52; 19 : 1 3 5 8 9 10 11 12 13 16 22 23 26 28 30 32 33 40 41 43 44 46 47 50 51; 20 : 1 2 4 6 7 9 11 12 13 15 23 25 26 29 31 34 36 40 42 43 44 45 47 48 50; 21 : 1 3 4 6 7 8 10 12 13 14 22 24 25 28 31 35 37 41 42 43 44 45 46 49 52; 22 : 1 4 5 6 9 10 11 13 14 15 17 19 21 28 29 33 34 38 42 44 46 49 50 51 52; 23 : 1 3 5 6 7 8 11 12 14 15 18 19 20 28 30 35 36 39 42 43 47 48 50 51 52; 24 : 1 2 3 5 6 7 9 12 13 16 17 18 21 30 34 36 37 40 41 45 46 48 49 51 52; 25 : 1 2 3 4 8 10 11 13 15 16 18 20 21 31 32 33 35 38 40 43 45 48 49 50 52; 26 : 1 2 4 7 8 9 10 12 14 16 17 19 20 29 31 32 37 39 41 44 47 48 49 50 51; 27 : 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52; 28 : 3 4 6 7 8 9 15 16 19 21 22 23 27 31 36 37 38 39 40 43 44 46 50 51 52; 29 : 2 4 5 6 8 9 13 14 18 20 22 26 27 33 36 37 38 41 42 43 45 47 49 50 51; 30 : 2 3 7 9 10 11 13 14 18 19 23 24 27 31 32 34 38 41 42 43 46 47 48 51 52; 31 : 3 6 7 9 10 11 14 16 20 21 25 26 27 28 30 34 38 39 41 43 44 45 48 49 50; 32 : 2 3 5 7 8 10 13 15 17 19 25 26 27 30 35 37 38 40 42 44 46 47 48 49 50; 33 : 2 4 5 6 10 11 12 16 18 19 22 25 27 29 34 35 39 40 41 43 46 47 49 50 52; 34 : 2 3 6 9 10 11 12 15 17 20 22 24 27 30 31 33 39 40 42 44 45 47 49 51 52; 35 : 2 3 4 5 8 11 12 14 17 21 23 25 27 32 33 36 39 41 42 44 45 46 48 50 52; 36 : 4 5 6 7 8 11 13 16 17 20 23 24 27 28 29 35 38 40 41 44 45 47 48 51 52; 37 : 4 5 7 8 9 10 12 15 18 21 24 26 27 28 29 32 39 40 42 43 45 46 48 49 51; 38 : 7 8 9 11 13 14 15 16 17 18 22 25 27 28 29 30 31 32 36 45 46 47 49 50 52; 39 : 3 4 6 10 12 14 15 16 17 18 23 26 27 28 31 33 34 35 37 45 46 47 48 50 51; 40 : 3 4 5 9 12 13 15 16 19 20 24 25 27 28 32 33 34 36 37 43 44 47 48 49 52; 41 : 2 6 8 11 12 13 14 16 19 21 24 26 27 29 30 31 33 35 36 43 44 46 48 49 51; 42 : 2 5 7 10 12 13 14 15 20 21 22 23 27 29 30 32 34 35 37 43 44 45 50 51 52; 43 : 6 8 9 10 12 13 18 19 20 21 23 25 27 28 29 30 31 33 37 40 41 42 48 50 52; 44 : 3 4 7 11 12 13 17 19 20 21 22 26 27 28 31 32 34 35 36 40 41 42 49 50 51; 45 : 2 4 6 7 14 15 17 18 20 21 24 25 27 29 31 34 35 36 37 38 39 42 48 49 52; 46 : 3 5 8 10 14 16 17 18 19 21 22 24 27 28 30 32 33 35 37 38 39 41 49 51 52; 47 : 2 5 9 11 15 16 17 18 19 20 23 26 27 29 30 32 33 34 36 38 39 40 48 50 51; 48 : 2 3 7 8 12 16 18 20 23 24 25 26 27 30 31 32 35 36 37 39 40 41 43 45 47; 49 : 2 4 9 10 13 16 17 21 22 24 25 26 27 29 31 32 33 34 37 38 40 41 44 45 46; 50 : 4 8 10 11 14 15 19 20 22 23 25 26 27 28 29 31 32 33 35 38 39 42 43 44 47; 51 : 5 6 7 9 12 14 17 19 22 23 24 26 27 28 29 30 34 36 37 39 41 42 44 46 47; 52 : 3 5 6 11 13 15 18 21 22 23 24 25 27 28 30 33 34 35 36 38 40 42 43 45 46; $$ *=10 k=1 1 K=5 -c x a=703e7f6 o=1632828 jcx a=db02f96 o=a5ec37d b=6e007af !Hadamard matrix graph #7 on 96 vertices n=96 $=1 g 1 : 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72; 2 : 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84; 3 : 55 56 57 58 59 60 67 68 69 70 71 72 73 74 75 76 77 78 85 86 87 88 89 90; 4 : 49 50 51 52 53 54 67 68 69 70 71 72 79 80 81 82 83 84 85 86 87 88 89 90; 5 : 52 53 54 58 59 60 64 65 66 70 71 72 73 74 75 79 80 81 85 86 87 91 92 93; 6 : 49 50 51 55 56 57 64 65 66 70 71 72 76 77 78 82 83 84 85 86 87 91 92 93; 7 : 51 52 53 55 56 60 63 64 65 67 68 72 73 74 78 81 82 83 85 86 90 93 94 95; 8 : 50 52 54 55 57 60 62 64 66 67 69 72 73 75 77 80 82 83 85 87 89 92 94 95; 9 : 49 53 54 56 57 60 61 65 66 68 69 72 74 75 76 79 82 83 86 87 88 91 94 95; 10 : 49 51 52 57 58 60 61 63 64 69 70 72 74 77 78 79 80 83 86 89 90 91 92 95; 11 : 50 51 54 56 58 60 62 63 66 68 70 72 73 76 77 79 81 83 85 88 89 91 93 95; 12 : 49 50 53 55 58 60 61 62 65 67 70 72 75 76 78 80 81 83 87 88 90 92 93 95; 13 : 50 51 53 57 59 60 62 63 65 69 71 72 73 76 78 79 80 82 85 88 90 91 92 94; 14 : 49 50 52 56 59 60 61 62 64 68 71 72 75 77 78 79 81 82 87 89 90 91 93 94; 15 : 49 51 54 55 59 60 61 63 66 67 71 72 74 76 77 80 81 82 86 88 89 92 93 94; 16 : 49 50 54 57 58 59 63 64 65 67 68 72 75 76 77 79 80 84 85 86 90 93 94 95; 17 : 49 51 53 56 58 59 62 64 66 67 69 72 74 76 78 79 81 84 85 87 89 92 94 95; 18 : 50 51 52 55 58 59 61 65 66 68 69 72 73 77 78 80 81 84 86 87 88 91 94 95; 19 : 50 53 54 55 56 58 61 63 64 69 71 72 73 75 76 81 83 84 86 89 90 91 92 94; 20 : 49 52 53 55 57 58 62 63 66 68 71 72 74 75 78 80 83 84 85 88 89 91 93 94; 21 : 51 52 54 56 57 58 61 62 65 67 71 72 73 74 77 79 83 84 87 88 90 92 93 94; 22 : 49 52 54 55 56 59 62 63 65 69 70 72 74 75 77 81 82 84 85 88 90 91 92 95; 23 : 51 53 54 55 57 59 61 62 64 68 70 72 73 74 76 80 82 84 87 89 90 91 93 95; 24 : 50 52 53 56 57 59 61 63 66 67 70 72 73 75 78 79 82 84 86 88 89 92 93 95; 25 : 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96; 26 : 49 50 51 52 53 54 55 56 57 58 59 60 85 86 87 88 89 90 91 92 93 94 95 96; 27 : 49 50 51 52 53 54 61 62 63 64 65 66 79 80 81 82 83 84 91 92 93 94 95 96; 28 : 55 56 57 58 59 60 61 62 63 64 65 66 73 74 75 76 77 78 91 92 93 94 95 96; 29 : 49 50 51 55 56 57 61 62 63 67 68 69 76 77 78 82 83 84 88 89 90 94 95 96; 30 : 52 53 54 58 59 60 61 62 63 67 68 69 73 74 75 79 80 81 88 89 90 94 95 96; 31 : 49 50 54 57 58 59 61 62 66 69 70 71 75 76 77 79 80 84 87 88 89 91 92 96; 32 : 49 51 53 56 58 59 61 63 65 68 70 71 74 76 78 79 81 84 86 88 90 91 93 96; 33 : 50 51 52 55 58 59 62 63 64 67 70 71 73 77 78 80 81 84 85 89 90 92 93 96; 34 : 50 53 54 55 56 59 62 65 66 67 68 71 73 75 76 81 82 84 85 87 88 93 94 96; 35 : 49 52 53 55 57 59 61 64 65 67 69 71 74 75 78 80 82 84 86 87 90 92 94 96; 36 : 51 52 54 56 57 59 63 64 66 68 69 71 73 74 77 79 82 84 85 86 89 91 94 96; 37 : 49 52 54 55 56 58 61 64 66 67 68 70 74 75 77 81 83 84 86 87 89 93 95 96; 38 : 51 53 54 55 57 58 63 65 66 67 69 70 73 74 76 80 83 84 85 86 88 92 95 96; 39 : 50 52 53 56 57 58 62 64 65 68 69 70 73 75 78 79 83 84 85 87 90 91 95 96; 40 : 51 52 53 55 56 60 61 62 66 69 70 71 73 74 78 81 82 83 87 88 89 91 92 96; 41 : 50 52 54 55 57 60 61 63 65 68 70 71 73 75 77 80 82 83 86 88 90 91 93 96; 42 : 49 53 54 56 57 60 62 63 64 67 70 71 74 75 76 79 82 83 85 89 90 92 93 96; 43 : 49 51 52 57 59 60 62 65 66 67 68 70 74 77 78 79 80 82 85 87 88 93 95 96; 44 : 50 51 54 56 59 60 61 64 65 67 69 70 73 76 77 79 81 82 86 87 90 92 95 96; 45 : 49 50 53 55 59 60 63 64 66 68 69 70 75 76 78 80 81 82 85 86 89 91 95 96; 46 : 50 51 53 57 58 60 61 64 66 67 68 71 73 76 78 79 80 83 86 87 89 93 94 96; 47 : 49 50 52 56 58 60 63 65 66 67 69 71 75 77 78 79 81 83 85 86 88 92 94 96; 48 : 49 51 54 55 58 60 62 64 65 68 69 71 74 76 77 80 81 83 85 87 90 91 94 96; 49 : 1 4 6 9 10 12 14 15 16 17 20 22 26 27 29 31 32 35 37 42 43 45 47 48; 50 : 1 4 6 8 11 12 13 14 16 18 19 24 26 27 29 31 33 34 39 41 44 45 46 47; 51 : 1 4 6 7 10 11 13 15 17 18 21 23 26 27 29 32 33 36 38 40 43 44 46 48; 52 : 1 4 5 7 8 10 14 18 20 21 22 24 26 27 30 33 35 36 37 39 40 41 43 47; 53 : 1 4 5 7 9 12 13 17 19 20 23 24 26 27 30 32 34 35 38 39 40 42 45 46; 54 : 1 4 5 8 9 11 15 16 19 21 22 23 26 27 30 31 34 36 37 38 41 42 44 48; 55 : 1 3 6 7 8 12 15 18 19 20 22 23 26 28 29 33 34 35 37 38 40 41 45 48; 56 : 1 3 6 7 9 11 14 17 19 21 22 24 26 28 29 32 34 36 37 39 40 42 44 47; 57 : 1 3 6 8 9 10 13 16 20 21 23 24 26 28 29 31 35 36 38 39 41 42 43 46; 58 : 1 3 5 10 11 12 16 17 18 19 20 21 26 28 30 31 32 33 37 38 39 46 47 48; 59 : 1 3 5 13 14 15 16 17 18 22 23 24 26 28 30 31 32 33 34 35 36 43 44 45; 60 : 1 3 5 7 8 9 10 11 12 13 14 15 26 28 30 40 41 42 43 44 45 46 47 48; 61 : 1 2 9 10 12 14 15 18 19 21 23 24 27 28 29 30 31 32 35 37 40 41 44 46; 62 : 1 2 8 11 12 13 14 17 20 21 22 23 27 28 29 30 31 33 34 39 40 42 43 48; 63 : 1 2 7 10 11 13 15 16 19 20 22 24 27 28 29 30 32 33 36 38 41 42 45 47; 64 : 1 2 5 6 7 8 10 14 16 17 19 23 27 28 33 35 36 37 39 42 44 45 46 48; 65 : 1 2 5 6 7 9 12 13 16 18 21 22 27 28 32 34 35 38 39 41 43 44 47 48; 66 : 1 2 5 6 8 9 11 15 17 18 20 24 27 28 31 34 36 37 38 40 43 45 46 47; 67 : 1 2 3 4 7 8 12 15 16 17 21 24 29 30 33 34 35 37 38 42 43 44 46 47; 68 : 1 2 3 4 7 9 11 14 16 18 20 23 29 30 32 34 36 37 39 41 43 45 46 48; 69 : 1 2 3 4 8 9 10 13 17 18 19 22 29 30 31 35 36 38 39 40 44 45 47 48; 70 : 1 2 3 4 5 6 10 11 12 22 23 24 31 32 33 37 38 39 40 41 42 43 44 45; 71 : 1 2 3 4 5 6 13 14 15 19 20 21 31 32 33 34 35 36 40 41 42 46 47 48; 72 : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; 73 : 2 3 5 7 8 11 13 18 19 21 23 24 25 28 30 33 34 36 38 39 40 41 44 46; 74 : 2 3 5 7 9 10 15 17 20 21 22 23 25 28 30 32 35 36 37 38 40 42 43 48; 75 : 2 3 5 8 9 12 14 16 19 20 22 24 25 28 30 31 34 35 37 39 41 42 45 47; 76 : 2 3 6 9 11 12 13 15 16 17 19 23 25 28 29 31 32 34 38 42 44 45 46 48; 77 : 2 3 6 8 10 11 14 15 16 18 21 22 25 28 29 31 33 36 37 41 43 44 47 48; 78 : 2 3 6 7 10 12 13 14 17 18 20 24 25 28 29 32 33 35 39 40 43 45 46 47; 79 : 2 4 5 9 10 11 13 14 16 17 21 24 25 27 30 31 32 36 39 42 43 44 46 47; 80 : 2 4 5 8 10 12 13 15 16 18 20 23 25 27 30 31 33 35 38 41 43 45 46 48; 81 : 2 4 5 7 11 12 14 15 17 18 19 22 25 27 30 32 33 34 37 40 44 45 47 48; 82 : 2 4 6 7 8 9 13 14 15 22 23 24 25 27 29 34 35 36 40 41 42 43 44 45; 83 : 2 4 6 7 8 9 10 11 12 19 20 21 25 27 29 37 38 39 40 41 42 46 47 48; 84 : 2 4 6 16 17 18 19 20 21 22 23 24 25 27 29 31 32 33 34 35 36 37 38 39; 85 : 3 4 5 6 7 8 11 13 16 17 20 22 25 26 33 34 36 38 39 42 43 45 47 48; 86 : 3 4 5 6 7 9 10 15 16 18 19 24 25 26 32 35 36 37 38 41 44 45 46 47; 87 : 3 4 5 6 8 9 12 14 17 18 21 23 25 26 31 34 35 37 39 40 43 44 46 48; 88 : 3 4 9 11 12 13 15 18 20 21 22 24 25 26 29 30 31 32 34 38 40 41 43 47; 89 : 3 4 8 10 11 14 15 17 19 20 23 24 25 26 29 30 31 33 36 37 40 42 45 46; 90 : 3 4 7 10 12 13 14 16 19 21 22 23 25 26 29 30 32 33 35 39 41 42 44 48; 91 : 5 6 9 10 11 13 14 18 19 20 22 23 25 26 27 28 31 32 36 39 40 41 45 48; 92 : 5 6 8 10 12 13 15 17 19 21 22 24 25 26 27 28 31 33 35 38 40 42 44 47; 93 : 5 6 7 11 12 14 15 16 20 21 23 24 25 26 27 28 32 33 34 37 41 42 43 46; 94 : 7 8 9 13 14 15 16 17 18 19 20 21 25 26 27 28 29 30 34 35 36 46 47 48; 95 : 7 8 9 10 11 12 16 17 18 22 23 24 25 26 27 28 29 30 37 38 39 43 44 45; 96 : 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48; $$ *=6 k=2 2 K=0 -c x a=9dddf99 o=9532ebc jcx a=775a4c2 o=af10220 b=fe3fd33 !Hadamard matrix graph #8 on 96 vertices n=96 $=1 g 1 : 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72; 2 : 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84; 3 : 55 56 57 58 59 60 67 68 69 70 71 72 73 74 75 76 77 78 85 86 87 88 89 90; 4 : 49 50 51 52 53 54 67 68 69 70 71 72 79 80 81 82 83 84 85 86 87 88 89 90; 5 : 52 53 54 58 59 60 64 65 66 70 71 72 73 74 75 79 80 81 85 86 87 91 92 93; 6 : 49 50 51 55 56 57 64 65 66 70 71 72 76 77 78 82 83 84 85 86 87 91 92 93; 7 : 49 50 54 57 58 59 61 62 66 69 70 71 75 76 77 79 80 84 87 88 89 91 92 96; 8 : 49 51 53 56 58 59 61 63 65 68 70 71 74 76 78 79 81 84 86 88 90 91 93 96; 9 : 50 51 52 55 58 59 62 63 64 67 70 71 73 77 78 80 81 84 85 89 90 92 93 96; 10 : 50 51 53 57 58 60 61 63 64 69 70 72 73 76 78 79 80 83 86 89 90 91 92 95; 11 : 49 50 52 56 58 60 62 63 66 68 70 72 75 77 78 79 81 83 85 88 89 91 93 95; 12 : 49 51 54 55 58 60 61 62 65 67 70 72 74 76 77 80 81 83 87 88 90 92 93 95; 13 : 49 51 52 57 59 60 62 63 65 69 71 72 74 77 78 79 80 82 85 88 90 91 92 94; 14 : 50 51 54 56 59 60 61 62 64 68 71 72 73 76 77 79 81 82 87 89 90 91 93 94; 15 : 49 50 53 55 59 60 61 63 66 67 71 72 75 76 78 80 81 82 86 88 89 92 93 94; 16 : 51 52 53 55 56 60 61 62 66 69 70 71 73 74 78 81 82 83 87 88 89 91 92 96; 17 : 50 52 54 56 57 60 61 63 65 67 70 71 73 75 77 79 82 83 86 88 90 92 93 96; 18 : 49 53 54 55 57 60 62 63 64 68 70 71 74 75 76 80 82 83 85 89 90 91 93 96; 19 : 49 52 54 55 56 58 61 63 64 69 71 72 74 75 77 81 83 84 86 89 90 91 92 94; 20 : 51 52 54 55 57 59 61 63 66 68 70 72 73 74 77 80 82 84 86 88 89 91 93 95; 21 : 49 52 53 56 57 59 61 62 64 67 70 72 74 75 78 79 82 84 87 89 90 92 93 95; 22 : 50 53 54 55 56 59 62 63 65 69 70 72 73 75 76 81 82 84 85 88 90 91 92 95; 23 : 50 52 53 55 57 58 61 62 65 68 71 72 73 75 78 80 83 84 87 88 90 91 93 94; 24 : 51 53 54 56 57 58 62 63 66 67 71 72 73 74 76 79 83 84 85 88 89 92 93 94; 25 : 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96; 26 : 49 50 51 52 53 54 55 56 57 58 59 60 85 86 87 88 89 90 91 92 93 94 95 96; 27 : 49 50 51 52 53 54 61 62 63 64 65 66 79 80 81 82 83 84 91 92 93 94 95 96; 28 : 55 56 57 58 59 60 61 62 63 64 65 66 73 74 75 76 77 78 91 92 93 94 95 96; 29 : 49 50 51 55 56 57 61 62 63 67 68 69 76 77 78 82 83 84 88 89 90 94 95 96; 30 : 52 53 54 58 59 60 61 62 63 67 68 69 73 74 75 79 80 81 88 89 90 94 95 96; 31 : 51 52 53 55 56 60 63 64 65 67 68 72 73 74 78 81 82 83 85 86 90 93 94 95; 32 : 50 52 54 55 57 60 62 64 66 67 69 72 73 75 77 80 82 83 85 87 89 92 94 95; 33 : 49 53 54 56 57 60 61 65 66 68 69 72 74 75 76 79 82 83 86 87 88 91 94 95; 34 : 49 52 54 55 56 59 62 65 66 67 68 71 74 75 77 81 82 84 85 87 88 93 94 96; 35 : 51 53 54 55 57 59 61 64 65 67 69 71 73 74 76 80 82 84 86 87 90 92 94 96; 36 : 50 52 53 56 57 59 63 64 66 68 69 71 73 75 78 79 82 84 85 86 89 91 94 96; 37 : 50 53 54 55 56 58 61 64 66 67 68 70 73 75 76 81 83 84 86 87 89 93 95 96; 38 : 49 52 53 55 57 58 63 65 66 67 69 70 74 75 78 80 83 84 85 86 88 92 95 96; 39 : 51 52 54 56 57 58 62 64 65 68 69 70 73 74 77 79 83 84 85 87 90 91 95 96; 40 : 49 50 54 57 58 59 63 64 65 67 68 72 75 76 77 79 80 84 85 86 90 93 94 95; 41 : 49 51 53 55 58 59 62 64 66 68 69 72 74 76 78 80 81 84 85 87 89 91 94 95; 42 : 50 51 52 56 58 59 61 65 66 67 69 72 73 77 78 79 81 84 86 87 88 92 94 95; 43 : 50 51 53 57 59 60 62 65 66 67 68 70 73 76 78 79 80 82 85 87 88 93 95 96; 44 : 49 50 53 56 58 60 62 64 65 67 69 71 75 76 78 79 81 83 85 87 90 92 94 96; 45 : 50 51 54 55 58 60 63 65 66 68 69 71 73 76 77 80 81 83 85 86 88 91 94 96; 46 : 49 51 52 57 58 60 61 64 66 67 68 71 74 77 78 79 80 83 86 87 89 93 94 96; 47 : 49 51 54 56 59 60 63 64 66 67 69 70 74 76 77 79 81 82 85 86 89 92 95 96; 48 : 49 50 52 55 59 60 61 64 65 68 69 70 75 77 78 80 81 82 86 87 90 91 95 96; 49 : 1 4 6 7 8 11 12 13 15 18 19 21 26 27 29 33 34 38 40 41 44 46 47 48; 50 : 1 4 6 7 9 10 11 14 15 17 22 23 26 27 29 32 36 37 40 42 43 44 45 48; 51 : 1 4 6 8 9 10 12 13 14 16 20 24 26 27 29 31 35 39 41 42 43 45 46 47; 52 : 1 4 5 9 11 13 16 17 19 20 21 23 26 27 30 31 32 34 36 38 39 42 46 48; 53 : 1 4 5 8 10 15 16 18 21 22 23 24 26 27 30 31 33 35 36 37 38 41 43 44; 54 : 1 4 5 7 12 14 17 18 19 20 22 24 26 27 30 32 33 34 35 37 39 40 45 47; 55 : 1 3 6 9 12 15 16 18 19 20 22 23 26 28 29 31 32 34 35 37 38 41 45 48; 56 : 1 3 6 8 11 14 16 17 19 21 22 24 26 28 29 31 33 34 36 37 39 42 44 47; 57 : 1 3 6 7 10 13 17 18 20 21 23 24 26 28 29 32 33 35 36 38 39 40 43 46; 58 : 1 3 5 7 8 9 10 11 12 19 23 24 26 28 30 37 38 39 40 41 42 44 45 46; 59 : 1 3 5 7 8 9 13 14 15 20 21 22 26 28 30 34 35 36 40 41 42 43 47 48; 60 : 1 3 5 10 11 12 13 14 15 16 17 18 26 28 30 31 32 33 43 44 45 46 47 48; 61 : 1 2 7 8 10 12 14 15 16 17 19 20 21 23 27 28 29 30 33 35 37 42 46 48; 62 : 1 2 7 9 11 12 13 14 16 18 21 22 23 24 27 28 29 30 32 34 39 41 43 44; 63 : 1 2 8 9 10 11 13 15 17 18 19 20 22 24 27 28 29 30 31 36 38 40 45 47; 64 : 1 2 5 6 9 10 14 18 19 21 27 28 31 32 35 36 37 39 40 41 44 46 47 48; 65 : 1 2 5 6 8 12 13 17 22 23 27 28 31 33 34 35 38 39 40 42 43 44 45 48; 66 : 1 2 5 6 7 11 15 16 20 24 27 28 32 33 34 36 37 38 41 42 43 45 46 47; 67 : 1 2 3 4 9 12 15 17 21 24 29 30 31 32 34 35 37 38 40 42 43 44 46 47; 68 : 1 2 3 4 8 11 14 18 20 23 29 30 31 33 34 36 37 39 40 41 43 45 46 48; 69 : 1 2 3 4 7 10 13 16 19 22 29 30 32 33 35 36 38 39 41 42 44 45 47 48; 70 : 1 2 3 4 5 6 7 8 9 10 11 12 16 17 18 20 21 22 37 38 39 43 47 48; 71 : 1 2 3 4 5 6 7 8 9 13 14 15 16 17 18 19 23 24 34 35 36 44 45 46; 72 : 1 2 3 4 5 6 10 11 12 13 14 15 19 20 21 22 23 24 31 32 33 40 41 42; 73 : 2 3 5 9 10 14 16 17 20 22 23 24 25 28 30 31 32 35 36 37 39 42 43 45; 74 : 2 3 5 8 12 13 16 18 19 20 21 24 25 28 30 31 33 34 35 38 39 41 46 47; 75 : 2 3 5 7 11 15 17 18 19 21 22 23 25 28 30 32 33 34 36 37 38 40 44 48; 76 : 2 3 6 7 8 10 12 14 15 18 22 24 25 28 29 33 35 37 40 41 43 44 45 47; 77 : 2 3 6 7 9 11 12 13 14 17 19 20 25 28 29 32 34 39 40 42 45 46 47 48; 78 : 2 3 6 8 9 10 11 13 15 16 21 23 25 28 29 31 36 38 41 42 43 44 46 48; 79 : 2 4 5 7 8 10 11 13 14 17 21 24 25 27 30 33 36 39 40 42 43 44 46 47; 80 : 2 4 5 7 9 10 12 13 15 18 20 23 25 27 30 32 35 38 40 41 43 45 46 48; 81 : 2 4 5 8 9 11 12 14 15 16 19 22 25 27 30 31 34 37 41 42 44 45 47 48; 82 : 2 4 6 13 14 15 16 17 18 20 21 22 25 27 29 31 32 33 34 35 36 43 47 48; 83 : 2 4 6 10 11 12 16 17 18 19 23 24 25 27 29 31 32 33 37 38 39 44 45 46; 84 : 2 4 6 7 8 9 19 20 21 22 23 24 25 27 29 34 35 36 37 38 39 40 41 42; 85 : 3 4 5 6 9 11 13 18 22 24 25 26 31 32 34 36 38 39 40 41 43 44 45 47; 86 : 3 4 5 6 8 10 15 17 19 20 25 26 31 33 35 36 37 38 40 42 45 46 47 48; 87 : 3 4 5 6 7 12 14 16 21 23 25 26 32 33 34 35 37 39 41 42 43 44 46 48; 88 : 3 4 7 8 11 12 13 15 16 17 20 22 23 24 25 26 29 30 33 34 38 42 43 45; 89 : 3 4 7 9 10 11 14 15 16 18 19 20 21 24 25 26 29 30 32 36 37 41 46 47; 90 : 3 4 8 9 10 12 13 14 17 18 19 21 22 23 25 26 29 30 31 35 39 40 44 48; 91 : 5 6 7 8 10 11 13 14 16 18 19 20 22 23 25 26 27 28 33 36 39 41 45 48; 92 : 5 6 7 9 10 12 13 15 16 17 19 21 22 24 25 26 27 28 32 35 38 42 44 47; 93 : 5 6 8 9 11 12 14 15 17 18 20 21 23 24 25 26 27 28 31 34 37 40 43 46; 94 : 13 14 15 19 23 24 25 26 27 28 29 30 31 32 33 34 35 36 40 41 42 44 45 46; 95 : 10 11 12 20 21 22 25 26 27 28 29 30 31 32 33 37 38 39 40 41 42 43 47 48; 96 : 7 8 9 16 17 18 25 26 27 28 29 30 34 35 36 37 38 39 43 44 45 46 47 48; $$ *=6 k=2 2 -c x a=1d9d85b o=56ed631 jcx a=8144944 o=2db9a03 b=787caae !2-(91,10,1) design #2 n=182 $=1 g 1 : 92 101 110 119 128 137 146 155 164 173; 2 : 92 102 111 120 129 138 147 156 165 174; 3 : 92 103 112 121 130 139 148 157 166 175; 4 : 92 104 113 122 131 140 149 158 167 176; 5 : 92 105 114 123 132 141 150 159 168 177; 6 : 92 106 115 124 133 142 151 160 169 178; 7 : 92 107 116 125 134 143 152 161 170 179; 8 : 92 108 117 126 135 144 153 162 171 180; 9 : 92 109 118 127 136 145 154 163 172 181; 10 : 93 101 112 120 134 145 153 158 169 177; 11 : 93 102 110 121 135 143 154 159 167 178; 12 : 93 103 111 119 136 144 152 160 168 176; 13 : 93 104 115 123 128 139 147 161 172 180; 14 : 93 105 113 124 129 137 148 162 170 181; 15 : 93 106 114 122 130 138 146 163 171 179; 16 : 93 107 118 126 131 142 150 155 166 174; 17 : 93 108 116 127 132 140 151 156 164 175; 18 : 93 109 117 125 133 141 149 157 165 173; 19 : 94 101 111 121 131 141 151 161 171 181; 20 : 94 102 112 119 132 142 149 162 172 179; 21 : 94 103 110 120 133 140 150 163 170 180; 22 : 94 104 114 124 134 144 154 155 165 175; 23 : 94 105 115 122 135 145 152 156 166 173; 24 : 94 106 113 123 136 143 153 157 164 174; 25 : 94 107 117 127 128 138 148 158 168 178; 26 : 94 108 118 125 129 139 146 159 169 176; 27 : 94 109 116 126 130 137 147 160 167 177; 28 : 95 101 116 122 129 142 154 157 168 180; 29 : 95 102 117 123 130 140 152 155 169 181; 30 : 95 103 118 124 128 141 153 156 167 179; 31 : 95 104 110 125 132 145 148 160 171 174; 32 : 95 105 111 126 133 143 146 158 172 175; 33 : 95 106 112 127 131 144 147 159 170 173; 34 : 95 107 113 119 135 139 151 163 165 177; 35 : 95 108 114 120 136 137 149 161 166 178; 36 : 95 109 115 121 134 138 150 162 164 176; 37 : 96 101 118 123 135 138 149 160 170 175; 38 : 96 102 116 124 136 139 150 158 171 173; 39 : 96 103 117 122 134 137 151 159 172 174; 40 : 96 104 112 126 129 141 152 163 164 178; 41 : 96 105 110 127 130 142 153 161 165 176; 42 : 96 106 111 125 128 140 154 162 166 177; 43 : 96 107 115 120 132 144 146 157 167 181; 44 : 96 108 113 121 133 145 147 155 168 179; 45 : 96 109 114 119 131 143 148 156 169 180; 46 : 97 101 117 124 132 143 147 163 166 176; 47 : 97 102 118 122 133 144 148 161 164 177; 48 : 97 103 116 123 131 145 146 162 165 178; 49 : 97 104 111 127 135 137 150 157 169 179; 50 : 97 105 112 125 136 138 151 155 167 180; 51 : 97 106 110 126 134 139 149 156 168 181; 52 : 97 107 114 121 129 140 153 160 172 173; 53 : 97 108 115 119 130 141 154 158 170 174; 54 : 97 109 113 120 128 142 152 159 171 175; 55 : 98 101 113 125 130 144 150 156 172 178; 56 : 98 102 114 126 128 145 151 157 170 176; 57 : 98 103 115 127 129 143 149 155 171 177; 58 : 98 104 116 119 133 138 153 159 166 181; 59 : 98 105 117 120 131 139 154 160 164 179; 60 : 98 106 118 121 132 137 152 158 165 180; 61 : 98 107 110 122 136 141 147 162 169 175; 62 : 98 108 111 123 134 142 148 163 167 173; 63 : 98 109 112 124 135 140 146 161 168 174; 64 : 99 101 115 126 136 140 148 159 165 179; 65 : 99 102 113 127 134 141 146 160 166 180; 66 : 99 103 114 125 135 142 147 158 164 181; 67 : 99 104 118 120 130 143 151 162 168 173; 68 : 99 105 116 121 128 144 149 163 169 174; 69 : 99 106 117 119 129 145 150 161 167 175; 70 : 99 107 112 123 133 137 154 156 171 176; 71 : 99 108 110 124 131 138 152 157 172 177; 72 : 99 109 111 122 132 139 153 155 170 178; 73 : 100 101 114 127 133 139 152 162 167 174; 74 : 100 102 115 125 131 137 153 163 168 175; 75 : 100 103 113 126 132 138 154 161 169 173; 76 : 100 104 117 121 136 142 146 156 170 177; 77 : 100 105 118 119 134 140 147 157 171 178; 78 : 100 106 116 120 135 141 148 155 172 176; 79 : 100 107 111 124 130 145 149 159 164 180; 80 : 100 108 112 122 128 143 150 160 165 181; 81 : 100 109 110 123 129 144 151 158 166 179; 82 : 92 93 94 95 96 97 98 99 100 182; 83 : 101 102 103 104 105 106 107 108 109 182; 84 : 110 111 112 113 114 115 116 117 118 182; 85 : 119 120 121 122 123 124 125 126 127 182; 86 : 128 129 130 131 132 133 134 135 136 182; 87 : 137 138 139 140 141 142 143 144 145 182; 88 : 146 147 148 149 150 151 152 153 154 182; 89 : 155 156 157 158 159 160 161 162 163 182; 90 : 164 165 166 167 168 169 170 171 172 182; 91 : 173 174 175 176 177 178 179 180 181 182; 92 : 1 2 3 4 5 6 7 8 9 82; 93 : 10 11 12 13 14 15 16 17 18 82; 94 : 19 20 21 22 23 24 25 26 27 82; 95 : 28 29 30 31 32 33 34 35 36 82; 96 : 37 38 39 40 41 42 43 44 45 82; 97 : 46 47 48 49 50 51 52 53 54 82; 98 : 55 56 57 58 59 60 61 62 63 82; 99 : 64 65 66 67 68 69 70 71 72 82; 100 : 73 74 75 76 77 78 79 80 81 82; 101 : 1 10 19 28 37 46 55 64 73 83; 102 : 2 11 20 29 38 47 56 65 74 83; 103 : 3 12 21 30 39 48 57 66 75 83; 104 : 4 13 22 31 40 49 58 67 76 83; 105 : 5 14 23 32 41 50 59 68 77 83; 106 : 6 15 24 33 42 51 60 69 78 83; 107 : 7 16 25 34 43 52 61 70 79 83; 108 : 8 17 26 35 44 53 62 71 80 83; 109 : 9 18 27 36 45 54 63 72 81 83; 110 : 1 11 21 31 41 51 61 71 81 84; 111 : 2 12 19 32 42 49 62 72 79 84; 112 : 3 10 20 33 40 50 63 70 80 84; 113 : 4 14 24 34 44 54 55 65 75 84; 114 : 5 15 22 35 45 52 56 66 73 84; 115 : 6 13 23 36 43 53 57 64 74 84; 116 : 7 17 27 28 38 48 58 68 78 84; 117 : 8 18 25 29 39 46 59 69 76 84; 118 : 9 16 26 30 37 47 60 67 77 84; 119 : 1 12 20 34 45 53 58 69 77 85; 120 : 2 10 21 35 43 54 59 67 78 85; 121 : 3 11 19 36 44 52 60 68 76 85; 122 : 4 15 23 28 39 47 61 72 80 85; 123 : 5 13 24 29 37 48 62 70 81 85; 124 : 6 14 22 30 38 46 63 71 79 85; 125 : 7 18 26 31 42 50 55 66 74 85; 126 : 8 16 27 32 40 51 56 64 75 85; 127 : 9 17 25 33 41 49 57 65 73 85; 128 : 1 13 25 30 42 54 56 68 80 86; 129 : 2 14 26 28 40 52 57 69 81 86; 130 : 3 15 27 29 41 53 55 67 79 86; 131 : 4 16 19 33 45 48 59 71 74 86; 132 : 5 17 20 31 43 46 60 72 75 86; 133 : 6 18 21 32 44 47 58 70 73 86; 134 : 7 10 22 36 39 51 62 65 77 86; 135 : 8 11 23 34 37 49 63 66 78 86; 136 : 9 12 24 35 38 50 61 64 76 86; 137 : 1 14 27 35 39 49 60 70 74 87; 138 : 2 15 25 36 37 50 58 71 75 87; 139 : 3 13 26 34 38 51 59 72 73 87; 140 : 4 17 21 29 42 52 63 64 77 87; 141 : 5 18 19 30 40 53 61 65 78 87; 142 : 6 16 20 28 41 54 62 66 76 87; 143 : 7 11 24 32 45 46 57 67 80 87; 144 : 8 12 22 33 43 47 55 68 81 87; 145 : 9 10 23 31 44 48 56 69 79 87; 146 : 1 15 26 32 43 48 63 65 76 88; 147 : 2 13 27 33 44 46 61 66 77 88; 148 : 3 14 25 31 45 47 62 64 78 88; 149 : 4 18 20 35 37 51 57 68 79 88; 150 : 5 16 21 36 38 49 55 69 80 88; 151 : 6 17 19 34 39 50 56 67 81 88; 152 : 7 12 23 29 40 54 60 71 73 88; 153 : 8 10 24 30 41 52 58 72 74 88; 154 : 9 11 22 28 42 53 59 70 75 88; 155 : 1 16 22 29 44 50 57 72 78 89; 156 : 2 17 23 30 45 51 55 70 76 89; 157 : 3 18 24 28 43 49 56 71 77 89; 158 : 4 10 25 32 38 53 60 66 81 89; 159 : 5 11 26 33 39 54 58 64 79 89; 160 : 6 12 27 31 37 52 59 65 80 89; 161 : 7 13 19 35 41 47 63 69 75 89; 162 : 8 14 20 36 42 48 61 67 73 89; 163 : 9 15 21 34 40 46 62 68 74 89; 164 : 1 17 24 36 40 47 59 66 79 90; 165 : 2 18 22 34 41 48 60 64 80 90; 166 : 3 16 23 35 42 46 58 65 81 90; 167 : 4 11 27 30 43 50 62 69 73 90; 168 : 5 12 25 28 44 51 63 67 74 90; 169 : 6 10 26 29 45 49 61 68 75 90; 170 : 7 14 21 33 37 53 56 72 76 90; 171 : 8 15 19 31 38 54 57 70 77 90; 172 : 9 13 20 32 39 52 55 71 78 90; 173 : 1 18 23 33 38 52 62 67 75 91; 174 : 2 16 24 31 39 53 63 68 73 91; 175 : 3 17 22 32 37 54 61 69 74 91; 176 : 4 12 26 36 41 46 56 70 78 91; 177 : 5 10 27 34 42 47 57 71 76 91; 178 : 6 11 25 35 40 48 55 72 77 91; 179 : 7 15 20 30 44 49 59 64 81 91; 180 : 8 13 21 28 45 50 60 65 79 91; 181 : 9 14 19 29 43 51 58 66 80 91; 182 : 82 83 84 85 86 87 88 89 90 91; $$ *=15 k=2 2 -c x a=6e86f1a o=bc7cabe cjx a=4567ab6 o=3309683 b=43ffcaf !Third and nastiest Levi graph of projective plane n=182 $=1 g 1 : 97 98 101 103 114 127 140 153 166 179; 2 : 98 99 102 104 115 128 141 154 167 180; 3 : 94 95 98 100 111 124 137 150 163 176; 4 : 92 93 96 98 109 122 135 148 161 174; 5 : 98 106 107 126 129 134 143 144 149 151; 6 : 98 108 117 119 120 139 142 170 175 177; 7 : 98 113 116 121 130 132 133 157 162 164; 8 : 98 105 110 112 145 146 165 168 173 182; 9 : 98 131 136 138 147 156 158 159 178 181; 10 : 98 118 123 125 152 155 160 169 171 172; 11 : 95 96 99 101 112 125 138 151 164 177; 12 : 93 100 101 104 117 130 143 156 169 182; 13 : 92 94 101 102 105 118 131 144 157 170; 14 : 101 109 110 119 129 133 137 147 152 154; 15 : 101 107 111 122 123 132 142 173 178 180; 16 : 101 106 116 120 124 135 136 160 165 167; 17 : 101 108 113 115 148 149 158 168 172 176; 18 : 101 134 139 141 146 150 161 162 171 181; 19 : 101 121 126 128 145 155 159 163 174 175; 20 : 93 94 97 99 110 123 136 149 162 175; 21 : 92 95 97 104 108 121 134 147 160 173; 22 : 96 97 100 102 113 126 139 152 165 178; 23 : 97 122 124 130 151 154 159 168 170 171; 24 : 97 135 137 143 146 155 157 158 177 180; 25 : 97 109 111 117 144 145 164 167 172 181; 26 : 97 112 115 120 129 131 132 161 163 169; 27 : 97 107 116 118 119 138 141 174 176 182; 28 : 97 105 106 125 128 133 142 148 150 156; 29 : 92 99 100 103 116 129 142 155 168 181; 30 : 94 96 103 104 107 120 133 146 159 172; 31 : 93 95 102 103 106 119 132 145 158 171; 32 : 103 111 112 118 121 135 139 149 154 156; 33 : 103 109 113 124 125 131 134 175 180 182; 34 : 103 105 108 122 126 137 138 162 167 169; 35 : 103 110 115 117 150 151 157 160 174 178; 36 : 103 136 141 143 148 152 163 164 170 173; 37 : 103 123 128 130 144 147 161 165 176 177; 38 : 99 105 109 120 121 140 143 171 176 178; 39 : 104 112 113 119 122 136 140 144 150 155; 40 : 102 135 140 142 147 151 162 163 172 182; 41 : 95 116 117 123 126 131 140 146 148 154; 42 : 100 133 138 140 145 149 160 161 170 180; 43 : 94 132 134 140 152 156 167 168 174 177; 44 : 96 106 115 118 130 137 140 173 175 181; 45 : 93 108 111 125 129 140 141 157 159 165; 46 : 92 107 110 124 128 139 140 158 164 169; 47 : 99 114 117 118 122 133 134 158 163 165; 48 : 104 110 114 125 126 132 135 170 176 181; 49 : 102 109 114 116 149 150 159 169 173 177; 50 : 94 106 108 114 154 155 161 164 178 182; 51 : 95 105 114 129 130 136 139 172 174 180; 52 : 100 107 112 114 147 148 157 167 171 175; 53 : 93 114 115 121 124 138 142 144 146 152; 54 : 92 113 114 120 123 137 141 145 151 156; 55 : 96 111 114 119 128 131 143 160 162 168; 56 : 99 107 108 127 130 131 135 145 150 152; 57 : 104 106 109 123 127 138 139 157 163 168; 58 : 102 122 127 129 146 156 160 164 175 176; 59 : 100 120 125 127 144 154 158 162 173 174; 60 : 94 119 121 127 148 151 165 169 180 181; 61 : 95 110 113 118 127 142 143 159 161 167; 62 : 92 111 115 126 127 133 136 171 177 182; 63 : 96 105 117 124 127 132 141 147 149 155; 64 : 93 112 116 127 128 134 137 170 172 178; 65 : 99 132 137 139 144 148 159 160 179 182; 66 : 104 105 111 116 151 152 158 161 175 179; 67 : 102 108 112 123 124 133 143 174 179 181; 68 : 96 134 136 142 145 154 157 169 176 179; 69 : 93 118 120 126 147 150 164 168 179 180; 70 : 92 119 125 130 146 149 163 167 178 179; 71 : 95 107 109 115 155 156 162 165 170 179; 72 : 100 106 110 121 122 131 141 172 177 179; 73 : 94 113 117 128 129 135 138 171 173 179; 74 : 99 119 124 126 153 156 157 161 172 173; 75 : 104 131 137 142 149 153 164 165 171 174; 76 : 102 110 111 120 130 134 138 148 153 155; 77 : 93 105 107 113 153 154 160 163 177 181; 78 : 92 106 112 117 152 153 159 162 176 180; 79 : 96 121 123 129 150 153 158 167 170 182; 80 : 94 115 116 122 125 139 143 145 147 153; 81 : 95 133 135 141 144 153 168 169 175 178; 82 : 100 108 109 118 128 132 136 146 151 153; 83 : 99 106 111 113 146 147 166 169 170 174; 84 : 104 118 124 129 145 148 162 166 177 178; 85 : 102 107 117 121 125 136 137 161 166 168; 86 : 92 132 138 143 150 154 165 166 172 175; 87 : 96 108 110 116 144 156 163 166 171 180; 88 : 93 131 133 139 151 155 166 167 173 176; 89 : 100 105 115 119 123 134 135 159 164 166; 90 : 94 109 112 126 130 141 142 158 160 166; 91 : 95 120 122 128 149 152 157 166 181 182; 92 : 4 13 21 29 46 54 62 70 78 86; 93 : 4 12 20 31 45 53 64 69 77 88; 94 : 3 13 20 30 43 50 60 73 80 90; 95 : 3 11 21 31 41 51 61 71 81 91; 96 : 4 11 22 30 44 55 63 68 79 87; 97 : 1 20 21 22 23 24 25 26 27 28; 98 : 1 2 3 4 5 6 7 8 9 10; 99 : 2 11 20 29 38 47 56 65 74 83; 100 : 3 12 22 29 42 52 59 72 82 89; 101 : 1 11 12 13 14 15 16 17 18 19; 102 : 2 13 22 31 40 49 58 67 76 85; 103 : 1 29 30 31 32 33 34 35 36 37; 104 : 2 12 21 30 39 48 57 66 75 84; 105 : 8 13 28 34 38 51 63 66 77 89; 106 : 5 16 28 31 44 50 57 72 78 83; 107 : 5 15 27 30 46 52 56 71 77 85; 108 : 6 17 21 34 45 50 56 67 82 87; 109 : 4 14 25 33 38 49 57 71 82 90; 110 : 8 14 20 35 46 48 61 72 76 87; 111 : 3 15 25 32 45 55 62 66 76 83; 112 : 8 11 26 32 39 52 64 67 78 90; 113 : 7 17 22 33 39 54 61 73 77 83; 114 : 1 47 48 49 50 51 52 53 54 55; 115 : 2 17 26 35 44 53 62 71 80 89; 116 : 7 16 27 29 41 49 64 66 80 87; 117 : 6 12 25 35 41 47 63 73 78 85; 118 : 10 13 27 32 44 47 61 69 82 84; 119 : 6 14 27 31 39 55 60 70 74 89; 120 : 6 16 26 30 38 54 59 69 76 91; 121 : 7 19 21 32 38 53 60 72 79 85; 122 : 4 15 23 34 39 47 58 72 80 91; 123 : 10 15 20 37 41 54 57 67 79 89; 124 : 3 16 23 33 46 53 63 67 74 84; 125 : 10 11 28 33 45 48 59 70 80 85; 126 : 5 19 22 34 41 48 62 69 74 90; 127 : 1 56 57 58 59 60 61 62 63 64; 128 : 2 19 28 37 46 55 64 73 82 91; 129 : 5 14 26 29 45 51 58 73 79 84; 130 : 7 12 23 37 44 51 56 70 76 90; 131 : 9 13 26 33 41 55 56 72 75 88; 132 : 7 15 26 31 43 48 63 65 82 86; 133 : 7 14 28 30 42 47 62 67 81 88; 134 : 5 18 21 33 43 47 64 68 76 89; 135 : 4 16 24 32 40 48 56 73 81 89; 136 : 9 16 20 36 39 51 62 68 82 85; 137 : 3 14 24 34 44 54 64 65 75 85; 138 : 9 11 27 34 42 53 57 73 76 86; 139 : 6 18 22 32 46 51 57 65 80 88; 140 : 1 38 39 40 41 42 43 44 45 46; 141 : 2 18 27 36 45 54 63 72 81 90; 142 : 6 15 28 29 40 53 61 68 75 90; 143 : 5 12 24 36 38 55 61 67 80 86; 144 : 5 13 25 37 39 53 59 65 81 87; 145 : 8 19 25 31 42 54 56 68 80 84; 146 : 8 18 24 30 41 53 58 70 82 83; 147 : 9 14 21 37 40 52 63 69 80 83; 148 : 4 17 28 36 41 52 60 65 76 84; 149 : 5 17 20 32 42 49 63 70 75 91; 150 : 3 18 28 35 39 49 56 69 79 86; 151 : 5 11 23 35 40 54 60 66 82 88; 152 : 10 14 22 36 43 53 56 66 78 91; 153 : 1 74 75 76 77 78 79 80 81 82; 154 : 2 14 23 32 41 50 59 68 77 86; 155 : 10 19 24 29 39 50 63 71 76 88; 156 : 9 12 28 32 43 54 58 71 74 87; 157 : 7 13 24 35 45 52 57 68 74 91; 158 : 9 17 24 31 46 47 59 66 79 90; 159 : 9 19 23 30 45 49 61 65 78 89; 160 : 10 16 21 35 42 55 58 65 77 90; 161 : 4 18 26 37 42 50 61 66 74 85; 162 : 7 18 20 34 40 55 59 71 78 84; 163 : 3 19 26 36 40 47 57 70 77 87; 164 : 7 11 25 36 46 50 58 69 75 89; 165 : 8 16 22 37 45 47 60 71 75 86; 166 : 1 83 84 85 86 87 88 89 90 91; 167 : 2 16 25 34 43 52 61 70 79 88; 168 : 8 17 23 29 43 55 57 69 81 85; 169 : 10 12 26 34 46 49 60 68 81 83; 170 : 6 13 23 36 42 48 64 71 79 83; 171 : 10 18 23 31 38 52 62 73 75 87; 172 : 10 17 25 30 40 51 64 72 74 86; 173 : 8 15 21 36 44 49 59 73 74 88; 174 : 4 19 27 35 43 51 59 67 75 83; 175 : 6 19 20 33 44 52 58 66 81 86; 176 : 3 17 27 37 38 48 58 68 78 88; 177 : 6 11 24 37 43 49 62 72 77 84; 178 : 9 15 22 35 38 50 64 70 81 84; 179 : 1 65 66 67 68 69 70 71 72 73; 180 : 2 15 24 33 42 51 60 69 78 87; 181 : 9 18 25 29 44 48 60 67 77 91; 182 : 8 12 27 33 40 50 62 65 79 91; $$ *=15 k=2 2 -c x a=c6a8a0f o=28228f9 cjx a=c645be o=e00d979 b=abec4e5 q nauty24r2/gutils.h0000600000604200001440000000153511274163463012773 0ustar bdmusers/* gutils.h - procedure declarations for gutil1.c and gutil2.c */ void degstats(graph*,int,int,unsigned long*,int*,int*,int*,int*,boolean*); void diamstats(graph*,int,int,int*,int*); void find_dist(graph*,int,int,int,int*); int girth(graph*,int,int); boolean isbiconnected1(graph*,int); boolean isbiconnected(graph*,int,int); boolean isbipartite(graph*,int,int); boolean twocolouring(graph*,int*,int,int); boolean isconnected1(graph*,int); boolean isconnected(graph*,int,int); boolean issubconnected(graph*,set*,int,int); int loopcount(graph*,int,int); long pathcount1(graph*,int,setword,setword); long cyclecount1(graph*,int); long cyclecount(graph*,int,int); void commonnbrs(graph*,int*,int*,int*,int*,int,int); void contract1(graph*,graph*,int,int,int); int cstarcontent(graph*,int,int); long numtriangles1(graph*,int); long numtriangles(graph*,int,int); nauty24r2/nautyex4.c0000600000604200001440000000413011274163463013232 0ustar bdmusers/* This program prints generators for the automorphism group of an n-vertex polygon, where n is a number supplied by the user. It needs to be linked with nauty.c, nautil.c and nausparse.c. This version uses sparse form with dynamic allocation. */ #include "nausparse.h" /* which includes nauty.h */ int main(int argc, char *argv[]) { DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(setword,workspace,workspace_sz); static DEFAULTOPTIONS_SPARSEGRAPH(options); statsblk stats; sparsegraph sg; /* Declare sparse graph structure */ int n,m,i; options.writeautoms = TRUE; /* Initialise sparse graph structure. */ SG_INIT(sg); while (1) { printf("\nenter n : "); if (scanf("%d",&n) == 1 && n > 0) { m = (n + WORDSIZE - 1) / WORDSIZE; nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); DYNALLOC1(int,lab,lab_sz,n,"malloc"); DYNALLOC1(int,ptn,ptn_sz,n,"malloc"); DYNALLOC1(int,orbits,orbits_sz,n,"malloc"); DYNALLOC1(setword,workspace,workspace_sz,2*m,"malloc"); /* SG_ALLOC makes sure that the v,d,e fields of a sparse graph * structure point to arrays that are large enough. This only * works if the structure has been initialised. */ SG_ALLOC(sg,n,2*n,"malloc"); sg.nv = n; /* Number of vertices */ sg.nde = 2*n; /* Number of directed edges */ for (i = 0; i < n; ++i) { sg.v[i] = 2*i; sg.d[i] = 2; sg.e[2*i] = (i+n-1)%n; /* edge i->i-1 */ sg.e[2*i+1] = (i+n+1)%n; /* edge i->i+1 */ } printf("Generators for Aut(C[%d]):\n",n); nauty((graph*)&sg,lab,ptn,NULL,orbits,&options,&stats, workspace,2*m,m,n,NULL); printf("Automorphism group size = %.0f",stats.grpsize1+0.1); } else break; } exit(0); } nauty24r2/naugroup.h0000600000604200001440000000272311274163463013324 0ustar bdmusers/* naugroup.h Procedures for handling groups found by nauty. */ #include "nauty.h" typedef struct perm_struct { struct perm_struct *ptr; /* general-purpose pointer */ permutation p[2]; /* extendable section */ } permrec; typedef struct coset_struct { int image; /* image of fixed point */ permrec *rep; /* pointer to a representative */ } cosetrec; typedef struct level_struct { int fixedpt; /* point that is fixed in this level */ int orbitsize; /* the size of the orbit containing fixedpt */ permrec *gens; /* pointer to list of generators */ cosetrec *replist; /* array of orbitsize representatives */ } levelrec; typedef struct group_struct { int n; /* number of points */ int numorbits; /* number of orbits */ int depth; /* number of points in base */ levelrec levelinfo[1]; /* extendable section */ } grouprec; #ifdef __cplusplus extern "C" { #endif extern void freepermrec(permrec*, int); extern grouprec *groupptr(boolean); extern permrec *newpermrec(int); extern void groupautomproc(int,permutation*,int*,int,int,int); extern void grouplevelproc(int*,int*,int,int*,statsblk*,int,int,int,int,int,int); extern void makecosetreps(grouprec*); extern int permcycles(permutation*,int,int*,boolean); extern void allgroup(grouprec*,void(*)(permutation*,int)); extern int allgroup2(grouprec*,void(*)(permutation*,int,int*)); #ifdef __cplusplus } #endif nauty24r2/testS.dre0000600000604200001440000000171111274163463013105 0ustar bdmusersC n=1 g. -cx a=1 o=be40 jcx a=1 b=ab2 o=be40 n=6 $=0 g 0 : 3 4 5; 1 : 3 4 5; 2 : 3 4 5; 3 : 0 1 2; 4 : 0 1 2; 5 : 0 1 2; $$ -cx a=b9adfd o=2f900 jcx a=d93e1c b=1becb61 o=2f900 n=13 $=0 g 0 : 6 7 8 9; 1 : 6 7 8 11; 2 : 7 8 10 12; 3 : 7 9 11 12; 4 : 8 10 11 12; 5 : 9 10 11 12; 6 : 0 1 9 10; 7 : 0 1 2 3; 8 : 0 1 2 4; 9 : 0 3 5 6; 10 : 2 4 5 6; 11 : 1 3 4 5; 12 : 2 3 4 5; $$ -cx a=1 o=d6f0789 jcx a=1 b=43ff82d o=d6f0789 n=16 $=0 g 0 : 8 9 10 11 12; 1 : 8 9 10 11 13; 2 : 8 9 10 14 15; 3 : 8 9 12 13 14; 4 : 8 9 12 13 15; 5 : 10 11 12 14 15; 6 : 10 11 13 14 15; 7 : 11 12 13 14 15; 8 : 0 1 2 3 4; 9 : 0 1 2 3 4; 10 : 0 1 2 5 6; 11 : 0 1 5 6 7; 12 : 0 3 4 5 7; 13 : 1 3 4 6 7; 14 : 2 3 5 6 7; 15 : 2 4 5 6 7; $$ -cx a=ee180d4 o=e21afbf jcx a=e330fba o=f2752f5 b=11b140e jcx a=72e30a7 o=627b41f b=65c46b6 n=16 g. _ -cx a=584406e o=2f9000 jcx a=584406e o=2f9000 b=de66369 jcx a=584406e o=2f9000 b=de66369 q nauty24r2/nausparse.c0000600000604200001440000011711311405400302013436 0ustar bdmusers/***************************************************************************** * * * Sparse-graph-specific auxiliary source file for version 2.4 of nauty. * * * * Copyright (2004-2010) Brendan McKay. All rights reserved. * * Subject to waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 26-Oct-04 : initial creation * * 23-Nov-06 : dispatch uses targetcell_sg, not bestcell_sg * * 8-Dec-06 : add adjacencies_sg * * * *****************************************************************************/ #define TMP /* #define ONE_WORD_SETS not sure about this! See notes.txt. */ #include "nausparse.h" /* macros for hash-codes: */ #define MASH(l,i) ((((l) ^ 065435) + (i)) & 077777) /* : expression whose long value depends only on long l and int/long i. Anything goes, preferably non-commutative. */ #define CLEANUP(l) ((int)((l) % 077777)) /* : expression whose value depends on long l and is less than 077777 when converted to int then short. Anything goes. */ #if MAXM==1 #define M 1 #else #define M m #endif #define ACCUM(x,y) x = (((x) + (y)) & 077777) static int fuzz1[] = {037541,061532,005257,026416}; static int fuzz2[] = {006532,070236,035523,062437}; #define FUZZ1(x) ((x) ^ fuzz1[(x)&3]) #define FUZZ2(x) ((x) ^ fuzz2[(x)&3]) /* aproto: header new_nauty_protos.h */ dispatchvec dispatch_sparse = {isautom_sg,testcanlab_sg,updatecan_sg,refine_sg,refine_sg,cheapautom_sg, targetcell_sg,nausparse_freedyn,nausparse_check,init_sg,NULL}; #if !MAXN DYNALLSTAT(short,vmark1,vmark1_sz); DYNALLSTAT(short,vmark2,vmark2_sz); DYNALLSTAT(shortish,work1,work1_sz); DYNALLSTAT(shortish,work2,work2_sz); DYNALLSTAT(shortish,work3,work3_sz); DYNALLSTAT(shortish,work4,work4_sz); #else static short vmark1[MAXN]; static short vmark2[MAXN]; static shortish work1[MAXN]; static shortish work2[MAXN]; static shortish work3[MAXN]; static shortish work4[MAXN]; #endif static short vmark1_val = 32000; #define MARK1(i) vmark1[i] = vmark1_val #define UNMARK1(i) vmark1[i] = 0 #define ISMARKED1(i) (vmark1[i] == vmark1_val) #define ISNOTMARKED1(i) (vmark1[i] != vmark1_val) static short vmark2_val = 32000; #define MARK2(i) vmark2[i] = vmark2_val #define UNMARK2(i) vmark2[i] = 0 #define ISMARKED2(i) (vmark2[i] == vmark2_val) #define ISNOTMARKED2(i) (vmark2[i] != vmark2_val) #if !MAXN #define RESETMARKS1 {if (vmark1_val++ >= 32000) \ {size_t ii; for (ii=0;ii= 32000) \ {size_t ii; for (ii=0;ii= 32000) \ {size_t ii; for (ii=0;ii= 32000) \ {size_t ii; for (ii=0;iinv; if (g2->nv != n || g2->nde != g1->nde) return FALSE; SG_VDE(g1,v1,d1,e1); SG_VDE(g2,v2,d2,e2); PREPAREMARKS1(n); for (i = 0; i < n; ++i) { di = d1[i]; if (d2[i] != di) return FALSE; vi = v1[i]; RESETMARKS1; for (j = 0; j < di; ++j) MARK1(e1[vi+j]); vi = v2[i]; for (j = 0; j < di; ++j) if (ISNOTMARKED1(e2[vi+j])) return FALSE; } return TRUE; } /***************************************************************************** * * * testcanlab_sg(g,canong,lab,samerows,m,n) compares g^lab to canong, * * using an ordering which is immaterial since it's only used here. The * * value returned is -1,0,1 if g^lab <,=,> canong. *samerows is set to * * the number of rows (0..n) of canong which are the same as those of g^lab. * * * *****************************************************************************/ int testcanlab_sg(graph *g, graph *canong, int *lab, int *samerows, int m, int n) { int *v,*d,*e; int *cv,*cd,*ce; int i,j,di,dli; int vi,vli,k; int mina; SG_VDE(g,v,d,e); SG_VDE(canong,cv,cd,ce); #if !MAXN DYNALLOC1(shortish,work1,work1_sz,n,"testcanlab_sg"); #endif #define INVLAB work1 PREPAREMARKS1(n); for (i = 0; i < n; ++i) INVLAB[lab[i]] = i; for (i = 0; i < n; ++i) { /* compare g[lab[i]]^INVLAB to canong[i] */ vi = cv[i]; di = cd[i]; vli = v[lab[i]]; dli = d[lab[i]]; if (di != dli) { *samerows = i; if (di < dli) return -1; return 1; } RESETMARKS1; mina = n; for (j = 0; j < di; ++j) MARK1(ce[vi+j]); for (j = 0; j < di; ++j) { k = INVLAB[e[vli+j]]; if (ISMARKED1(k)) UNMARK1(k); else if (k < mina) mina = k; } if (mina != n) { *samerows = i; for (j = 0; j < di; ++j) { k = ce[vi+j]; if (ISMARKED1(k) && k < mina) return -1; } return 1; } } *samerows = n; return 0; } /***************************************************************************** * * * updatecan_sg(g,canong,lab,samerows,m,n) sets canong = g^lab, assuming * * the first samerows vertices of canong are ok already. Also assumes * * contiguity and ample space in canong. * * * *****************************************************************************/ void updatecan_sg(graph *g, graph *canong, permutation *lab, int samerows, int m, int n) { int *v,*d,*e; int *cv,*cd,*ce; int i,j; int vli,dli,k; SG_VDE(g,v,d,e); SG_VDE(canong,cv,cd,ce); #if !MAXN DYNALLOC1(shortish,work1,work1_sz,n,"testcanlab_sg"); #endif #define INVLAB work1 PREPAREMARKS1(n); ((sparsegraph*)canong)->nv = n; ((sparsegraph*)canong)->nde = ((sparsegraph*)g)->nde; for (i = 0; i < n; ++i) INVLAB[lab[i]] = i; if (samerows == 0) k = 0; else k = cv[samerows-1]+cd[samerows-1]; for (i = samerows; i < n; ++i) { cv[i] = k; cd[i] = dli = d[lab[i]]; vli = v[lab[i]]; for (j = 0; j < dli; ++j) ce[k++] = INVLAB[e[vli+j]]; } } /***************************************************************************** * * * sortindirect(x,n,z) - sort x[0..n-1] according to z[x[i]] values * * * *****************************************************************************/ static void sortindirect(int *x, int n, shortish *z) { int i,j,h,xi; shortish iw; j = n / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < n; ++i) { xi = x[i]; iw = z[xi]; for (j = i; z[x[j-h]] > iw; ) { x[j] = x[j-h]; if ((j -= h) < h) break; } x[j] = xi; } h /= 3; } while (h > 0); } /***************************************************************************** * * * sortshortish(x,n) - sort x[0..n-1] according to numerical values * * * *****************************************************************************/ static void sortshortish(shortish *x, int n) { int i,j,h; shortish xi; j = n / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < n; ++i) { xi = x[i]; for (j = i; x[j-h] > xi; ) { x[j] = x[j-h]; if ((j -= h) < h) break; } x[j] = xi; } h /= 3; } while (h > 0); } /***************************************************************************** * * * sortints(x,n) - sort x[0..n-1] according to numerical values * * * *****************************************************************************/ static void sortints(int *x, int n) { int i,j,h; int xi; j = n / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < n; ++i) { xi = x[i]; for (j = i; x[j-h] > xi; ) { x[j] = x[j-h]; if ((j -= h) < h) break; } x[j] = xi; } h /= 3; } while (h > 0); } /***************************************************************************** * * * init_sg(graph *gin, graph **gout, graph *hin, graph **hout, * * int *lab, int *ptn, set *active, optionblk *options, * * int *status, int m, int n) * * Initialse routine for dispatch vector. This one just makes sure * * that *hin has enough space. * * * *****************************************************************************/ void init_sg(graph *gin, graph **gout, graph *hin, graph **hout, int *lab, int *ptn, set *active, struct optionstruct *options, int *status, int m, int n) { sparsegraph *sg,*sh; if (options->getcanon) { sg = (sparsegraph*)gin; sh = (sparsegraph*)hin; SG_ALLOC(*sh,sg->nv,sg->nde,"init_sg"); } *status = 0; } /***************************************************************************** * * * distvals(sparsegraph *sg, int v0, shortish *dist, int n) sets dist[i] * * to the distance from v0 to i, for each i, or to n if there is no such * * distance. work4[] is used as a queue. * * * *****************************************************************************/ void distvals(sparsegraph *g, int v0, shortish *dist, int n) { int *v,*d,*e; int i,head,tail; int vi,di,j,k; SG_VDE(g,v,d,e); #if !MAXN DYNALLOC1(shortish,work4,work4_sz,n,"distvals"); #endif #define QUEUE work4 for (i = 0; i < n; ++i) dist[i] = n; QUEUE[0] = v0; dist[v0] = 0; head = 0; tail = 1; while (tail < n && head < tail) { i = QUEUE[head++]; vi = v[i]; di = d[i]; for (j = 0; j < di; ++j) { k = e[vi+j]; if (dist[k] == n) { dist[k] = dist[i] + 1; QUEUE[tail++] = k; } } } } /***************************************************************************** * * * refine_sg(g,lab,ptn,level,numcells,count,active,code,m,n) performs a * * refinement operation on the partition at the specified level of the * * partition nest (lab,ptn). *numcells is assumed to contain the number of * * cells on input, and is updated. The initial set of active cells (alpha * * in the paper) is specified in the set active. Precisely, x is in active * * iff the cell starting at index x in lab is active. * * The resulting partition is equitable if active is correct (see the paper * * and the Guide). * * *code is set to a value which depends on the fine detail of the * * algorithm, but which is independent of the labelling of the graph. * * count is used for work space. * * * *****************************************************************************/ void refine_sg(graph *g, int *lab, int *ptn, int level, int *numcells, permutation *count, set *active, int *code, int m, int n) { int i,j,k,l,v1,v2,v3,isplit; shortish w1,w2,w3; long longcode; int *v,*d,*e; int size,bigsize,bigpos; int nactive,hitcells; int lj,vi,di,splitv; boolean trivsplit; SG_VDE(g,v,d,e); #if !MAXN DYNALLOC1(shortish,work1,work1_sz,n,"refine_sg"); DYNALLOC1(shortish,work2,work2_sz,n,"refine_sg"); DYNALLOC1(shortish,work3,work3_sz,n,"refine_sg"); DYNALLOC1(shortish,work4,work4_sz,n,"refine_sg"); #endif #define CELLSTART work1 #define ACTIVE work2 #define HITS work3 #define HITCELL work4 PREPAREMARKS1(n); PREPAREMARKS2(n); longcode = *numcells; /* Set ACTIVE[0..nactive-1] = queue of active cell starts */ nactive = 0; for (i = -1; (i = nextelement(active,m,i)) >= 0;) ACTIVE[nactive++] = i; if (nactive == 0) { *code = CLEANUP(longcode); return; } /* Set CELLSTART[i] = starting point in lab[] of nontrivial cell containing i, or n if i is a singleton */ for (i = 0; i < n; ) { /* Just here, i is a cell starting position */ if (ptn[i] <= level) { CELLSTART[lab[i]] = n; ++i; } else { j = i; do { CELLSTART[lab[i]] = j; } while (ptn[i++] > level); } } if (level <= 2 && nactive == 1 && ptn[ACTIVE[0]] <= level && *numcells <= n/8) { isplit = ACTIVE[--nactive]; DELELEMENT(active,isplit); distvals((sparsegraph*)g,lab[isplit],HITS,n); for (v1 = 0; v1 < n; ) { if (ptn[v1] <= level) { ++v1; continue; } longcode = MASH(longcode,v1); w1 = HITS[lab[v1]]; v2 = v1+1; while (ptn[v2-1] > level && HITS[lab[v2]] == w1) ++v2; if (ptn[v2-1] <= level) { v1 = v2; continue; } w2 = NAUTY_INFINITY; v3 = j = v2; do { lj = lab[j]; w3 = HITS[lj]; if (w3 == w1) { lab[j] = lab[v3]; lab[v3] = lab[v2]; lab[v2] = lj; ++v2; ++v3; } else if (w3 == w2) { lab[j] = lab[v3]; lab[v3] = lj; ++v3; } else if (w3 < w1) { lab[j] = lab[v2]; lab[v2] = lab[v1]; lab[v1] = lj; v3 = v2 + 1; v2 = v1 + 1; w2 = w1; w1 = w3; } else if (w3 < w2) { lab[j] = lab[v2]; lab[v2] = lj; v3 = v2 + 1; w2 = w3; } } while (ptn[j++] > level); longcode = MASH(longcode,w2); longcode = MASH(longcode,v2); if (j != v2) /* At least two fragments * v1..v2-1 = w1; v2..v3-1 = w2 */ { if (v2 == v1+1) CELLSTART[lab[v1]] = n; if (v3 == v2+1) CELLSTART[lab[v2]] = n; else for (k = v2; k < v3; ++k) CELLSTART[lab[k]] = v2; ++*numcells; ptn[v2-1] = level; if (j == v3) { /* Two fragments only */ if (v2-v1 <= v3-v2 && !ISELEMENT(active,v1)) { ADDELEMENT(active,v1); ACTIVE[nactive++] = v1; } else { ADDELEMENT(active,v2); ACTIVE[nactive++] = v2; } } else { /* Extra fragments: v3..j-1 > w2 */ sortindirect(lab+v3,j-v3,HITS); ACTIVE[nactive++] = v2; ADDELEMENT(active,v2); if (v2-v1 >= v3-v2) { bigpos = -1; bigsize = v2-v1; } else { bigpos = nactive-1; bigsize = v3-v2; } for (k = v3-1; k < j-1;) { ptn[k] = level; longcode = MASH(longcode,k); ++*numcells; l = k+1; ADDELEMENT(active,l); ACTIVE[nactive++] = l; w3 = HITS[lab[l]]; for (k = l; k < j-1 && HITS[lab[k+1]] == w3; ++k) CELLSTART[lab[k+1]] = l; size = k-l+1; if (size == 1) CELLSTART[lab[l]] = n; else { CELLSTART[lab[l]] = l; if (size > bigsize) { bigsize = size; bigpos = nactive-1; } } } if (bigpos >= 0 && !ISELEMENT(active,v1)) { longcode = MASH(longcode,bigpos); DELELEMENT(active,ACTIVE[bigpos]); ADDELEMENT(active,v1); ACTIVE[bigpos] = v1; } } } v1 = j; } } /* Iterate until complete */ while (nactive > 0 && *numcells < n) { for (i = 0; i < nactive && i < 10; ++i) if (ptn[ACTIVE[i]] <= level) break; if (i < nactive && i < 10) { trivsplit = TRUE; isplit = ACTIVE[i]; ACTIVE[i] = ACTIVE[--nactive]; } else { isplit = ACTIVE[--nactive]; trivsplit = ptn[isplit] <= level; } DELELEMENT(active,isplit); longcode = MASH(longcode,isplit); if (trivsplit) { RESETMARKS1; RESETMARKS2; hitcells = 0; splitv = lab[isplit]; vi = v[splitv]; di = d[splitv]; for (i = 0; i < di; ++i) { j = e[vi+i]; MARK2(j); k = CELLSTART[j]; if (k != n && ISNOTMARKED1(k)) { MARK1(k); HITCELL[hitcells++] = k; } } if (hitcells > 1) sortshortish(HITCELL,hitcells); /* divide cells according to which vertices are hit */ for (i = 0; i < hitcells; ++i) { j = v1 = v2 = HITCELL[i]; k = 0; do { lj = lab[j]; if (ISMARKED2(lj)) HITS[k++] = lj; else lab[v2++] = lj; } while (ptn[j++] > level); longcode = MASH(longcode,k); v3 = v2; while (--k >= 0) { j = HITS[k]; CELLSTART[j] = v2; lab[v3++] = j; } if (v2 != v3 && v2 != v1) { ++*numcells; if (v2 == v1+1) CELLSTART[lab[v1]] = n; if (v3 == v2+1) CELLSTART[lab[v2]] = n; ptn[v2-1] = level; longcode = MASH(longcode,v2); if (v2-v1 <= v3-v2 && !ISELEMENT(active,v1)) { ADDELEMENT(active,v1); ACTIVE[nactive++] = v1; } else { ADDELEMENT(active,v2); ACTIVE[nactive++] = v2; } } } } else /* non-trivial splitting */ { /* isplit is the start of the splitting cell. Set HITS[i] = hits of i for i in non-trivial cells, HITCELL[0..hitcells-1] = starts of hit non-trivial cells */ RESETMARKS1; hitcells = 0; do { vi = v[lab[isplit]]; di = d[lab[isplit]]; for (i = 0; i < di; ++i) { j = e[vi+i]; k = CELLSTART[j]; if (k != n) { if (ISNOTMARKED1(k)) { MARK1(k); HITCELL[hitcells++] = k; do { HITS[lab[k]] = 0; } while (ptn[k++] > level); } ++HITS[j]; } } } while (ptn[isplit++] > level); if (hitcells > 1) sortshortish(HITCELL,hitcells); /* divide cells according to hit counts */ longcode = MASH(longcode,hitcells); for (i = 0; i < hitcells; ++i) { v1 = HITCELL[i]; w1 = HITS[lab[v1]]; v2 = v1+1; while (ptn[v2-1] > level && HITS[lab[v2]] == w1) ++v2; if (ptn[v2-1] <= level) continue; w2 = NAUTY_INFINITY; v3 = j = v2; do { lj = lab[j]; w3 = HITS[lj]; if (w3 == w1) { lab[j] = lab[v3]; lab[v3] = lab[v2]; lab[v2] = lj; ++v2; ++v3; } else if (w3 == w2) { lab[j] = lab[v3]; lab[v3] = lj; ++v3; } else if (w3 < w1) { lab[j] = lab[v2]; lab[v2] = lab[v1]; lab[v1] = lj; v3 = v2 + 1; v2 = v1 + 1; w2 = w1; w1 = w3; } else if (w3 < w2) { lab[j] = lab[v2]; lab[v2] = lj; v3 = v2 + 1; w2 = w3; } } while (ptn[j++] > level); longcode = MASH(longcode,w1); longcode = MASH(longcode,v2); if (j != v2) /* At least two fragments * v1..v2-1 = w1; v2..v3-1 = w2 */ { if (v2 == v1+1) CELLSTART[lab[v1]] = n; if (v3 == v2+1) CELLSTART[lab[v2]] = n; else for (k = v2; k < v3; ++k) CELLSTART[lab[k]] = v2; ++*numcells; ptn[v2-1] = level; if (j == v3) { /* Two fragments only */ if (v2-v1 <= v3-v2 && !ISELEMENT(active,v1)) { ADDELEMENT(active,v1); ACTIVE[nactive++] = v1; } else { ADDELEMENT(active,v2); ACTIVE[nactive++] = v2; } } else { /* Extra fragments: v3..j-1 > w2 */ longcode = MASH(longcode,v3); sortindirect(lab+v3,j-v3,HITS); ACTIVE[nactive++] = v2; ADDELEMENT(active,v2); if (v2-v1 >= v3-v2) { bigpos = -1; bigsize = v2-v1; } else { bigpos = nactive-1; bigsize = v3-v2; longcode = MASH(longcode,bigsize); } for (k = v3-1; k < j-1;) { ptn[k] = level; ++*numcells; l = k+1; ADDELEMENT(active,l); ACTIVE[nactive++] = l; w3 = HITS[lab[l]]; longcode = MASH(longcode,w3); for (k = l; k < j-1 && HITS[lab[k+1]] == w3; ++k) CELLSTART[lab[k+1]] = l; size = k-l+1; if (size == 1) CELLSTART[lab[l]] = n; else { CELLSTART[lab[l]] = l; if (size > bigsize) { bigsize = size; bigpos = nactive-1; } } } if (bigpos >= 0 && !ISELEMENT(active,v1)) { DELELEMENT(active,ACTIVE[bigpos]); ADDELEMENT(active,v1); ACTIVE[bigpos] = v1; } } } } } } longcode = MASH(longcode,*numcells); *code = CLEANUP(longcode); } /***************************************************************************** * * * cheapautom_sg(ptn,level,digraph,n) returns TRUE if the partition at the * * specified level in the partition nest (lab,ptn) {lab is not needed here} * * satisfies a simple sufficient condition for its cells to be the orbits of * * some subgroup of the automorphism group. Otherwise it returns FALSE. * * It always returns FALSE if digraph!=FALSE. * * * * nauty assumes that this function will always return TRUE for any * * partition finer than one for which it returns TRUE. * * * *****************************************************************************/ boolean cheapautom_sg(int *ptn, int level, boolean digraph, int n) { int i,k,nnt; if (digraph) return FALSE; k = n; nnt = 0; for (i = 0; i < n; ++i) { --k; if (ptn[i] > level) { ++nnt; while (ptn[++i] > level) {} } } return (k <= nnt + 1 || k <= 4); } /***************************************************************************** * * * bestcell_sg(g,lab,ptn,level,tc_level,m,n) returns the index in lab of * * the start of the "best non-singleton cell" for fixing. If there is no * * non-singleton cell it returns n. * * This implementation finds the first cell which is non-trivially joined * * to the greatest number of other cells, assuming equitability. * * This is not good for digraphs! * * * *****************************************************************************/ static int bestcell_sg(graph *g, int *lab, int *ptn, int level, int tc_level, int m, int n) { int nnt; int *v,*d,*e; int i,j,k,vi,di; shortish *work1b; int maxcnt; SG_VDE(g,v,d,e); #if !MAXN DYNALLOC1(shortish,work1,work1_sz,n,"bestcell_sg"); DYNALLOC1(shortish,work2,work2_sz,n,"bestcell_sg"); DYNALLOC1(shortish,work3,work3_sz,n,"bestcell_sg"); DYNALLOC1(shortish,work4,work4_sz,n,"bestcell_sg"); #endif work1b = work1 + (n/2); #define START work1 #define SIZE work1b #define NNTCELL work2 #define HITS work3 #define COUNT work4 /* find non-singleton cells: put starts in START[0..nnt-1], sizes in SIZE[0..nnt-1]. Also NNTCELL[i] = n if {i} is a singelton, else index of nontriv cell containing i. */ i = nnt = 0; while (i < n) { if (ptn[i] > level) { START[nnt] = i; j = i; do NNTCELL[lab[j]] = nnt; while (ptn[j++] > level); SIZE[nnt] = j-i; ++nnt; i = j; } else { NNTCELL[lab[i]] = n; ++i; } } if (nnt == 0) return n; /* set COUNT[i] to # non-trivial neighbours of n.s. cell i */ for (i = 0; i < nnt; ++i) HITS[i] = COUNT[i] = 0; for (i = 0; i < nnt; ++i) { vi = v[lab[START[i]]]; di = d[lab[START[i]]]; for (j = 0; j < di; ++j) { k = NNTCELL[e[vi+j]]; if (k != n) ++HITS[k]; } for (j = 0; j < di; ++j) { k = NNTCELL[e[vi+j]]; if (k != n) { if (HITS[k] > 0 && HITS[k] < SIZE[k]) ++COUNT[i]; HITS[k] = 0; } } } /* find first greatest bucket value */ j = 0; maxcnt = COUNT[0]; for (i = 1; i < nnt; ++i) if (COUNT[i] > maxcnt) { j = i; maxcnt = COUNT[i]; } return (int)START[j]; } /***************************************************************************** * * * targetcell_sg(g,lab,ptn,level,tc_level,digraph,hint,m,n) returns the * * index in lab of the next cell to split. * * hint is a suggestion for the answer, which is obeyed if it is valid. * * Otherwise we use bestcell() up to tc_level and the first non-trivial * * cell after that. * * * *****************************************************************************/ int targetcell_sg(graph *g, int *lab, int *ptn, int level, int tc_level, boolean digraph, int hint, int m, int n) { int i; if (hint >= 0 && ptn[hint] > level && (hint == 0 || ptn[hint-1] <= level)) return hint; else if (level <= tc_level) return bestcell_sg(g,lab,ptn,level,tc_level,m,n); else { for (i = 0; i < n && ptn[i] <= level; ++i) {} return (i == n ? 0 : i); } } /***************************************************************************** * * * sortlists_sg(g) sorts the adjacency lists into numerical order * * * *****************************************************************************/ void sortlists_sg(sparsegraph *g) { int *v,*d,*e; int n,i; SG_VDE(g,v,d,e); n = g->nv; for (i = 0; i < n; ++i) if (d[i] > 1) sortints(e+v[i],d[i]); } /***************************************************************************** * * * put_sg(f,sg,digraph,linelength) writes the sparse graph to file f using * * at most linelength characters per line. If digraph then all directed * * edges are written; else one v-w for w>=v is written. * * * *****************************************************************************/ void put_sg(FILE *f, sparsegraph *sg, boolean digraph, int linelength) { int *v,*d,*e; int n,vi,di; int i,j,curlen,slen; char s[12]; SG_VDE(sg,v,d,e); n = sg->nv; for (i = 0; i < n; ++i) { vi = v[i]; di = d[i]; if (di == 0) continue; slen = itos(i+labelorg,s); putstring(f,s); putstring(f," :"); curlen = slen + 2; for (j = 0; j < di; ++j) { if (!digraph && e[vi+j] < i) continue; slen = itos(e[vi+j]+labelorg,s); if (linelength && curlen + slen + 1 >= linelength) { putstring(f,"\n "); curlen = 2; } PUTC(' ',f); putstring(f,s); curlen += slen + 1; } PUTC('\n',f); } } /***************************************************************************** * * * sg_to_nauty(sg,g,reqm,&m) creates a nauty-format graph from a sparse * * graph. reqm is the required m value (computed from n if reqm=0), and * * m is the actual value used. g is dynamically generated if NULL is given. * * A pointer to g is returned. * * * *****************************************************************************/ graph* sg_to_nauty(sparsegraph *sg, graph *g, int reqm, int *pm) { int *v,*d,*e; int m,n,i,j,di; int vi; set *gi; SG_VDE(sg,v,d,e); n = sg->nv; if (reqm != 0 && reqm*WORDSIZE < n) { fprintf(ERRFILE,"sg_to_nauty: reqm is impossible\n"); exit(1); } if (reqm != 0) m = reqm; else m = (n+WORDSIZE-1)/WORDSIZE; *pm = m; if (g == NULL) { if ((g = (graph*)ALLOCS(n,m*sizeof(graph))) == NULL) { fprintf(ERRFILE,"sg_to_nauty: malloc failed\n"); exit(1); } } for (i = 0, gi = g; i < n; ++i, gi += m) { vi = v[i]; di = d[i]; EMPTYSET(gi,m); for (j = 0; j < di; ++j) ADDELEMENT(gi,e[vi+j]); } return g; } /***************************************************************************** * * * nauty_to_sg(g,m,n) creates a sparse graph from a nauty format graph * * If sg is not NULL, it is assumed that the vlen,dlen,elen fields are * * correct and v,d,e are dynamically allocated (or NULL); they are * * reallocated if necessary. If sg==NULL, a new structure is allocated. * * A pointer to the sparse graph is returned. * * * *****************************************************************************/ sparsegraph* nauty_to_sg(graph *g, sparsegraph *sg, int m, int n) { int *v,*d,*e; int i,j,k; int di,nde; long l; set *gi; if (!sg) { if ((sg = (sparsegraph*)ALLOCS(1,sizeof(sparsegraph))) == NULL) { fprintf(ERRFILE,"nauty_to_sg: malloc failed\n"); exit(1); } SG_INIT(*sg); } nde = 0; for (l = m*1L*n; --l >= 0; ) if (g[l] != 0) nde += POPCOUNT(g[l]); sg->nv = n; sg->nde = nde; SG_ALLOC(*sg,n,nde,"nauty_to_sg"); SG_VDE(sg,v,d,e); j = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { v[i] = j; di = 0; for (k = -1; (k = nextelement(gi,m,k)) >= 0; ) e[j++] = k; d[i] = j - v[i]; } return sg; } /***************************************************************************** * * * distances_sg() assigns to each vertex v a value depending on the number * * of vertices at each distance from v, and what cells they lie in. * * If we find any cell which is split in this manner, we don't try any * * further cells. * * * *****************************************************************************/ void distances_sg(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int *v,*d,*e; int i,j,k,dlim,wt; int vi,di; int cell1,cell2,iv,liv,kcode; int head,tail; long longcode; boolean success; SG_VDE(g,v,d,e); #if !MAXN DYNALLOC1(shortish,work1,work1_sz,n,"distances_sg"); DYNALLOC1(shortish,work4,work4_sz,n,"distances_sg"); DYNALLOC1(shortish,work3,work3_sz,n,"distances_sg"); #endif #define CELLCODE work1 #define QUEUE work4 #define DIST work3 for (i = n; --i >= 0;) invar[i] = 0; wt = 1; for (i = 0; i < n; ++i) { CELLCODE[lab[i]] = FUZZ1(wt); if (ptn[i] <= level) ++wt; } if (invararg > n || invararg == 0) dlim = n; else dlim = invararg+1; success = FALSE; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} if (cell2 == cell1) continue; for (iv = cell1; iv <= cell2; ++iv) { liv = lab[iv]; QUEUE[0] = liv; DIST[liv] = 0; RESETMARKS1; MARK1(liv); longcode = 0; head = 0; tail = 1; while (tail < n && head < tail) { i = QUEUE[head++]; if (DIST[i] >= dlim) break; vi = v[i]; di = d[i]; for (j = 0; j < di; ++j) { k = e[vi+j]; if (ISNOTMARKED1(k)) { MARK1(k); DIST[k] = DIST[i] + 1; kcode = DIST[k]+CELLCODE[k]; ACCUM(longcode,FUZZ1(kcode)); QUEUE[tail++] = k; } } } invar[liv] = CLEANUP(longcode); if (invar[liv] != invar[lab[cell1]]) success = TRUE; } if (success) break; } } /***************************************************************************** * * * adjacencies_sg() assigns to each vertex v a code depending on which cells * * it is joined to and from, and how many times. It is intended to provide * * better partitioning that the normal refinement routine for digraphs. * * It will not help with undirected graphs in nauty at all. * * * *****************************************************************************/ void adjacencies_sg(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos, permutation *invar, int invararg, boolean digraph, int m, int n) { int *v,*d,*e; shortish vwt,wwt; int *ei,di,i,j; SG_VDE(g,v,d,e); #if !MAXN DYNALLOC1(shortish,work2,work2_sz,n,"adjacencies_sg"); #endif vwt = 1; for (i = 0; i < n; ++i) { work2[lab[i]] = vwt; if (ptn[i] <= level) ++vwt; invar[i] = 0; } for (i = 0; i < n; ++i) { vwt = FUZZ1(work2[i]); wwt = 0; di = d[i]; ei = e + v[i]; for (j = 0; j < di; ++j) { ACCUM(wwt,FUZZ2(work2[ei[j]])); ACCUM(invar[ei[j]],vwt); } ACCUM(invar[i],wwt); } } /***************************************************************************** * * * nausparse_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void nausparse_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in nausparse.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in nausparse.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in nausparse.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: nausparse.c version mismatch\n"); exit(1); } } /***************************************************************************** * * * nausparse_freedyn() - free the dynamic memory in this module * * * *****************************************************************************/ void nausparse_freedyn(void) { #if !MAXN DYNFREE(vmark1,vmark1_sz); DYNFREE(vmark2,vmark2_sz); DYNFREE(work1,work1_sz); DYNFREE(work2,work2_sz); DYNFREE(work3,work3_sz); DYNFREE(work4,work4_sz); #endif } nauty24r2/nautyex1.c0000600000604200001440000000601611274163463013234 0ustar bdmusers/* This program prints generators for the automorphism group of an n-vertex polygon, where n is a number supplied by the user. It needs to be linked with nauty.c, nautil.c and naugraph.c. This version uses a fixed limit for MAXN. */ #define MAXN 1000 /* Define this before including nauty.h */ #include "nauty.h" /* which includes and other system files */ int main(int argc, char *argv[]) { graph g[MAXN*MAXM]; int lab[MAXN],ptn[MAXN],orbits[MAXN]; static DEFAULTOPTIONS_GRAPH(options); statsblk stats; setword workspace[5*MAXM]; int n,m,v; set *gv; /* Default options are set by the DEFAULTOPTIONS_GRAPH macro above. * Here we change those options that we want to be different from the * defaults. writeautoms=TRUE causes automorphisms to be written. */ options.writeautoms = TRUE; while (1) { printf("\nenter n : "); if (scanf("%d",&n) != 1 || n <= 0) /* Exit if EOF or bad number */ break; if (n > MAXN) { printf("n must be in the range 1..%d\n",MAXN); exit(1); } /* The nauty parameter m is a value such that an array of * m setwords is sufficient to hold n bits. The type setword * is defined in nauty.h. The number of bits in a setword is * WORDSIZE, which is 16, 32 or 64. Here we calculate * m = ceiling(n/WORDSIZE). */ m = (n + WORDSIZE - 1) / WORDSIZE; /* The following optional call verifies that we are linking * to compatible versions of the nauty routines. */ nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); /* Now we create the cycle. For each v, we add the edges * (v,v+1) and (v,v-1), where values are mod n. gv is set to * the position in g[] where row v starts, EMPTYSET zeros it, * then ADDELEMENT adds one bit (a directed edge) to it. */ for (v = 0; v < n; ++v) { gv = GRAPHROW(g,v,m); EMPTYSET(gv,m); ADDELEMENT(gv,(v+n-1)%n); ADDELEMENT(gv,(v+1)%n); } printf("Generators for Aut(C[%d]):\n",n); /* Since we are not requiring a canonical labelling, the last * parameter to nauty() is noit required and can be NULL. * Similarly, we are not using a fancy active[] value, so we * can pass NULL to ask nauty() to use the default. */ nauty(g,lab,ptn,NULL,orbits,&options,&stats, workspace,5*MAXM,m,n,NULL); /* The size of the group is returned in stats.grpsize1 and * stats.grpsize2. See dreadnaut.c for code that will write the * value in a sensible format; here we will take advantage of * knowing that the size cannot be very large. Adding 0.1 is * just in case the floating value is truncated instead of rounded, * but that shouldn't be. */ printf("Automorphism group size = %.0f",stats.grpsize1+0.1); } exit(0); } nauty24r2/nautaux.c0000600000604200001440000002176311405400302013127 0ustar bdmusers/***************************************************************************** * * * Auxiliary procedures for use with nauty 2.4. * * None of these procedures are needed by nauty or by dreadnaut. * * * * Copyright (1984-2010) Brendan McKay. All rights reserved. * * Subject to waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 26-Apr-89 : initial creation for Version 1.5. * * 14-Oct-90 : renamed to version 1.6 (no changes to this file) * * 5-Jun-93 : renamed to version 1.7+ (no changes to this file) * * 18-Aug-93 : renamed to version 1.8 (no changes to this file) * * 17-Sep-93 : renamed to version 1.9 (no changes to this file) * * 24-Jan-00 : renamed to version 2.0 (no changes to this file) * * 16-Nov-00 : made changes listed in nauty.h * * 8-Aug-02 : updated for version 2.2 (dynamic storage) * * 3-Nov-04 : fixed names of nautaux_freedyn() and nautaux_check() * * 10-Dec-06 : removed BIGNAUTY * * * *****************************************************************************/ #define ONE_WORD_SETS #include "naututil.h" /* which includes "nauty.h" and */ #include "nautaux.h" #if MAXM==1 #define M 1 #else #define M m #endif #if !MAXN DYNALLSTAT(set,workset,workset_sz); DYNALLSTAT(permutation,workperm,workperm_sz); #else static set workset[MAXM]; /* used for scratch work */ static permutation workperm[MAXN+2]; #endif /***************************************************************************** * * * ptncode(g,lab,ptn,level,m,n) returns a long integer invariant which * * depends on the (assumed equitable) partition at the stated level, and * * the number of edges betwen the various cells. * * Neither nauty nor dreadnaut use this. * * * * GLOBALS ACCESSED: bit,setinter() * * * *****************************************************************************/ long ptncode(graph *g, int *lab, int *ptn, int level, int m, int n) { int i; long code; int v1,v2,nc,inter,cellend; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"testcanlab"); DYNALLOC1(set,workset,workset_sz,m,"testcanlab"); #endif /* find all cells: put starts in workperm[0..n] */ i = nc = 0; code = 0; while (i < n) { workperm[nc++] = i; code = ((code << 13) ^ (code >> 19)) + i; while (ptn[i] > level) ++i; ++i; } workperm[nc] = n; for (v2 = 0; v2 < nc; ++v2) { EMPTYSET(workset,m); for (i = workperm[v2], cellend = workperm[v2+1] - 1; i <= cellend; ++i) ADDELEMENT(workset,lab[i]); for (v1 = 0; v1 < nc; ++v1) { i = workperm[v1]; cellend = workperm[v1+1] - 1; inter = setinter(workset,GRAPHROW(g,lab[i],M),M); code = ((code << 13) ^ (code >> 19)) + inter; } } return(code); } /***************************************************************************** * * * equitable(g,lab,ptn,level,m,n) checks that the partition at the given * * level is equitable. Neither nauty nor dreadnaut use this. * * * * GLOBALS ACCESSED: bit,setinter() * * * *****************************************************************************/ boolean equitable(graph *g, int *lab, int *ptn, int level, int m, int n) { int i; int v1,v2,nc,inter,cellend; boolean ok; /* find all cells: put starts in workperm[0..n] */ #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"testcanlab"); DYNALLOC1(set,workset,workset_sz,m,"testcanlab"); #endif i = nc = 0; while (i < n) { workperm[nc++] = i; while (ptn[i] > level) ++i; ++i; } workperm[nc] = n; ok = TRUE; for (v2 = 0; v2 < nc && ok; ++v2) { EMPTYSET(workset,m); for (i = workperm[v2], cellend = workperm[v2+1] - 1; i <= cellend; ++i) ADDELEMENT(workset,lab[i]); for (v1 = 0; v1 < nc; ++v1) { i = workperm[v1]; cellend = workperm[v1+1] - 1; if (i == cellend) continue; inter = setinter(workset,GRAPHROW(g,lab[i],M),M); while (++i <= cellend) if (setinter(workset,GRAPHROW(g,lab[i],M),M) != inter) ok = FALSE; } } return ok; } /***************************************************************************** * * * component(g,v,c,m,n) determines the set of all vertices that can be * * reached along directed paths starting at vertex v, including v itself. * * This set is returned as c, unless c is null. The size of the set is * * returned as the function value. * * * * GLOBALS ACCESSED: bit,setinter(),nextelement() * * * *****************************************************************************/ int component(graph *g, int v, set *cmpt, int m, int n) { int i,z; set newverts[MAXM],*gx; int head,tail,x; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n+2,"testcanlab"); #endif EMPTYSET(workset,m); ADDELEMENT(workset,v); head = 0; tail = 1; workperm[head] = v; while (head < tail && tail < n) { x = workperm[head++]; gx = GRAPHROW(g,x,m); for (i = m; --i >= 0;) { newverts[i] = gx[i] & ~workset[i]; workset[i] |= gx[i]; } for (z = -1; (z = nextelement(newverts,m,z)) >= 0; ) workperm[tail++] = z; } if (cmpt != NULL) for (i = m; --i >= 0;) cmpt[i] = workset[i]; return tail; } /***************************************************************************** * * * nautaux_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void nautaux_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in nautaux.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in nautaux.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in nautaux.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: nautaux.c version mismatch\n"); exit(1); } } /***************************************************************************** * * * nautaux_freedyn() - free the dynamic memory in this module * * * *****************************************************************************/ void nautaux_freedyn(void) { #if !MAXN DYNFREE(workset,workset_sz); DYNFREE(workperm,workperm_sz); #endif } nauty24r2/copyg.c0000600000604200001440000001015611274163463012577 0ustar bdmusers/* copyg.c version 1.0; B D McKay, Jan 1997 */ #define USAGE "copyg [-gsfp#:#qhx] [infile [outfile]]" #define HELPTEXT \ " Copy a file of graphs with possible format conversion.\n\ \n\ -g Use graph6 format for output\n\ -s Use sparse6 format for output\n\ In the absence of -g and -s, the format depends on \n\ the header or, if none, the first input line.\n\ \n\ -p# -p#:# \n\ Specify range of input lines (first is 1)\n\ -f With -p, assume input lines of fixed length\n\ (ignored if header or first line has sparse6 format).\n\ \n\ -h Write a header.\n\ -x Don't write a header.\n\ In the absence of -h and -x, a header is written if\n\ there is one in the input.\n\ \n\ -q Suppress auxiliary output.\n" /***********************************************************************/ #include "gtools.h" main(int argc, char *argv[]) { graph *g; int m,n,codetype; char *infilename,*outfilename; FILE *infile,*outfile; int outcode; long nin; int argnum,j; char *arg,sw; boolean sswitch,fswitch,pswitch,qswitch,gswitch; boolean hswitch,xswitch; boolean badargs; long pval1,pval2,maxin; HELP; sswitch = fswitch = pswitch = FALSE; gswitch = qswitch = xswitch = hswitch = FALSE; infilename = outfilename = NULL; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('s',sswitch) else SWBOOLEAN('g',gswitch) else SWBOOLEAN('q',qswitch) else SWBOOLEAN('f',fswitch) else SWBOOLEAN('h',hswitch) else SWBOOLEAN('x',xswitch) else SWRANGE('p',":-",pswitch,pval1,pval2,"copyg -p") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (sswitch && gswitch) gt_abort(">E copyg: -s and -g are incompatible\n"); if (hswitch && xswitch) gt_abort(">E copyg: -h and -x are incompatible\n"); if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!qswitch) { fprintf(stderr,">A copyg"); if (sswitch || gswitch || fswitch || pswitch || xswitch || hswitch) fprintf(stderr," -"); if (sswitch) fprintf(stderr,"s"); if (gswitch) fprintf(stderr,"g"); if (hswitch) fprintf(stderr,"h"); if (xswitch) fprintf(stderr,"x"); if (fswitch) fprintf(stderr,"f"); if (pswitch) writerange(stderr,'p',pval1,pval2); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,fswitch, pswitch ? pval1 : 1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (sswitch || !gswitch && (codetype&SPARSE6)) outcode = SPARSE6; else outcode = GRAPH6; if (hswitch || !xswitch && (codetype&HAS_HEADER)) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } nin = 0; if (!pswitch || pval2 == NOLIMIT) maxin = NOLIMIT; else if (pval1 < 1) maxin = pval2; else maxin = pval2 - pval1 + 1; while (nin < maxin || maxin == NOLIMIT) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; if (outcode == readg_code) writelast(outfile); else if (outcode == SPARSE6) writes6(outfile,g,m,n); else writeg6(outfile,g,m,n); FREES(g); } if (!qswitch) fprintf(stderr,">Z %ld graphs copied from %s to %s\n", nin,infilename,outfilename); exit(0); } nauty24r2/rng.h0000600000604200001440000000222411274163463012246 0ustar bdmusers/* rng.h : definitions for using Don Knuth's random number generator. To use it: 1. Call ran_init(seed) with any long seed. (Optional, but you will always get the same sequence otherwise.) 2. Use NEXTRAN to get the next number (0..2^30-1). Alternatively, use KRAN(k) to get a random number 0..k-1. For large k, KRAN(k) is not quite uniform. In that case use GETKRAN(k,var) to set the variable var to a better random number 0..k-1. Some of these definitions are also in naututil.h. */ #ifdef __cplusplus extern "C" { #endif extern long *ran_arr_ptr; long ran_arr_cycle(void); void ran_init(long seed); void ran_array(long *aa, int n); #ifdef __cplusplus } #endif #define MAXRAN (0x3fffffffL) /* Values are 0..MAXRAN */ #define NEXTRAN (*ran_arr_ptr>=0 ? *ran_arr_ptr++ : ran_arr_cycle()) #define KRAN(k) (NEXTRAN%(k)) #define RANREAL ((NEXTRAN+0.5)/(MAXRAN+1.0)) /* Uniform (0,1) */ #define MAXSAFE(k) (((MAXRAN+1)/(k))*(k)) #define GETKRAN(k,var) {long __getkran; \ do {__getkran = NEXTRAN;} while (__getkran >= MAXSAFE(k)); \ var = __getkran % (k);} #define INITRANBYTIME ran_init((long)time(NULL)) nauty24r2/planarg.c0000600000604200001440000002274011274163463013104 0ustar bdmusers/* planarg : test for planarity and find embedding or obstruction */ #define USAGE "planarg [-v] [-nVq] [-p|-u] [infile [outfile]]" #define HELPTEXT \ " For each input, write to output if planar.\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -v Write non-planar graphs instead of planar graphs\n\ -V Write report on every input\n\ -u Don't write anything, just count\n\ -p Write in planar_code if planar (without -p, same format as input)\n\ -k Follow each non-planar output with an obstruction in sparse6\n\ format (implies -v, incompatible with -p)\n\ -n Suppress checking of the result\n\ -q Suppress auxiliary information\n\ \n\ This program permits multiple edges and loops\n" /*************************************************************************/ #include "gtools.h" #include "planarity.h" /*************************************************************************/ static void write_planarcode(FILE *f, t_ver_sparse_rep *VR, t_adjl_sparse_rep *A, t_embed_sparse_rep *ER, int n, int ne) /* Write the embedding to f in planar_code */ { int bytes; size_t i,j,len,k,k0; unsigned int w; DYNALLSTAT(unsigned char,buff,buff_sz); #define PUT1(x) buff[j++]=(x); #define PUT2(x) w=(x); buff[j++]=(w>>8)&0xFF; buff[j++]=w&0xff; #define PUT4(x) w=(x); buff[j++]=(w>>24)&0xFF; buff[j++]=(x>>16)&0xff; \ buff[j++]=(w>>8)&0xFF; buff[j++]=w&0xff; if (n <= 255) bytes = 1; else if (n <= 65535) bytes = 2; else bytes = 4; len = bytes * (1 + n + 2*(size_t)ne); if (bytes == 2) len += 1; else if (bytes == 4) len += 3; DYNALLOC1(unsigned char,buff,buff_sz,len,"planarg"); if (bytes == 1) { j = 0; PUT1(n); for (i = 0; i < n; ++i) { k = k0 = VR[i].first_edge; if (k != NIL) do { PUT1(A[ER[k].in_adjl].end_vertex+1); k = ER[k].next; } while (k != k0); PUT1(0); } } else if (bytes == 2) { j = 0; PUT1(0); PUT2(n); for (i = 0; i < n; ++i) { k = k0 = VR[i].first_edge; if (k != NIL) do { PUT2(A[ER[k].in_adjl].end_vertex+1); k = ER[k].next; } while (k != k0); PUT2(0); } } else { j = 0; PUT1(0); PUT2(0); PUT4(n); for (i = 0; i < n; ++i) { k = k0 = VR[i].first_edge; if (k != NIL) do { PUT4(A[ER[k].in_adjl].end_vertex+1); k = ER[k].next; } while (k != k0); PUT4(0); } } if (fwrite((void*)buff,1,len,f) != len) { fprintf(stderr,">E write_planarcode : error on writing\n"); ABORT(">E write_planarcode"); } } /*************************************************************************/ static boolean isplanar(t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int e, int *c, t_ver_sparse_rep **VR, t_adjl_sparse_rep **AR, t_embed_sparse_rep **ER, int *nbr_e_obs, boolean planarcheck, boolean nonplanarcheck) /* The input graph is given as an adjacency list: V: array of vertices n: size of graph A: adjacency list e: number of edges If the graph is planar the embedding is stored in VR and ER; the embedding contains e edges (nbr_e_obs not used) If the graph is non planar the obstruction is returned in VR and AR together with the number of edges in nbr_e_obs. In all cases the number of components is return in c. planarcheck and nonplanarcheck determine if checking is done. The embedding and obstruction outputs are only made if the appropriate checking is done. */ { t_dlcl **dfs_tree, **back_edges, **mult_edges; int edge_pos, v, w; boolean ans; t_ver_edge *embed_graph; ans = sparseg_adjl_is_planar(V, n, A, c, &dfs_tree, &back_edges, &mult_edges, &embed_graph, &edge_pos, &v, &w); if (!ans && nonplanarcheck) { embedg_obstruction(V, A, dfs_tree, back_edges, embed_graph, n, &edge_pos, v, w, VR, AR, nbr_e_obs); } else if (planarcheck) { embedg_embedding(V, A, embed_graph, n, e, *c, edge_pos, mult_edges, VR, ER); } sparseg_dlcl_delete(dfs_tree, n); sparseg_dlcl_delete(back_edges, n); sparseg_dlcl_delete(mult_edges, n); embedg_VES_delete(embed_graph, n); return ans; } /*************************************************************************/ main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile,*outfile; sparsegraph sg; boolean badargs; boolean verbose,nonplanar,quiet; boolean planarcode,nowrite,nocheck; int i,j,k,n,v,w,argnum,ne,loops; int codetype,outcode; t_ver_sparse_rep *VR; t_adjl_sparse_rep *AR; t_embed_sparse_rep *ER; int nbr_c,nbr_e_obs,size_A,pos_in_A; unsigned long nin,nout,nplan; char *arg,sw; double t0,tp,tnp,netotalp,netotalnp; DYNALLSTAT(t_ver_sparse_rep,V,V_sz); DYNALLSTAT(t_adjl_sparse_rep,A,A_sz); HELP; infilename = outfilename = NULL; badargs = FALSE; quiet = nowrite = planarcode = FALSE; verbose = nonplanar = nocheck = FALSE; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('v',nonplanar) else SWBOOLEAN('q',quiet) else SWBOOLEAN('V',verbose) else SWBOOLEAN('p',planarcode) else SWBOOLEAN('u',nowrite) else SWBOOLEAN('n',nocheck) else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); exit(1); } if (planarcode && nonplanar) { fprintf(stderr,">E planarg: -p and -v are incompatible\n"); exit(1); } if (!quiet) { fprintf(stderr,">A planarg"); if (nonplanar||planarcode||nowrite||nocheck) fprintf(stderr," -"); if (nonplanar) fprintf(stderr,"v"); if (nowrite) fprintf(stderr,"u"); if (planarcode) fprintf(stderr,"p"); if (nocheck) fprintf(stderr,"n"); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!nowrite) { if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (planarcode) outcode = PLANARCODE; else if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (outcode == PLANARCODE) writeline(outfile,PLANARCODE_HEADER); else if (codetype&HAS_HEADER) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } } nin = nout = nplan = 0; netotalp = netotalnp = 0.0; SG_INIT(sg); tp = tnp = 0.0; while (TRUE) { if (read_sg_loops(infile,&sg,&loops) == NULL) break; n = sg.nv; ne = (sg.nde+loops)/2; ++nin; DYNALLOC1(t_ver_sparse_rep,V,V_sz,n,"planarg"); DYNALLOC1(t_adjl_sparse_rep,A,A_sz,2*ne+1,"planarg"); k = 0; for (i = 0; i < n; ++i) if (sg.d[i] == 0) V[i].first_edge = NIL; else { V[i].first_edge = k; for (j = sg.v[i]; j < sg.v[i]+sg.d[i]; ++j) { A[k].end_vertex = sg.e[j]; A[k].next = k+1; ++k; if (A[k-1].end_vertex == i) /* loops go in twice */ { A[k].end_vertex = i; A[k].next = k+1; k++; } } A[k-1].next = NIL; } if (k != 2*ne) { fprintf(stderr,">E planarg: decoding error; nin=%lu\n",nin); fprintf(stderr,"n=%d nde=%d ne=%d loops=%d\n", n,sg.nde,ne,loops); exit(1); } VR = NULL; AR = NULL; ER = NULL; t0 = CPUTIME; if (isplanar(V,n,A,ne,&nbr_c,&VR,&AR,&ER,&nbr_e_obs, !nocheck||planarcode,!nocheck)) { ++nplan; tp += CPUTIME - t0; netotalp += ne; if (!nowrite && !nonplanar) { if (planarcode) write_planarcode(outfile,VR,A,ER,n,ne); else writelast(outfile); ++nout; } if (verbose) fprintf(stderr,"graph %lu: n=%d ne=%d planar\n", nin,n,ne); } else { tnp += CPUTIME - t0; netotalnp += ne; if (!nowrite && nonplanar) { writelast(outfile); ++nout; } if (verbose) fprintf(stderr,"graph %lu: n=%d ne=%d non-planar\n", nin,n,ne); } FREES(VR); FREES(AR); FREES(ER); } if (!nowrite) { if (!quiet) fprintf(stderr, ">Z %lu graphs read from %s, %lu written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,tp+tnp); } else { fprintf(stderr, " %9lu graphs input\n %9lu graphs planar\n",nin,nplan); fprintf(stderr," cpu = %3.2f sec. ",tp+tnp); if (netotalp) fprintf(stderr," planar:%.3f",1e5*tp/netotalp); if (netotalnp) fprintf(stderr," nonplanar:%.3f",1e5*tnp/netotalnp); fprintf(stderr,"\n"); } return 0; } nauty24r2/nautyex5.c0000600000604200001440000001031311274163463013233 0ustar bdmusers/* This program demonstrates how an isomorphism is found between graphs of the form in the figure above, for general size. It needs to be linked with nauty.c, nautil.c and nausparse.c. This version uses sparse form with dynamic allocation. */ #include "nausparse.h" /* which includes nauty.h */ int main(int argc, char *argv[]) { DYNALLSTAT(int,lab1,lab1_sz); DYNALLSTAT(int,lab2,lab2_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(setword,workspace,workspace_sz); DYNALLSTAT(int,map,map_sz); static DEFAULTOPTIONS_SPARSEGRAPH(options); statsblk stats; sparsegraph sg1,sg2,cg1,cg2; /* Declare sparse graph structures */ int n,m,i; /* Select option for canonical labelling */ options.getcanon = TRUE; /* Initialise sparse graph structure. */ SG_INIT(sg1); SG_INIT(sg2); SG_INIT(cg1); SG_INIT(cg2); while (1) { printf("\nenter n : "); if (scanf("%d",&n) == 1 && n > 0) { if (n%2 != 0) { fprintf(stderr,"Sorry, n must be even\n"); continue; } m = (n + WORDSIZE - 1) / WORDSIZE; nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); DYNALLOC1(int,lab1,lab1_sz,n,"malloc"); DYNALLOC1(int,lab2,lab2_sz,n,"malloc"); DYNALLOC1(int,ptn,ptn_sz,n,"malloc"); DYNALLOC1(int,orbits,orbits_sz,n,"malloc"); DYNALLOC1(setword,workspace,workspace_sz,2*m,"malloc"); DYNALLOC1(int,map,map_sz,n,"malloc"); /* Now make the first graph */ SG_ALLOC(sg1,n,3*n,"malloc"); sg1.nv = n; /* Number of vertices */ sg1.nde = 3*n; /* Number of directed edges */ for (i = 0; i < n; ++i) { sg1.v[i] = 3*i; sg1.d[i] = 3; } for (i = 0; i < n; i += 2) sg1.e[sg1.v[i]] = i+1; for (i = 1; i < n; i += 2) sg1.e[sg1.v[i]] = i-1; for (i = 0; i < n; ++i) { sg1.e[sg1.v[i]+1] = i+2; sg1.e[sg1.v[i]+2] = i-2; } sg1.e[sg1.v[0]+2] = n-1; sg1.e[sg1.v[1]+2] = n-2; sg1.e[sg1.v[n-2]+1] = 1; sg1.e[sg1.v[n-1]+1] = 0; /* Now make the second graph */ SG_ALLOC(sg2,n,3*n,"malloc"); sg2.nv = n; /* Number of vertices */ sg2.nde = 3*n; /* Number of directed edges */ for (i = 0; i < n; ++i) { sg2.v[i] = 3*i; sg2.d[i] = 3; } for (i = 0; i < n; ++i) { sg2.v[i] = 3*i; sg2.d[i] = 3; sg2.e[sg2.v[i]] = (i+1) % n; sg2.e[sg2.v[i]+1] = (i+n-1) % n; sg2.e[sg2.v[i]+2] = (i+n/2) % n; } /* Label sg1, result in cg1 and labelling in lab1; similarly sg1. It is not necessary to pre-allocate space in cg1 and cg2, but they have to be initialised as we did above. */ nauty((graph*)&sg1,lab1,ptn,NULL,orbits,&options,&stats, workspace,2*m,m,n,(graph*)&cg1); nauty((graph*)&sg2,lab2,ptn,NULL,orbits,&options,&stats, workspace,2*m,m,n,(graph*)&cg2); /* Compare canonically labelled graphs */ if (aresame_sg(&cg1,&cg2)) { printf("Isomorphic.\n"); if (n <= 1000) { /* Write the isomorphism. For each i, vertex lab1[i] of sg1 maps onto vertex lab2[i] of sg2. We compute the map in order of labelling because it looks better. */ for (i = 0; i < n; ++i) map[lab1[i]] = lab2[i]; for (i = 0; i < n; ++i) { printf(" %d-%d",i,map[i]); } printf("\n"); } } else printf("Not isomorphic.\n"); } else break; } exit(0); } nauty24r2/nauty.h0000600000604200001440000013533411405400302012607 0ustar bdmusers/************************************************************************** * This is the header file for Version 2.4 of nauty(). * * nauty.h. Generated from nauty-h.in by configure. **************************************************************************/ #ifndef _NAUTY_H_ /* only process this file once */ #define _NAUTY_H_ /* The parts between the ==== lines are modified by configure when creating nauty.h out of nauty-h.in. If configure is not being used, it is necessary to check they are correct. ====================================================================*/ /* Check whether various headers are available */ #define HAVE_UNISTD_H 1 /* */ #define HAVE_SYSTYPES_H 1 /* */ #define HAVE_STDDEF_H 1 /* */ #define HAVE_STDLIB_H 1 /* */ #define HAVE_STRING_H 1 /* */ #define MALLOC_DEC 1 /* 1 = malloc() is declared in stdlib.h, 2 = in malloc.h, 0 = in neither place */ #define HAS_MATH_INF 0 /* INFINITY is defined in math.h or some system header likely to be used */ #define HAS_STDIO_UNLOCK 1 /* Whether there are getc_unlocked, putc_unlocked,flockfile and funlockfile*/ #define SIZEOF_INT 4 #define SIZEOF_LONG 4 #define SIZEOF_LONG_LONG 8 /* 0 if nonexistent */ #define HAVE_CONST 1 /* compiler properly supports const */ /*==================================================================*/ /* The following line must be uncommented for compiling into Magma. */ /* #define NAUTY_IN_MAGMA */ #ifdef NAUTY_IN_MAGMA #include "defs.h" #include "system.h" #include "bs.h" #define OLDEXTDEFS #else #include #define P_(x) x #endif #if defined(__cray) || defined(__cray__) || defined(cray) #define SYS_CRAY /* Cray UNIX, portable or standard C */ #endif #if defined(__unix) || defined(__unix__) || defined(unix) #define SYS_UNIX #endif #if !HAVE_CONST #define const #endif /***************************************************************************** * * * AUTHOR: Brendan D. McKay * * School of Computer Science * * Australian National University * * Canberra, ACT 0200, Australia * * phone: +61 2 6125 3845 fax: +61 2 6125 0010 * * email: bdm@cs.anu.edu.au * * * * Copyright (1984-2010) Brendan McKay. All rights reserved. Permission * * is hereby given for use and/or distribution with the exception of * * sale for profit or application with nontrivial military significance. * * You must not remove this copyright notice, and you must document any * * changes that you make to this program. * * This software is subject to this copyright only, irrespective of * * any copyright attached to any package of which this is a part. * * * * This program is only provided "as is". No responsibility will be taken * * by the author, his employer or his pet rabbit* for any misfortune which * * befalls you because of its use. I don't think it will delete all your * * files, burn down your computer room or turn your children against you, * * but if it does: stiff cheddar. On the other hand, I very much welcome * * bug reports, or at least I would if there were any bugs. * * * RIP, 1989 * * * * If you wish to acknowledge use of this program in published articles, * * please do so by citing the User's Guide: * * * * B. D. McKay, nauty User's Guide (Version 2.4), * http://cs.anu.edu.au/~bdm/nauty/. * * * CHANGE HISTORY * * 10-Nov-87 : final changes for version 1.2 * * 5-Dec-87 : renamed to version 1.3 (no changes to this file) * * 28-Sep-88 : added PC Turbo C support, making version 1.4 * * 23-Mar-89 : changes for version 1.5 : * * - reworked M==1 code * * - defined NAUTYVERSION string * * - made NAUTYH_READ to allow this file to be read twice * * - added optional ANSI function prototypes * * - added validity check for WORDSIZE * * - added new fields to optionblk structure * * - updated DEFAULTOPTIONS to add invariants fields * * - added (set*) cast to definition of GRAPHROW * * - added definition of ALLOCS and FREES * * 25-Mar-89 : - added declaration of new function doref() * * - added UNION macro * * 29-Mar-89 : - reduced the default MAXN for small machines * * - removed OUTOFSPACE (no longer used) * * - added SETDIFF and XOR macros * * 2-Apr-89 : - extended statsblk structure * * 4-Apr-89 : - added IS_* macros * * - added ERRFILE definition * * - replaced statsblk.outofspace by statsblk.errstatus * * 5-Apr-89 : - deleted definition of np2vector (no longer used) * * - introduced EMPTYSET macro * * 12-Apr-89 : - eliminated MARK, UNMARK and ISMARKED (no longer used) * * 18-Apr-89 : - added MTOOBIG and CANONGNIL * * 12-May-89 : - made ISELEM1 and ISELEMENT return 0 or 1 * * 2-Mar-90 : - added EXTPROC macro and used it * * 12-Mar-90 : - added SYS_CRAY, with help from N. Sloane and A. Grosky * * - added dummy groupopts field to optionblk * * - select some ANSI things if __STDC__ exists * * 20-Mar-90 : - changed default MAXN for Macintosh versions * * - created SYS_MACTHINK for Macintosh THINK compiler * * 27-Mar-90 : - split SYS_MSDOS into SYS_PCMS4 and SYS_PCMS5 * * 13-Oct-90 : changes for version 1.6: * * - fix definition of setword for WORDSIZE==64 * * 14-Oct-90 : - added SYS_APOLLO version to avoid compiler bug * * 15-Oct-90 : - improve detection of ANSI conformance * * 17-Oct-90 : - changed temp name in EMPTYSET to avoid A/UX bug * * 16-Apr-91 : changes for version 1.7: * * - made version SYS_PCTURBO use free(), not cfree() * * 2-Sep-91 : - noted that SYS_PCMS5 also works for Quick C * * - moved MULTIPLY to here from nauty.c * * 12-Jun-92 : - changed the top part of this comment * * 27-Aug-92 : - added version SYS_IBMC, thanks to Ivo Duentsch * * 5-Jun-93 : - renamed to version 1.7+, only change in naututil.h * * 29-Jul-93 : changes for version 1.8: * * - fixed error in default 64-bit version of FIRSTBIT * * (not used in any version before ALPHA) * * - installed ALPHA version (thanks to Gordon Royle) * * - defined ALLOCS,FREES for SYS_IBMC * * 3-Sep-93 : - make calloc void* in ALPHA version * * 17-Sep-93 : - renamed to version 1.9, * * changed only dreadnaut.c and nautinv.c * * 24-Feb-94 : changes for version 1.10: * * - added version SYS_AMIGAAZT, thanks to Carsten Saager * * (making 1.9+) * * 19-Apr-95 : - added prototype wrapper for C++, * * thanks to Daniel Huson * * 5-Mar-96 : - added SYS_ALPHA32 version (32-bit setwords on Alpha) * * 13-Jul-96 : changes for version 2.0: * * - added dynamic allocation * * - ERRFILE must be defined * * - added FLIPELEM1 and FLIPELEMENT macros * * 13-Aug-96 : - added SWCHUNK? macros * * - added TAKEBIT macro * * 28-Nov-96 : - include sys/types.h if not ANSI (tentative!) * * 24-Jan-97 : - and stdlib.h if ANSI * * - removed use of cfree() from UNIX variants * * 25-Jan-97 : - changed options.getcanon from boolean to int * * Backwards compatibility is ok, as boolean and int * * are the same. Now getcanon=2 means to get the label * * and not care about the group. Sometimes faster. * * 6-Feb-97 : - Put in #undef for FALSE and TRUE to cope with * * compilers that illegally predefine them. * * - declared nauty_null and nautil_null * * 2-Jul-98 : - declared ALLBITS * * 21-Oct-98 : - allow WORDSIZE==64 using unsigned long long * * - added BIGNAUTY option for really big graphs * * 11-Dec-99 : - made bit, leftbit and bytecount static in each file * * 9-Jan-00 : - declared nauty_check() and nautil_check() * * 12-Feb-00 : - Used #error for compile-time checks * * - Added DYNREALLOC * * 4-Mar-00 : - declared ALLMASK(n) * * 27-May-00 : - declared CONDYNFREE * * 28-May-00 : - declared nautil_freedyn() * * 16-Aug-00 : - added OLDNAUTY and changed canonical labelling * * 16-Nov-00 : - function prototypes are now default and unavoidable * * - removed UPROC, now assume all compilers know void * * - removed nvector, now just int (as it always was) * * - added extra parameter to targetcell() * * - removed old versions which were only to skip around * * bugs that should have been long fixed: * * SYS_APOLLO and SYS_VAXBSD. * * - DEFAULTOPIONS now specifies no output * * - Removed obsolete SYS_MACLSC version * * 21-Apr-01 : - Added code to satisfy compilation into Magma. This * * is activated by defining NAUTY_IN_MAGMA above. * * - The *_null routines no longer exist * * - Default maxinvarlevel is now 1. (This has no effect * * unless an invariant is specified.) * * - Now labelorg has a concrete declaration in nautil.c * * and EXTDEFS is not needed * * 5-May-01 : - NILFUNCTION, NILSET, NILGRAPH now obsolete. Use NULL. * * 11-Sep-01 : - setword is unsigned int in the event that UINT_MAX * * is defined and indicates it is big enough * * 17-Oct-01 : - major rewrite for 2.1. SYS_* variables gone! * * Some modernity assumed, eg size_t * * 8-Aug-02 : - removed MAKEEMPTY (use EMPTYSET instead) * * - deleted OLDNAUTY everywhere * * 27-Aug-02 : - converted to use autoconf. Now the original of this * * file is nauty-h.in. Run configure to make nauty.h. * * 20-Dec-02 : - increased INFINITY * * some reorganization to please Magma * * - declared nauty_freedyn() * * 17-Nov-03 : - renamed INFINITY to NAUTY_INFINITY * * 29-May-04 : - added definition of SETWORD_FORMAT * * 14-Sep-04 : - extended prototypes even to recursive functions * * 16-Oct-04 : - added DEFAULTOPTIONS_GRAPH * * 24-Oct-04 : Starting 2.3 * * - remove register declarations as modern compilers * * tend to find them a nuisance * * - Don't define the obsolete symbol INFINITY if it is * * defined already * * 17-Nov-04 : - make 6 counters in statsblk unsigned long * * 17-Jan-04 : - add init() and cleanup() to dispatchvec * * 12-Nov-05 : - Changed NAUTY_INFINITY to 2^30+2 in BIGNAUTY case * * 22-Nov-06 : Starting 2.4 * * - removed usertcellproc from options * * changed bestcell to targetcell in dispatch vector * * declare targetcell and maketargetcell * * 29-Nov-06 : - add extraoptions to optionblk * * - add declarations of extra_autom and extra_level * * 10-Dec-06 : - BIGNAUTY is gone! Now permutation=shortish=int. * * NAUTY_INFINITY only depends on whether sizeof(int)=2. * * 27-Jun-08 : - define nauty_counter and LONG_LONG_COUNTERS * * 30-Jun-08 : - declare version 2.4 * * 14-Jun-10 : Maintenance release 2.4r1 * * * * nauty.h. Generated from nauty-h.in by configure. * * *****************************************************************************/ /***************************************************************************** * * * 16-bit, 32-bit and 64-bit versions can be selected by defining WORDSIZE. * * The largest graph that can be handled has MAXN vertices. * * Both WORDSIZE and MAXN can be defined on the command line. * * WORDSIZE must be 16, 32 or 64; MAXN must be <= NAUTY_INFINITY-2; * * * * With a very slight loss of efficiency (depending on platform), nauty * * can be compiled to dynamically allocate arrays. Predefine MAXN=0 to * * achieve this effect, which is default behaviour from version 2.0. * * In that case, graphs of size up to NAUTY_INFINITY-2 can be handled * * if the the memory is available. * * * * If only very small graphs need to be processed, use MAXN<=WORDSIZE * * since this causes substantial code optimizations. * * * * Conventions and Assumptions: * * * * A 'setword' is the chunk of memory that is occupied by one part of * * a set. This is assumed to be >= WORDSIZE bits in size. * * * * The rightmost (loworder) WORDSIZE bits of setwords are numbered * * 0..WORDSIZE-1, left to right. It is necessary that the 2^WORDSIZE * * setwords with the other bits zero are totally ordered under <,=,>. * * This needs care on a 1's-complement machine. * * * * The int variables m and n have consistent meanings throughout. * * Graphs have n vertices always, and sets have m setwords always. * * * * A 'set' consists of m contiguous setwords, whose bits are numbered * * 0,1,2,... from left (high-order) to right (low-order), using only * * the rightmost WORDSIZE bits of each setword. It is used to * * represent a subset of {0,1,...,n-1} in the usual way - bit number x * * is 1 iff x is in the subset. Bits numbered n or greater, and * * unnumbered bits, are assumed permanently zero. * * * * A 'graph' consists of n contiguous sets. The i-th set represents * * the vertices adjacent to vertex i, for i = 0,1,...,n-1. * * * * A 'permutation' is an array of n ints repesenting a permutation of * * the set {0,1,...,n-1}. The value of the i-th entry is the number to * * which i is mapped. * * * * If g is a graph and p is a permutation, then g^p is the graph in * * which vertex i is adjacent to vertex j iff vertex p[i] is adjacent * * to vertex p[j] in g. * * * * A partition nest is represented by a pair (lab,ptn), where lab and ptn * * are int arrays. The "partition at level x" is the partition whose * * cells are {lab[i],lab[i+1],...,lab[j]}, where [i,j] is a maximal * * subinterval of [0,n-1] such that ptn[k] > x for i <= k < j and * * ptn[j] <= x. The partition at level 0 is given to nauty by the user. * * This is refined for the root of the tree, which has level 1. * * * *****************************************************************************/ #define NAUTYVERSIONID 2400 /* 1000 times the version number */ #define NAUTYREQUIRED 2400 /* Minimum compatible version */ #ifndef NAUTY_IN_MAGMA #if HAVE_SYSTYPES_H #include #endif #if HAVE_UNISTD_H #include #endif #if HAVE_STDDEF_H #include #endif #if HAVE_STDLIB_H #include #endif #if HAVE_STRING_H #include #else #include #endif #endif /* WORDSIZE is the number of set elements per setword (16, 32 or 64). Starting at version 2.2, WORDSIZE and setword are defined as follows: If WORDSIZE is so far undefined, use 32 unless longs have more than 32 bits, in which case use 64. Define setword thus: WORDSIZE==16 : unsigned short WORDSIZE==32 : unsigned int unless it is too small, in which case unsigned long WORDSIZE==64 : the first of unsigned int, unsigned long, unsigned long long, which is large enough. */ #ifdef NAUTY_IN_MAGMA #undef WORDSIZE #define WORDSIZE WORDBITS #endif #ifdef WORDSIZE #if (WORDSIZE != 16) && (WORDSIZE != 32) && (WORDSIZE != 64) #error "WORDSIZE must be 16, 32 or 64" #endif #else /* WORDSIZE undefined */ #if SIZEOF_LONG>4 #define WORDSIZE 64 #else #define WORDSIZE 32 #endif #endif /* WORDSIZE */ #ifdef NAUTY_IN_MAGMA typedef t_uint setword; #define SETWORD_INT /* Don't assume this is correct in Magma. */ #else /* NAUTY_IN_MAGMA */ #if WORDSIZE==16 typedef unsigned short setword; #define SETWORD_SHORT #endif #if WORDSIZE==32 #if SIZEOF_INT>=4 typedef unsigned int setword; #define SETWORD_INT #else typedef unsigned long setword; #define SETWORD_LONG #endif #endif #if WORDSIZE==64 #if SIZEOF_INT>=8 typedef unsigned int setword; #define SETWORD_INT #else #if SIZEOF_LONG>=8 typedef unsigned long setword; #define SETWORD_LONG #else typedef unsigned long long setword; #define SETWORD_LONGLONG #endif #endif #endif #endif /* NAUTY_IN_MAGMA else */ #if SIZEOF_LONG_LONG>=8 && SIZEOF_LONG==4 typedef unsigned long long nauty_counter; #define LONG_LONG_COUNTERS 1 #else typedef unsigned long nauty_counter; #define LONG_LONG_COUNTERS 0 #endif #if WORDSIZE==16 #define NAUTYVERSION "2.4 (16 bits)" #endif #if WORDSIZE==32 #define NAUTYVERSION "2.4 (32 bits)" #endif #if WORDSIZE==64 #define NAUTYVERSION "2.4 (64 bits)" #endif #ifndef MAXN /* maximum allowed n value; use 0 for dynamic sizing. */ #define MAXN 0 #define MAXM 0 #else #define MAXM ((MAXN+WORDSIZE-1)/WORDSIZE) /* max setwords in a set */ #endif /* MAXN */ /* Starting at version 2.2, set operations work for all set sizes unless ONE_WORD_SETS is defined. In the latter case, if MAXM=1, set ops work only for single-setword sets. In any case, macro versions ending with 1 work for single-setword sets and versions ending with 0 work for all set sizes. */ #if WORDSIZE==16 #define SETWD(pos) ((pos)>>4) /* number of setword containing bit pos */ #define SETBT(pos) ((pos)&0xF) /* position within setword of bit pos */ #define TIMESWORDSIZE(w) ((w)<<4) #endif #if WORDSIZE==32 #define SETWD(pos) ((pos)>>5) #define SETBT(pos) ((pos)&0x1F) #define TIMESWORDSIZE(w) ((w)<<5) #endif #if WORDSIZE==64 #define SETWD(pos) ((pos)>>6) #define SETBT(pos) ((pos)&0x3F) #define TIMESWORDSIZE(w) ((w)<<6) /* w*WORDSIZE */ #endif #ifdef NAUTY_IN_MAGMA #define BITT bs_bit #else #define BITT bit #endif #define ADDELEMENT1(setadd,pos) (*(setadd) |= BITT[pos]) #define DELELEMENT1(setadd,pos) (*(setadd) &= ~BITT[pos]) #define FLIPELEMENT1(setadd,pos) (*(setadd) ^= BITT[pos]) #define ISELEMENT1(setadd,pos) ((*(setadd) & BITT[pos]) != 0) #define EMPTYSET1(setadd,m) *(setadd) = 0; #define GRAPHROW1(g,v,m) ((set*)(g) + (v)) #define ADDELEMENT0(setadd,pos) ((setadd)[SETWD(pos)] |= BITT[SETBT(pos)]) #define DELELEMENT0(setadd,pos) ((setadd)[SETWD(pos)] &= ~BITT[SETBT(pos)]) #define FLIPELEMENT0(setadd,pos) ((setadd)[SETWD(pos)] ^= BITT[SETBT(pos)]) #define ISELEMENT0(setadd,pos) (((setadd)[SETWD(pos)] & BITT[SETBT(pos)]) != 0) #define EMPTYSET0(setadd,m) \ {setword *es; \ for (es = (setword*)(setadd)+(m); --es >= (setword*)(setadd);) *es=0;} #define GRAPHROW0(g,v,m) ((set*)(g) + (long)(v)*(long)(m)) #if (MAXM==1) && defined(ONE_WORD_SETS) #define ADDELEMENT ADDELEMENT1 #define DELELEMENT DELELEMENT1 #define FLIPELEMENT FLIPELEMENT1 #define ISELEMENT ISELEMENT1 #define EMPTYSET EMPTYSET1 #define GRAPHROW GRAPHROW1 #else #define ADDELEMENT ADDELEMENT0 #define DELELEMENT DELELEMENT0 #define FLIPELEMENT FLIPELEMENT0 #define ISELEMENT ISELEMENT0 #define EMPTYSET EMPTYSET0 #define GRAPHROW GRAPHROW0 #endif #ifdef NAUTY_IN_MAGMA #undef EMPTYSET #define EMPTYSET(setadd,m) {t_int _i; bsp_makeempty(setadd,m,_i);} #endif #define NOTSUBSET(word1,word2) ((word1) & ~(word2)) /* test if the 1-bits in setword word1 do not form a subset of those in word2 */ #define INTERSECT(word1,word2) ((word1) &= (word2)) /* AND word2 into word1 */ #define UNION(word1,word2) ((word1) |= (word2)) /* OR word2 into word1 */ #define SETDIFF(word1,word2) ((word1) &= ~(word2)) /* - word2 into word1 */ #define XOR(word1,word2) ((word1) ^= (word2)) /* XOR word2 into word1 */ #define ZAPBIT(word,x) ((word) &= ~BITT[x]) /* delete bit x in setword */ #define TAKEBIT(iw,w) {iw = FIRSTBIT(w); w ^= BITT[iw];} #ifdef SETWORD_LONGLONG #define MSK3232 0xFFFFFFFF00000000ULL #define MSK1648 0xFFFF000000000000ULL #define MSK0856 0xFF00000000000000ULL #define MSK1632 0x0000FFFF00000000ULL #define MSK0840 0xFF0000000000ULL #define MSK1616 0xFFFF0000ULL #define MSK0824 0xFF000000ULL #define MSK0808 0xFF00ULL #define MSK63C 0x7FFFFFFFFFFFFFFFULL #define MSK31C 0x7FFFFFFFULL #define MSK15C 0x7FFFULL #define MSK64 0xFFFFFFFFFFFFFFFFULL #define MSK32 0xFFFFFFFFULL #define MSK16 0xFFFFULL #endif #ifdef SETWORD_LONG #define MSK3232 0xFFFFFFFF00000000UL #define MSK1648 0xFFFF000000000000UL #define MSK0856 0xFF00000000000000UL #define MSK1632 0x0000FFFF00000000UL #define MSK0840 0xFF0000000000UL #define MSK1616 0xFFFF0000UL #define MSK0824 0xFF000000UL #define MSK0808 0xFF00UL #define MSK63C 0x7FFFFFFFFFFFFFFFUL #define MSK31C 0x7FFFFFFFUL #define MSK15C 0x7FFFUL #define MSK64 0xFFFFFFFFFFFFFFFFUL #define MSK32 0xFFFFFFFFUL #define MSK16 0xFFFFUL #endif #if defined(SETWORD_INT) || defined(SETWORD_SHORT) #define MSK3232 0xFFFFFFFF00000000U #define MSK1648 0xFFFF000000000000U #define MSK0856 0xFF00000000000000U #define MSK1632 0x0000FFFF00000000U #define MSK0840 0xFF0000000000U #define MSK1616 0xFFFF0000U #define MSK0824 0xFF000000U #define MSK0808 0xFF00U #define MSK63C 0x7FFFFFFFFFFFFFFFU #define MSK31C 0x7FFFFFFFU #define MSK15C 0x7FFFU #define MSK64 0xFFFFFFFFFFFFFFFFU #define MSK32 0xFFFFFFFFU #define MSK16 0xFFFFU #endif #if defined(SETWORD_LONGLONG) #if WORDSIZE==16 #define SETWORD_FORMAT "%04llx" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08llx" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16llx" #endif #endif #if defined(SETWORD_LONG) #if WORDSIZE==16 #define SETWORD_FORMAT "%04lx" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08lx" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16lx" #endif #endif #if defined(SETWORD_INT) #if WORDSIZE==16 #define SETWORD_FORMAT "%04x" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08x" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16x" #endif #endif #if defined(SETWORD_SHORT) #if WORDSIZE==16 #define SETWORD_FORMAT "%04hx" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08hx" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16hx" #endif #endif /* POPCOUNT(x) = number of 1-bits in a setword x FIRSTBIT(x) = number of first 1-bit in non-zero setword (0..WORDSIZE-1) BITMASK(x) = setword whose rightmost WORDSIZE-x-1 (numbered) bits are 1 and the rest 0 (0 <= x < WORDSIZE) (I.e., bits 0..x are unselected and the rest selected.) ALLBITS = all (numbered) bits in a setword */ #if WORDSIZE==64 #define POPCOUNT(x) (bytecount[(x)>>56 & 0xFF] + bytecount[(x)>>48 & 0xFF] \ + bytecount[(x)>>40 & 0xFF] + bytecount[(x)>>32 & 0xFF] \ + bytecount[(x)>>24 & 0xFF] + bytecount[(x)>>16 & 0xFF] \ + bytecount[(x)>>8 & 0xFF] + bytecount[(x) & 0xFF]) #define FIRSTBIT(x) ((x) & MSK3232 ? \ (x) & MSK1648 ? \ (x) & MSK0856 ? \ 0+leftbit[((x)>>56) & 0xFF] : \ 8+leftbit[(x)>>48] \ : (x) & MSK0840 ? \ 16+leftbit[(x)>>40] : \ 24+leftbit[(x)>>32] \ : (x) & MSK1616 ? \ (x) & MSK0824 ? \ 32+leftbit[(x)>>24] : \ 40+leftbit[(x)>>16] \ : (x) & MSK0808 ? \ 48+leftbit[(x)>>8] : \ 56+leftbit[x]) #define BITMASK(x) (MSK63C >> (x)) #define ALLBITS MSK64 #define SWCHUNK0(w) ((long)((w)>>48)&0xFFFFL) #define SWCHUNK1(w) ((long)((w)>>32)&0xFFFFL) #define SWCHUNK2(w) ((long)((w)>>16)&0xFFFFL) #define SWCHUNK3(w) ((long)(w)&0xFFFFL) #endif #if WORDSIZE==32 #define POPCOUNT(x) (bytecount[(x)>>24 & 0xFF] + bytecount[(x)>>16 & 0xFF] \ + bytecount[(x)>>8 & 0xFF] + bytecount[(x) & 0xFF]) #define FIRSTBIT(x) ((x) & MSK1616 ? ((x) & MSK0824 ? \ leftbit[((x)>>24) & 0xFF] : 8+leftbit[(x)>>16]) \ : ((x) & MSK0808 ? 16+leftbit[(x)>>8] : 24+leftbit[x])) #define BITMASK(x) (MSK31C >> (x)) #define ALLBITS MSK32 #define SWCHUNK0(w) ((long)((w)>>16)&0xFFFFL) #define SWCHUNK1(w) ((long)(w)&0xFFFFL) #endif #if WORDSIZE==16 #define POPCOUNT(x) (bytecount[(x)>>8 & 0xFF] + bytecount[(x) & 0xFF]) #define FIRSTBIT(x) ((x) & MSK0808 ? leftbit[((x)>>8) & 0xFF] : 8+leftbit[x]) #define BITMASK(x) (MSK15C >> (x)) #define ALLBITS MSK16 #define SWCHUNK0(w) ((long)(w)&0xFFFFL) #endif #ifdef SYS_CRAY #undef POPCOUNT #undef FIRSTBIT #undef BITMASK #define POPCOUNT(x) _popcnt(x) #define FIRSTBIT(x) _leadz(x) #define BITMASK(x) _mask(65+(x)) #endif #ifdef NAUTY_IN_MAGMA #undef POPCOUNT #undef FIRSTBIT #undef BITMASK #define POPCOUNT(x) bs_popcount(x) #define FIRSTBIT(x) bs_firstbit(x) #define BITMASK(x) bs_bitmask(x) #endif #define ALLMASK(n) ((n)?~BITMASK((n)-1):(setword)0) /* First n bits */ /* various constants: */ #undef FALSE #undef TRUE #define FALSE 0 #define TRUE 1 #if SIZEOF_INT>=4 #define NAUTY_INFINITY 0x40000002 #else #define NAUTY_INFINITY 0x7FFF #endif typedef int shortish; /* For backward compatibility: */ #if !HAS_MATH_INF && !defined(INFINITY) #define INFINITY NAUTY_INFINITY #endif #if MAXN > NAUTY_INFINITY-2 #error MAXN must be at most NAUTY_INFINITY-2 #endif /* typedefs for sets, graphs, permutations, etc.: */ typedef int boolean; /* boolean MUST be the same as int */ #define UPROC void /* obsolete */ typedef setword set,graph; typedef int nvector,np2vector; /* obsolete */ typedef shortish permutation; #ifdef NAUTY_IN_MAGMA typedef graph nauty_graph; typedef set nauty_set; #endif typedef struct { double grpsize1; /* size of group is */ int grpsize2; /* grpsize1 * 10^grpsize2 */ #define groupsize1 grpsize1 /* for backwards compatibility */ #define groupsize2 grpsize2 int numorbits; /* number of orbits in group */ int numgenerators; /* number of generators found */ int errstatus; /* if non-zero : an error code */ #define outofspace errstatus; /* for backwards compatibility */ unsigned long numnodes; /* total number of nodes */ unsigned long numbadleaves; /* number of leaves of no use */ int maxlevel; /* maximum depth of search */ unsigned long tctotal; /* total size of all target cells */ unsigned long canupdates; /* number of updates of best label */ unsigned long invapplics; /* number of applications of invarproc */ unsigned long invsuccesses; /* number of successful uses of invarproc() */ int invarsuclevel; /* least level where invarproc worked */ } statsblk; /* codes for errstatus field (see nauty.c for more accurate descriptions): */ #define NTOOBIG 1 /* n > MAXN or n > WORDSIZE*m */ #define MTOOBIG 2 /* m > MAXM */ #define CANONGNIL 3 /* canong = NULL, but getcanon = TRUE */ /* manipulation of real approximation to group size */ #define MULTIPLY(s1,s2,i) if ((s1 *= i) >= 1e10) {s1 /= 1e10; s2 += 10;} struct optionstruct; /* incomplete definition */ typedef struct { boolean (*isautom) /* test for automorphism */ (graph*,permutation*,boolean,int,int); int (*testcanlab) /* test for better labelling */ (graph*,graph*,int*,int*,int,int); void (*updatecan) /* update canonical object */ (graph*,graph*,permutation*,int,int,int); void (*refine) /* refine partition */ (graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); void (*refine1) /* refine partition, MAXM==1 */ (graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); boolean (*cheapautom) /* test for easy automorphism */ (int*,int,boolean,int); int (*targetcell) /* decide which cell to split */ (graph*,int*,int*,int,int,boolean,int,int,int); void (*freedyn)(void); /* free dynamic memory */ void (*check) /* check compilation parameters */ (int,int,int,int); void (*init)(graph*,graph**,graph*,graph**,int*,int*,set*, struct optionstruct*,int*,int,int); void (*cleanup)(graph*,graph**,graph*,graph**,int*,int*, struct optionstruct*,statsblk*,int,int); } dispatchvec; typedef struct optionstruct { int getcanon; /* make canong and canonlab? */ #define LABELONLY 2 /* new value UNIMPLEMENTED */ boolean digraph; /* multiple edges or loops? */ boolean writeautoms; /* write automorphisms? */ boolean writemarkers; /* write stats on pts fixed, etc.? */ boolean defaultptn; /* set lab,ptn,active for single cell? */ boolean cartesian; /* use cartesian rep for writing automs? */ int linelength; /* max chars/line (excl. '\n') for output */ FILE *outfile; /* file for output, if any */ void (*userrefproc) /* replacement for usual refine procedure */ (graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); void (*userautomproc) /* procedure called for each automorphism */ (int,permutation*,int*,int,int,int); void (*userlevelproc) /* procedure called for each level */ (int*,int*,int,int*,statsblk*,int,int,int,int,int,int); void (*usernodeproc) /* procedure called for each node */ (graph*,int*,int*,int,int,int,int,int,int); void (*invarproc) /* procedure to compute vertex-invariant */ (graph*,int*,int*,int,int,int,permutation*,int,boolean,int,int); int tc_level; /* max level for smart target cell choosing */ int mininvarlevel; /* min level for invariant computation */ int maxinvarlevel; /* max level for invariant computation */ int invararg; /* value passed to (*invarproc)() */ dispatchvec *dispatch; /* vector of object-specific routines */ void *extra_options; /* arbitrary extra options */ #ifdef NAUTY_IN_MAGMA boolean print_stats; /* CAYLEY specfic - GYM Sep 1990 */ char *invarprocname; /* Magma - no longer global sjc 1994 */ int lab_h; /* Magma - no longer global sjc 1994 */ int ptn_h; /* Magma - no longer global sjc 1994 */ int orbitset_h; /* Magma - no longer global sjc 1994 */ #endif } optionblk; #ifndef CONSOLWIDTH #define CONSOLWIDTH 78 #endif /* The following are obsolete. Just use NULL. */ #define NILFUNCTION ((void(*)())NULL) /* nil pointer to user-function */ #define NILSET ((set*)NULL) /* nil pointer to set */ #define NILGRAPH ((graph*)NULL) /* nil pointer to graph */ #define DEFAULTOPTIONS_GRAPH(options) optionblk options = \ {0,FALSE,FALSE,FALSE,TRUE,FALSE,CONSOLWIDTH, \ NULL,NULL,NULL,NULL,NULL,NULL,100,0,1,0,&dispatch_graph,NULL} #ifndef DEFAULTOPTIONS #define DEFAULTOPTIONS DEFAULTOPTIONS_GRAPH #endif #ifdef NAUTY_IN_MAGMA #define PUTC(c,f) io_putchar(c) #else #ifdef IS_JAVA extern void javastream(FILE* f,char c); #define PUTC(c,f) javastream(f,c) #else #define PUTC(c,f) putc(c,f) #endif #endif /* We hope that malloc, free, realloc are declared either in or . Otherwise we will define them. We also assume that size_t has been defined by the time we get to define malloc(). */ #ifndef NAUTY_IN_MAGMA #if MALLOC_DEC==2 #include #endif #if MALLOC_DEC==0 extern void *malloc(size_t); extern void *realloc(void*,size_t); extern void free(void*); #endif #endif /* ALLOCS(x,y) should return a pointer (any pointer type) to x*y units of new storage, not necessarily initialised. A "unit" of storage is defined by the sizeof operator. x and y are integer values of type int or larger, but x*y may well be too large for an int. The macro should cast to the correct type for the call. On failure, ALLOCS(x,y) should return a NULL pointer. FREES(p) should free storage previously allocated by ALLOCS, where p is the value that ALLOCS returned. */ #ifdef NAUTY_IN_MAGMA #define ALLOCS(x,y) mem_malloc((size_t)(x)*(size_t)(y)) #define REALLOCS(p,x) mem_realloc(p,(size_t)(x)) #define FREES(p) mem_free(p) #else #define ALLOCS(x,y) malloc((size_t)(x)*(size_t)(y)) #define REALLOCS(p,x) realloc(p,(size_t)(x)) #define FREES(p) free(p) #endif /* The following macros are used by nauty if MAXN=0. They dynamically allocate arrays of size dependent on m or n. For each array there should be two static variables: type *name; size_t name_sz; "name" will hold a pointer to an allocated array. "name_sz" will hold the size of the allocated array in units of sizeof(type). DYNALLSTAT declares both variables and initialises name_sz=0. DYNALLOC1 and DYNALLOC2 test if there is enough space allocated, and if not free the existing space and allocate a bigger space. The allocated space is not initialised. In the case of DYNALLOC1, the space is allocated using ALLOCS(sz,sizeof(type)). In the case of DYNALLOC2, the space is allocated using ALLOCS(sz1,sz2*sizeof(type)). DYNREALLOC is like DYNALLOC1 except that the old contents are copied into the new space. realloc() is assumed. This is not currently used by nauty or dreadnaut. DYNFREE frees any allocated array and sets name_sz back to 0. CONDYNFREE does the same, but only if name_sz exceeds some limit. */ #define DYNALLSTAT(type,name,name_sz) \ static type *name; static size_t name_sz=0 #define DYNALLOC1(type,name,name_sz,sz,msg) \ if ((size_t)(sz) > name_sz) \ { if (name_sz) FREES(name); name_sz = (sz); \ if ((name=(type*)ALLOCS(sz,sizeof(type))) == NULL) {alloc_error(msg);}} #define DYNALLOC2(type,name,name_sz,sz1,sz2,msg) \ if ((size_t)(sz1)*(size_t)(sz2) > name_sz) \ { if (name_sz) FREES(name); name_sz = (size_t)(sz1)*(size_t)(sz2); \ if ((name=(type*)ALLOCS((sz1),(sz2)*sizeof(type))) == NULL) \ {alloc_error(msg);}} #define DYNREALLOC(type,name,name_sz,sz,msg) \ {if ((size_t)(sz) > name_sz) \ { if ((name = (type*)REALLOCS(name,(sz)*sizeof(type))) == NULL) \ {alloc_error(msg);} else name_sz = (sz);}} #define DYNFREE(name,name_sz) if (name_sz) {FREES(name); name_sz = 0;} #define CONDYNFREE(name,name_sz,minsz) \ if (name_sz > (size_t)(minsz)) {FREES(name); name_sz = 0;} /* File to write error messages to (used as first argument to fprintf()). */ #define ERRFILE stderr /* Don't use OLDEXTDEFS, it is only still here for Magma. */ #ifdef OLDEXTDEFS #define EXTDEF_CLASS #ifdef EXTDEFS #define EXTDEF_TYPE 1 #else #define EXTDEF_TYPE 2 #endif #else #define EXTDEF_CLASS static #define EXTDEF_TYPE 2 #endif extern int labelorg; /* Declared in nautil.c */ #ifndef NAUTY_IN_MAGMA /* Things equivalent to bit, bytecount, leftbit are defined in bs.h for Magma. */ #if EXTDEF_TYPE==1 extern setword bit[]; extern int bytecount[]; extern int leftbit[]; #else /* array giving setwords with single 1-bit */ #if WORDSIZE==64 #ifdef SETWORD_LONGLONG EXTDEF_CLASS setword bit[] = {01000000000000000000000LL,0400000000000000000000LL, 0200000000000000000000LL,0100000000000000000000LL, 040000000000000000000LL,020000000000000000000LL, 010000000000000000000LL,04000000000000000000LL, 02000000000000000000LL,01000000000000000000LL, 0400000000000000000LL,0200000000000000000LL, 0100000000000000000LL,040000000000000000LL, 020000000000000000LL,010000000000000000LL, 04000000000000000LL,02000000000000000LL, 01000000000000000LL,0400000000000000LL,0200000000000000LL, 0100000000000000LL,040000000000000LL,020000000000000LL, 010000000000000LL,04000000000000LL,02000000000000LL, 01000000000000LL,0400000000000LL,0200000000000LL, 0100000000000LL,040000000000LL,020000000000LL,010000000000LL, 04000000000LL,02000000000LL,01000000000LL,0400000000LL, 0200000000LL,0100000000LL,040000000LL,020000000LL, 010000000LL,04000000LL,02000000LL,01000000LL,0400000LL, 0200000LL,0100000LL,040000LL,020000LL,010000LL,04000LL, 02000LL,01000LL,0400LL,0200LL,0100LL,040LL,020LL,010LL, 04LL,02LL,01LL}; #else EXTDEF_CLASS setword bit[] = {01000000000000000000000,0400000000000000000000, 0200000000000000000000,0100000000000000000000, 040000000000000000000,020000000000000000000, 010000000000000000000,04000000000000000000, 02000000000000000000,01000000000000000000, 0400000000000000000,0200000000000000000, 0100000000000000000,040000000000000000,020000000000000000, 010000000000000000,04000000000000000,02000000000000000, 01000000000000000,0400000000000000,0200000000000000, 0100000000000000,040000000000000,020000000000000, 010000000000000,04000000000000,02000000000000, 01000000000000,0400000000000,0200000000000,0100000000000, 040000000000,020000000000,010000000000,04000000000, 02000000000,01000000000,0400000000,0200000000,0100000000, 040000000,020000000,010000000,04000000,02000000,01000000, 0400000,0200000,0100000,040000,020000,010000,04000, 02000,01000,0400,0200,0100,040,020,010,04,02,01}; #endif #endif #if WORDSIZE==32 EXTDEF_CLASS setword bit[] = {020000000000,010000000000,04000000000,02000000000, 01000000000,0400000000,0200000000,0100000000,040000000, 020000000,010000000,04000000,02000000,01000000,0400000, 0200000,0100000,040000,020000,010000,04000,02000,01000, 0400,0200,0100,040,020,010,04,02,01}; #endif #if WORDSIZE==16 EXTDEF_CLASS setword bit[] = {0100000,040000,020000,010000,04000,02000,01000,0400,0200, 0100,040,020,010,04,02,01}; #endif /* array giving number of 1-bits in bytes valued 0..255: */ EXTDEF_CLASS int bytecount[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8}; /* array giving position (1..7) of high-order 1-bit in byte: */ EXTDEF_CLASS int leftbit[] = {8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; #endif /* EXTDEFS */ #endif /* not NAUTY_IN_MAGMA */ #define ANSIPROT 1 #define EXTPROC(func,args) extern func args; /* obsolete */ /* The following is for C++ programs that read nauty.h. Compile nauty itself using C, not C++. */ #ifdef __cplusplus extern "C" { #endif extern void alloc_error(char*); extern void breakout(int*,int*,int,int,int,set*,int); extern boolean cheapautom(int*,int,boolean,int); extern void doref(graph*,int*,int*,int,int*,int*,permutation*,set*,int*, void(*)(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int), void(*)(graph*,int*,int*,int,int,int,permutation*,int,boolean,int,int), int,int,int,boolean,int,int); extern void extra_autom(permutation*,int); extern void extra_level(int,int*,int*,int,int,int,int,int,int); extern boolean isautom(graph*,permutation*,boolean,int,int); extern dispatchvec dispatch_graph; extern int itos(int,char*); extern void fmperm(permutation*,set*,set*,int,int); extern void fmptn(int*,int*,int,set*,set*,int,int); extern void longprune(set*,set*,set*,set*,int); extern void nauty(graph*,int*,int*,set*,int*,optionblk*, statsblk*,set*,int,int,int,graph*); extern void maketargetcell(graph*,int*,int*,int,set*,int*,int*,int,boolean, int,int (*)(graph*,int*,int*,int,int,boolean,int,int,int),int,int); extern int nextelement(set*,int,int); extern int orbjoin(int*,permutation*,int); extern void permset(set*,set*,int,permutation*); extern void putstring(FILE*,char*); extern void refine(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); extern void refine1(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); extern void shortprune(set*,set*,int); extern int targetcell(graph*,int*,int*,int,int,boolean,int,int,int); extern int testcanlab(graph*,graph*,int*,int*,int,int); extern void updatecan(graph*,graph*,permutation*,int,int,int); extern void writeperm(FILE*,permutation*,boolean,int,int); extern void nauty_freedyn(void); extern void nauty_check(int,int,int,int); extern void naugraph_check(int,int,int,int); extern void nautil_check(int,int,int,int); extern void nautil_freedyn(void); extern void naugraph_freedyn(void); #ifdef __cplusplus } #endif #endif /* _NAUTY_H_ */ nauty24r2/config.txt0000600000604200001440000000207411274163463013320 0ustar bdmusers======================================================================== | In order to compile nauty on systems which include a Unix-like shell | (which includes MacOSX and Cygwin), you must first run the script | "configure". Usually this can be done with the command | ./configure | | The configure script will create custom versions of these files: | gtools.h makefile naututil.h nauty.h | Afterwards you can use "make" to compile everything. | | In case you can't run shell scripts, or configure doesn't work for | some reason, you need to adjust the configuration by hand: | For gtools.h, naututil.h, and nauty.h, make sure definitions near the | start of the file (like HAVE_UNISTD_H and SIZEOF_INT) are all correct. | For makefile, copy the file makefile.basic to makefile, then check the | definitions near the start. | | Please notify Brendan McKay of any problems with | the configuration and of any hints you might have for other people with | similar setups as you have. ======================================================================== nauty24r2/config.guess0000700000604200001440000012430711274163463013634 0ustar bdmusers#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. timestamp='2004-08-13' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amd64:OpenBSD:*:*) echo x86_64-unknown-openbsd${UNAME_RELEASE} exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; cats:OpenBSD:*:*) echo arm-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; luna88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mips64-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit 0 ;; macppc:MirBSD:*:*) echo powerppc-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; *:OS400:*:*) echo powerpc-ibm-os400 exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then # avoid double evaluation of $set_cc_for_build test -n "$CC_FOR_BUILD" || eval $set_cc_for_build if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:[34]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' exit 0 ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit 0 ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in *86) UNAME_PROCESSOR=i686 ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms && exit 0 ;; I*) echo ia64-dec-vms && exit 0 ;; V*) echo vax-dec-vms && exit 0 ;; esac esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: nauty24r2/testlab.c0000600000604200001440000001213711274163463013115 0ustar bdmusers/* testlab.c version 1.1; B D McKay, Feb 23 2000 */ #define USAGE "testlab [-qsgu] [-c#] [infile [outfile]]" #define HELPTEXT \ " Canonically label a file of graphs multiple times as a check.\n\ \n\ -u no output\n\ -s force output to sparse6 format\n\ -g force output to graph6 format\n\ If neither -s or -g are given, the output format is\n\ determined by the header or, if there is none, by the\n\ format of the first input graph.\n\ \n\ The output file will have a header if and only if the input file does.\n\ \n\ -c# After labelling the graph once, this many times randomly\n\ relabel it then label the result again. The canonical form\n\ and number of orbits are compared each time.\n\ \n\ -q suppress auxiliary information\n" /*************************************************************************/ #include "gtools.h" static long orbtotal; static double unorbtotal; extern int gt_numorbits; /**************************************************************************/ main(argc,argv) int argc; char *argv[]; { graph *g; int m,n,codetype; int argnum,j,outcode; char *arg,sw,*fmt; boolean badargs; long code1,code2; int numorbs; int i,nchecks; boolean sswitch,gswitch,qswitch,fswitch,Oswitch; boolean uswitch,cswitch; double t; char *infilename,*outfilename; FILE *infile,*outfile; long nin; #if MAXN graph h[MAXN*MAXM]; permutation perm[MAXN]; #else DYNALLSTAT(graph,h,h_sz); DYNALLSTAT(permutation,perm,perm_sz); #endif HELP; nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); #ifdef INITSEED INITSEED; ran_init(seed); #endif sswitch = gswitch = uswitch = qswitch = FALSE; fswitch = Oswitch = FALSE; cswitch = FALSE; infilename = outfilename = NULL; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('s',sswitch) else SWBOOLEAN('g',gswitch) else SWBOOLEAN('u',uswitch) else SWBOOLEAN('q',qswitch) else SWBOOLEAN('O',Oswitch) /* else if (sw == 'f') { fswitch = TRUE; fmt = arg; break; } */ else SWINT('c',cswitch,nchecks,"testlab -c") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if ((sswitch != 0) + (uswitch != 0) + (gswitch!= 0) > 1) gt_abort(">E testlab: -s, -g and -u are incompatible\n"); if (badargs || argnum > 2) { fprintf(stderr,">E Usage: %s\n",USAGE); exit(1); } if (!qswitch) { fprintf(stderr,">A testlab"); if (sswitch || gswitch || fswitch || uswitch || cswitch) fprintf(stderr," -"); if (sswitch) fprintf(stderr,"s"); if (gswitch) fprintf(stderr,"g"); if (uswitch) fprintf(stderr,"u"); if (cswitch) fprintf(stderr,"c%d",nchecks); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (sswitch || !gswitch && (codetype&SPARSE6)) outcode = SPARSE6; else outcode = GRAPH6; if (!fswitch) fmt = NULL; if ((codetype&HAS_HEADER) && !uswitch) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } if (!cswitch) nchecks = 1; nin = 0; orbtotal = 0; unorbtotal = 0.0; t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"testlab"); DYNALLOC1(permutation,perm,perm_sz,n,"testlab"); #endif fcanonise(g,m,n,h,fmt); code1 = hash(h,m*(long)n,3); code2 = hash(h,m*(long)n,11); numorbs = gt_numorbits; for (i = 0; i < nchecks; ++i) { ranperm(perm,n); relabel(g,NULL,perm,h,m,n); fcanonise(g,m,n,h,fmt); if (hash(h,m*(long)n,3) != code1 || hash(h,m*(long)n,11) != code2 || gt_numorbits != numorbs) { fprintf(stderr,">E Input %ld poorly labelled\n",nin); exit(1); } } orbtotal += gt_numorbits; unorbtotal += 1.0 / gt_numorbits; if (!uswitch) { if (outcode == SPARSE6) writes6(outfile,h,m,n); else writeg6(outfile,h,m,n); } FREES(g); } t = CPUTIME - t; if (Oswitch) fprintf(stderr,">C orbit totals = %ld %15.8f\n", orbtotal,unorbtotal); if (!qswitch) fprintf(stderr, ">Z %ld graphs labelled from %s to %s in %3.2f sec.\n", nin,infilename,outfilename,t); exit(0); } nauty24r2/install-sh0000700000604200001440000000024611274163463013313 0ustar bdmusers# This is a dummy file to keep autoconf happy # Since we don't provide an "install" target, # it is an error for autoconf to complain when # this file is absent. nauty24r2/nautyex3.c0000600000604200001440000000556511274163463013246 0ustar bdmusers/* This program prints the entire automorphism group of an n-vertex polygon, where n is a number supplied by the user. It needs to be linked with nauty.c, nautil.c, naugraph.c and naugroup.c. */ #include "nauty.h" /* which includes */ #include "naugroup.h" /**************************************************************************/ void writeautom(permutation *p, int n) /* Called by allgroup. Just writes the permutation p. */ { int i; for (i = 0; i < n; ++i) printf(" %2d",p[i]); printf("\n"); } /**************************************************************************/ int main(int argc, char *argv[]) { DYNALLSTAT(graph,g,g_sz); DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(setword,workspace,workspace_sz); static DEFAULTOPTIONS_GRAPH(options); statsblk stats; int n,m,v; set *gv; grouprec *group; /* The following cause nauty to call two procedures which store the group information as nauty runs. */ options.userautomproc = groupautomproc; options.userlevelproc = grouplevelproc; while (1) { printf("\nenter n : "); if (scanf("%d",&n) == 1 && n > 0) { m = (n + WORDSIZE - 1) / WORDSIZE; nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); DYNALLOC2(graph,g,g_sz,m,n,"malloc"); DYNALLOC1(int,lab,lab_sz,n,"malloc"); DYNALLOC1(int,ptn,ptn_sz,n,"malloc"); DYNALLOC1(int,orbits,orbits_sz,n,"malloc"); DYNALLOC1(setword,workspace,workspace_sz,5*m,"malloc"); for (v = 0; v < n; ++v) { gv = GRAPHROW(g,v,m); EMPTYSET(gv,m); ADDELEMENT(gv,(v+n-1)%n); ADDELEMENT(gv,(v+1)%n); } printf("Automorphisms of C[%d]:\n",n); nauty(g,lab,ptn,NULL,orbits,&options,&stats, workspace,5*m,m,n,NULL); /* Get a pointer to the structure in which the group information has been stored. If you use TRUE as an argument, the structure will be "cut loose" so that it won't be used again the next time nauty() is called. Otherwise, as here, the same structure is used repeatedly. */ group = groupptr(FALSE); /* Expand the group structure to include a full set of coset representatives at every level. This step is necessary if allgroup() is to be called. */ makecosetreps(group); /* Call the procedure writeautom() for every element of the group. The first call is always for the identity. */ allgroup(group,writeautom); } else break; } exit(0); } nauty24r2/naututil-h.in0000600000604200001440000002776611274163463013753 0ustar bdmusers/***************************************************************************** * This is the header file for versions 2.4 of naututil.c and dreadnaut.c. * * @configure_input@ *****************************************************************************/ /* The parts between the ==== lines are modified by configure when creating naututil.h out of naututil-h.in. If configure is not being used, it is necessary to check they are correct. ====================================================================*/ /* Check whether various headers are available */ #define HAVE_ISATTY @have_isatty@ /* if isatty() is available */ #define HAVE_TIMES @have_times@ /* if times() is available */ #define HAVE_TIME @have_time@ /* if time() is available */ #define HAVE_GETRUSAGE @have_getrusage@ /* if getrusage() is available */ #define HAVE_GETTIMEOFDAY @have_gettimeofday@ /* if gettimeofday() */ /*==================================================================*/ /***************************************************************************** * * * Copyright (1984-2007) Brendan McKay. All rights reserved. * * Subject to the waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 10-Nov-87 : final changes for version 1.2 * * 5-Dec-87 : changes for version 1.3 : * * - added declarations of readinteger() and readstring() * * - added definition of DEFEXT : default file-name * * extension for dreadnaut input files * * 28-Sep-88 : changes for version 1.4 : * * - added support for PC Turbo C * * 29-Nov-88 : - added getc macro for AZTEC C on MAC * * 23-Mar-89 : changes for version 1.5 : * * - added DREADVERSION macro * * - added optional ANSI function prototypes * * - changed file name to naututil.h * * - moved ALLOCS to nauty.h and defined DYNALLOC * * 25-Mar-89 : - added declaration of twopaths() * * 29-Mar-89 : - added declaration of putmapping() * * 4-Apr-89 : - added declarations of triples, quadruples, adjtriang * * - only define ERRFILE if not in nauty.h * * 25-Apr-89 : - added declarations of cellquads,distances,getbigcells * * 26-Apr-89 : - added declarations of indsets,cliques,cellquins * * - removed declarations of ptncode and equitable * * 27-Apr-89 : - added declaration of putquotient * * 18-Aug-89 : - added new arg to putset, and changed mathon * * 2-Mar-90 : - added declarations of celltrips, cellcliq, cellind * * - changed declarations to use EXTPROC * * 12-Mar-90 : - added changes for Cray version * * 20-Mar-90 : - added changes for THINK version * * 27-Mar-90 : - split SYS_MSDOS into SYS_PCMS4 and SYS_PCMS5 * * 13-Oct-90 : changes for version 1.6 : * * - changed CPUTIME to use HZ on Unix for times() * * 14-Oct-90 : - added SYS_APOLLO variant * * 19-Oct-90 : - changed CPUTIME defs for BSDUNIX to avoid conficting * * declarations of size_t and ptrdiff_t in gcc * * 27-Aug-92 : changes for version 1.7 : * * - added SYS_IBMC variant * * - removed workaround for bad gcc installation * * 5-Jun-93 : changes for version 1.8 : * * - changed CRAY version of CPUTIME to use CLK_TCK * * if HZ could not be found (making 1.7+) * * 30-Jul-93 : - added SYS_ALPHA variant * * 17-Sep-93 : changes for version 1.9 : * * - declared adjacencies() * * 24-Feb-94 : changes for version 1.10 : * * - added version SYS_AMIGAAZT (making 1.9+) * * 19-Apr-95 : - added C++ prototype wrapper * * 6-Mar-96 : - added SYS_ALPHA32 code * * 23-Jul-96 : changes for version 2.0 : * * - changed readstring() declaration * * - removed DYNALLOC definition * * - added sublabel() definition * * 15-Aug-96 : - added sethash() definition * * 30-Aug-96 : - added KRAN and D. Knuth routines * * 16-Sep-96 : - fixed the above! * * 7-Feb-96 : - declared nautinv_null() and setnbhd() * * 4-Sep-97 : - arg of time() is type time_t*, was long* * * 22-Sep-97 : - defined fileno() and time_t for SYS_PCTURBO * * 10-Dec-97 : - revised KRAN for new rng.c from Knuth * * 18-Feb-98 : - changed time() to time_t for Unix * * 21-Oct-98 : - changed short to shortish as needed * * 9-Jan-00 : - declared nautinv_check() and naututil_check() * * 16-Nov-00 : - applied changes logged in nauty.h * * 22-Apr-01 : changes for version 2.1 : * * - prototypes for nautinv.c are now in nautinv.h * * - CPUTIME for UNIX uses CLK_TCK (needs revision!) * * 2-Jun-01 : - prototype for converse() * * 18-Oct-01 : - complete revision; sysdeps in separate files * * 28-Aug-02 : changes for version 2.2 : * * - revised for autoconf * * 17-Nov-02 : added explicit "extern" where it was implicit before * * 11-Apr-02 : added rangraph2() * * 10-Sep-07 : Define CPUTIME=0.0 for hosts that don't provide it * * * *****************************************************************************/ #include "nauty.h" /* which includes stdio.h */ /* At this point we can assume that , , , , or and if necessary have been included if they exist. */ #ifdef __cplusplus extern "C" { #endif extern void complement(graph*,int,int); extern void converse(graph*,int,int); extern void copycomment(FILE*,FILE*,int); extern void flushline(FILE*); extern void fixit(int*,int*,int*,int,int); extern int getint(FILE*); extern long hash(set*,long,int); extern void mathon(graph*,int,int,graph*,int,int); extern void naututil_check(int,int,int,int); extern void putcanon(FILE*,int*,graph*,int,int,int); extern void putdegs(FILE*,graph*,int,int,int); extern void putgraph(FILE*,graph*,int,int,int); extern void putmapping(FILE*,int*,int,int*,int,int,int); extern void putorbits(FILE*,int*,int,int); extern void putptn(FILE*,int*,int*,int,int,int); extern void putquotient(FILE*,graph*,int*,int*,int,int,int,int); extern void putset(FILE*,set*,int*,int,int,boolean); extern long ran_arr_cycle(void); extern void ran_array(long*,int); extern void ran_init(long); extern void rangraph(graph*,boolean,int,int,int); extern void rangraph2(graph*,boolean,int,int,int,int); extern void ranperm(permutation*,int); extern void readgraph(FILE*,graph*,boolean,boolean,boolean,int,int,int); extern boolean readinteger(FILE*,int*); extern void readperm(FILE*,permutation*,boolean,int); extern void readptn(FILE*,int*,int*,int*,boolean,int); extern void readvperm(FILE*,permutation*,boolean,int,int*); extern boolean readstring(FILE*,char*,int); extern void relabel(graph*,int*,permutation*,graph*,int,int); extern long sethash(set*,int,long,int); extern int setinter(set*,set*,int); extern int setsize(set*,int); extern void sublabel(graph*,permutation*,int,graph*,int,int); extern void unitptn(int*,int*,int*,int); #ifdef __cplusplus } #endif #define PROMPTFILE stdout /* where to write prompts */ #ifndef ERRFILE #define ERRFILE stderr /* where to write error messages */ #endif #define MAXIFILES 10 /* how many input files can be open at once */ #define EXIT exit(0) /* how to stop normally */ #define DEFEXT ".dre" /* extension for dreadnaut files */ extern long *ran_arr_ptr; /* declared in rng.c */ extern long seed; /* declared in naututil.c */ #define NEXTRAN (*ran_arr_ptr>=0 ? *ran_arr_ptr++ : ran_arr_cycle()) #define KRAN(k) (NEXTRAN%(k)) /************************************************************************* The following macros may represent differences between system. This file contains the UNIX/POSIX editions. For other systems, a separate file of definitions is read in first. That file should define the variables NAUTY_*_DEFINED for sections that are to replace the UNIX versions. See the provided examples for more details. If your system does not have a predefined macro you can use to cause a definitions file to be read, you have to make up one and arrange for it to be defined when this file is read. The system-dependent files can also redefine the macros just ahead of this comment. **************************************************************************/ #ifdef __weirdmachine__ #include "weird.h" /* Some weird machine (ILLUSTRATION ONLY) */ #endif /*************************************************************************/ #ifndef NAUTY_PROMPT_DEFINED #if HAVE_ISATTY #define DOPROMPT(fp) (isatty(fileno(fp)) && isatty(fileno(PROMPTFILE))) #else #define DOPROMPT(fp) (curfile==0) #endif #endif /*NAUTY_PROMPT_DEFINED*/ /*************************************************************************/ #ifndef NAUTY_OPEN_DEFINED #define OPENOUT(fp,name,append) fp = fopen(name,(append)?"a":"w") #endif /*NAUTY_OPEN_DEFINED*/ /*************************************************************************/ #ifndef NAUTY_CPU_DEFINED #if HAVE_TIMES #include #define CPUDEFS static struct tms timebuffer; #ifndef CLK_TCK #include #endif #if !defined(CLK_TCK) && defined(_SC_CLK_TCK) #define CLK_TCK sysconf(_SC_CLK_TCK) #endif #ifndef CLK_TCK #define CLK_TCK 60 #endif #define CPUTIME (times(&timebuffer),\ (double)(timebuffer.tms_utime + timebuffer.tms_stime) / CLK_TCK) #else #if HAVE_GETRUSAGE #include #include #define CPUDEFS struct rusage ruse; #define CPUTIME (getrusage(RUSAGE_SELF,&ruse),\ ruse.ru_utime.tv_sec + ruse.ru_stime.tv_sec + \ 1e-6 * (ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec)) #endif #endif #ifndef CPUTIME #define CPUTIME 0.0 #endif #endif /*NAUTY_CPU_DEFINED*/ /*************************************************************************/ #ifndef NAUTY_SEED_DEFINED #if HAVE_GETTIMEOFDAY #include #define INITSEED \ {struct timeval nauty_tv; \ struct timezone nauty_tz; \ gettimeofday(&nauty_tv,&nauty_tz); \ seed = (nauty_tv.tv_sec<<10) + (nauty_tv.tv_usec>>10) & 017777777777L;} #else #if HAVE_TIME #include #define INITSEED seed = ((time((time_t*)NULL)<<1) | 1) & 017777777777L #endif #endif #endif /*NAUTY_SEED_DEFINED*/ nauty24r2/rng.c0000600000604200001440000001127511274163463012247 0ustar bdmusers/* rng.c This file contains the code for a high-quality random number generator written by Don Knuth. The auxilliary routine ran_arr_cycle() has been modified slightly, and ran_init() is new. To use it: 0. #include "rng.h" (or "naututil.h" if you are using nauty) 1. Call ran_init(seed), where seed is any long integer. This step is optional, but if you don't use it you will always get the same sequence of random numbers. 2. For each random number, use the NEXTRAN macro. It will give a random value in the range 0..2^30-1. Alternatively, KRAN(k) will have a random value in the range 0..k-1. KRAN(k) actually gives you NEXTRAN mod k, so it is not totally uniform if k is very large. In that case, you can use the slightly slower GETKRAN(k,var) to set the variable var to a better random number from 0..k-1. Brendan McKay, July 2002. Fixed Nov 2002 on advice of DEK. */ /* This program by D E Knuth is in the public domain and freely copyable * AS LONG AS YOU MAKE ABSOLUTELY NO CHANGES! * It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6 * (or in the errata to the 2nd edition --- see * http://www-cs-faculty.stanford.edu/~knuth/taocp.html * in the changes to Volume 2 on pages 171 and following). */ /* N.B. The MODIFICATIONS introduced in the 9th printing (2002) are included here; there's no backwards compatibility with the original. */ /* If you find any bugs, please report them immediately to * taocp@cs.stanford.edu * (and you will be rewarded if the bug is genuine). Thanks! */ /************ see the book for explanations and caveats! *******************/ /************ in particular, you need two's complement arithmetic **********/ #define KK 100 /* the long lag */ #define LL 37 /* the short lag */ #define MM (1L<<30) /* the modulus */ #define mod_diff(x,y) (((x)-(y))&(MM-1)) /* subtraction mod MM */ long ran_x[KK]; /* the generator state */ #ifdef __STDC__ void ran_array(long aa[],int n) #else void ran_array(aa,n) /* put n new random numbers in aa */ long *aa; /* destination */ int n; /* array length (must be at least KK) */ #endif { int i,j; for (j=0;j=MM) ss-=MM-2; /* cyclic shift 29 bits */ } x[1]++; /* make x[1] (and only x[1]) odd */ for (ss=seed&(MM-1),t=TT-1; t; ) { for (j=KK-1;j>0;j--) x[j+j]=x[j], x[j+j-1]=0; /* "square" */ for (j=KK+KK-2;j>=KK;j--) x[j-(KK-LL)]=mod_diff(x[j-(KK-LL)],x[j]), x[j-KK]=mod_diff(x[j-KK],x[j]); if (is_odd(ss)) { /* "multiply by z" */ for (j=KK;j>0;j--) x[j]=x[j-1]; x[0]=x[KK]; /* shift the buffer cyclically */ x[LL]=mod_diff(x[LL],x[KK]); } if (ss) ss>>=1; else t--; } for (j=0;j=0? *ran_arr_ptr++: ran_arr_cycle()) long ran_arr_cycle(void) /* Modified by BDM to automatically initialise if no explicit initialisation has been done */ { if (ran_arr_ptr==&ran_arr_dummy) ran_start(314159L); /* the user forgot to initialize */ ran_array(ran_arr_buf,QUALITY); ran_arr_buf[KK]=-1; ran_arr_ptr=ran_arr_buf+1; return ran_arr_buf[0]; } nauty24r2/makefile.in0000600000604200001440000004043411405400216013403 0ustar bdmusers# makefile for nauty 2.4, including gtools # @configure_input@ SHELL=/bin/sh CC=@CC@ CFLAGS=@CFLAGS@ @MORECFLAGS@ SAFECFLAGS=@CFLAGS@ LDFLAGS=@LIBS@ LOK=@lok@ # 0 if no 64-bit integers TESTPROGS=@testprogs@ EXEEXT=@EXEEXT@ BIGTEST=1 # set to 0 if less than 512MB is available SMALL=-DMAXN=WORDSIZE L1=-DMAXN=WORDSIZE -DWORDSIZE=64 W1=-DMAXN=WORDSIZE -DWORDSIZE=32 S1=-DMAXN=WORDSIZE -DWORDSIZE=16 S=-DWORDSIZE=16 L=-DWORDSIZE=64 FOURK=-DMAXN=4096 all : nauty gtools ; nauty : dreadnaut ; gtools : copyg listg labelg dretog amtog geng complg shortg showg NRswitchg \ biplabg addedgeg deledgeg countg pickg genrang newedgeg catg genbg directg \ multig planarg gentourng ; rng.o: rng.c ${CC} -c ${CFLAGS} rng.c dreadnaut: dreadnaut.c naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${CC} -o dreadnaut ${SAFECFLAGS} dreadnaut.c \ naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${LDFLAGS} naututil.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} naututil.c nautil.o: nauty.h nautil.c ${CC} -c ${CFLAGS} nautil.c nauty.o: nauty.h nauty.c ${CC} -c ${CFLAGS} nauty.c nautinv.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} nautinv.c nautaux.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} nautaux.c naugraph.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} naugraph.c nausparse.o : nauty.h nausparse.h nausparse.c ${CC} -c ${CFLAGS} nausparse.c dreadnaut1: dreadnaut.c naututil1.o nauty1.o nautil1.o \ nautinv1.o naugraph1.o rng.o ${CC} -o dreadnaut1 ${SAFECFLAGS} ${SMALL} dreadnaut.c naututil1.o \ nauty1.o nautil1.o nautinv1.o naugraph1.o rng.o ${LDFLAGS} naututil1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${SMALL} -o naututil1.o naututil.c nautil1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${SMALL} -o nautil1.o nautil.c nauty1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${SMALL} -o nauty1.o nauty.c nautinv1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${SMALL} -o nautinv1.o nautinv.c nautaux1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${SMALL} -o nautaux1.o nautaux.c naugraph1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${SMALL} -o naugraph1.o naugraph.c dreadnaut4K: dreadnaut.c naututil4K.o nauty4K.o nautil4K.o \ nautinv4K.o naugraph4K.o rng.o ${CC} -o dreadnaut4K ${SAFECFLAGS} ${FOURK} dreadnaut.c naututil4K.o \ nauty4K.o nautil4K.o nautinv4K.o naugraph4K.o rng.o ${LDFLAGS} naututil4K.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${FOURK} -o naututil4K.o naututil.c nautil4K.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${FOURK} -o nautil4K.o nautil.c nauty4K.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${FOURK} -o nauty4K.o nauty.c nautinv4K.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${FOURK} -o nautinv4K.o nautinv.c nautaux4K.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${FOURK} -o nautaux4K.o nautaux.c naugraph4K.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${FOURK} -o naugraph4K.o naugraph.c dreadnautL1: dreadnaut.c naututilL1.o nautyL1.o nautilL1.o nautinvL1.o \ naugraphL1.o rng.o ${CC} -o dreadnautL1 ${SAFECFLAGS} ${L1} dreadnaut.c naututilL1.o \ nautyL1.o nautilL1.o nautinvL1.o naugraphL1.o rng.o ${LDFLAGS} naututilL1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${L1} -o naututilL1.o naututil.c nautilL1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${L1} -o nautilL1.o nautil.c nautyL1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${L1} -o nautyL1.o nauty.c nautinvL1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${L1} -o nautinvL1.o nautinv.c nautauxL1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${L1} -o nautauxL1.o nautaux.c naugraphL1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${L1} -o naugraphL1.o naugraph.c dreadnautW1: dreadnaut.c naututilW1.o nautyW1.o nautilW1.o nautinvW1.o \ naugraphW1.o rng.o ${CC} -o dreadnautW1 ${SAFECFLAGS} ${W1} dreadnaut.c naututilW1.o \ nautyW1.o nautilW1.o nautinvW1.o naugraphW1.o rng.o ${LDFLAGS} naututilW1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${W1} -o naututilW1.o naututil.c nautilW1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${W1} -o nautilW1.o nautil.c nautyW1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${W1} -o nautyW1.o nauty.c nautinvW1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${W1} -o nautinvW1.o nautinv.c nautauxW1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${W1} -o nautauxW1.o nautaux.c naugraphW1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${W1} -o naugraphW1.o naugraph.c gtoolsW1.o : gtools.h gtools.c ${CC} -c ${CFLAGS} ${W1} -o gtoolsW1.o gtools.c dreadnautS1: dreadnaut.c naututilS1.o nautyS1.o nautilS1.o nautinvS1.o \ naugraphS1.o rng.o ${CC} -o dreadnautS1 ${SAFECFLAGS} ${S1} dreadnaut.c naututilS1.o \ nautyS1.o nautilS1.o nautinvS1.o naugraphS1.o rng.o ${LDFLAGS} naututilS1.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${S1} -o naututilS1.o naututil.c nautilS1.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${S1} -o nautilS1.o nautil.c nautyS1.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${S1} -o nautyS1.o nauty.c nautinvS1.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${S1} -o nautinvS1.o nautinv.c nautauxS1.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${S1} -o nautauxS1.o nautaux.c naugraphS1.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${S1} -o naugraphS1.o naugraph.c dreadnautL: dreadnaut.c naututilL.o nautyL.o nautilL.o nautinvL.o \ naugraphL.o rng.o ${CC} -o dreadnautL ${SAFECFLAGS} ${L} dreadnaut.c naututilL.o \ nautyL.o nautilL.o nautinvL.o naugraphL.o rng.o ${LDFLAGS} naututilL.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${L} -o naututilL.o naututil.c nautilL.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${L} -o nautilL.o nautil.c nautyL.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${L} -o nautyL.o nauty.c nautinvL.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${L} -o nautinvL.o nautinv.c nautauxL.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${L} -o nautauxL.o nautaux.c naugraphL.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${L} -o naugraphL.o naugraph.c dreadnautS: dreadnaut.c naututilS.o nautyS.o nautilS.o nautinvS.o \ naugraphS.o rng.o ${CC} -o dreadnautS ${SAFECFLAGS} ${S} dreadnaut.c naututilS.o \ nautyS.o nautilS.o nautinvS.o naugraphS.o rng.o ${LDFLAGS} naututilS.o: nauty.h naututil.h naututil.c ${CC} -c ${CFLAGS} ${S} -o naututilS.o naututil.c nautilS.o: nauty.h nautil.c ${CC} -c ${CFLAGS} ${S} -o nautilS.o nautil.c nautyS.o: nauty.h nauty.c ${CC} -c ${CFLAGS} ${S} -o nautyS.o nauty.c nautinvS.o: nauty.h naututil.h nautinv.c ${CC} -c ${CFLAGS} ${S} -o nautinvS.o nautinv.c nautauxS.o: nautaux.h nauty.h naututil.h nautaux.c ${CC} -c ${CFLAGS} ${S} -o nautauxS.o nautaux.c naugraphS.o: nauty.h naugraph.c ${CC} -c ${CFLAGS} ${S} -o naugraphS.o naugraph.c clean: rm -f *.o config.log config.cache config.status rm -f dreadtest${EXEEXT} dreadtestL${EXEEXT} \ dreadtestS${EXEEXT} dreadtestS1${EXEEXT} \ dreadtest4K${EXEEXT} dreadtest1${EXEEXT} \ dreadtestL1${EXEEXT} dreadtestW1${EXEEXT} gtools.h : nauty.h naututil.h nausparse.h touch gtools.h gtools.o : gtools.h gtools.c ${CC} -c ${CFLAGS} gtools.c gtnauty.o : gtools.h gtnauty.c ${CC} -c ${CFLAGS} gtnauty.c gutil1.o : gtools.h gutils.h gutil1.c ${CC} -c ${CFLAGS} gutil1.c gutil2.o : gtools.h gutils.h gutil2.c ${CC} -c ${CFLAGS} gutil2.c catg : gtools.h catg.c gtools.o ${CC} -o catg ${CFLAGS} catg.c gtools.o ${LDFLAGS} copyg : gtools.h copyg.c gtools.o ${CC} -o copyg ${CFLAGS} copyg.c gtools.o ${LDFLAGS} listg : gtools.h listg.c gtools.o nautil.o ${CC} -o listg ${CFLAGS} listg.c gtools.o nautil.o ${LDFLAGS} labelg : gtools.h naututil.h labelg.c gtools.o gtnauty.o nauty.o \ nautil.o naugraph.o nautinv.o nausparse.h nausparse.o \ gutils.h gutil2.o ${CC} -o labelg ${SAFECFLAGS} labelg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nautinv.o nausparse.o \ gutil2.o ${LDFLAGS} shortg : gtools.h shortg.c gtools.o gtnauty.o nauty.o nautil.o naugraph.o \ nausparse.h nausparse.o gutils.h gutil2.o nautinv.h nautinv.o ${CC} -o shortg ${CFLAGS} shortg.c gtools.o gtnauty.o nautinv.o \ nauty.o nautil.o naugraph.o nausparse.o gutil2.o ${LDFLAGS} dretog : gtools.h dretog.c gtools.o naututil.o nautil.o naugraph.o rng.o ${CC} -o dretog ${CFLAGS} dretog.c \ gtools.o naututil.o nautil.o rng.o naugraph.o ${LDFLAGS} amtog : gtools.h amtog.c gtools.o ${CC} -o amtog ${CFLAGS} amtog.c gtools.o ${LDFLAGS} genbg : gtools.h genbg.c gtoolsW1.o nautyW1.o nautilW1.o naugraphW1.o ${CC} -o genbg ${CFLAGS} ${W1} genbg.c gtoolsW1.o \ nautyW1.o nautilW1.o naugraphW1.o ${LDFLAGS} genbgL : gtools.h genbg.c gtoolsL1.o nautyL1.o nautilL1.o naugraphL1.o ${CC} -o genbgL ${CFLAGS} ${L1} -DMAXN1=30 genbg.c gtoolsL1.o \ nautyL1.o nautilL1.o naugraphL1.o ${LDFLAGS} geng : gtools.h geng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o geng ${CFLAGS} -DMAXN=32 geng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} geng16 : gtools.h geng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o geng16 ${CFLAGS} -DMAXN=16 geng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} geng24 : gtools.h geng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o geng24 ${CFLAGS} -DMAXN=24 geng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} gentourng : gtools.h gentourng.c gtools.o nauty1.o nautil1.o naugraph1.o ${CC} -o gentourng ${CFLAGS} -DMAXN=24 gentourng.c gtools.o nauty1.o \ nautil1.o naugraph1.o ${LDFLAGS} genrang : gtools.h genrang.c gtools.o naututil.o nautil.o naugraph.o \ rng.o nausparse.o ${CC} -o genrang ${CFLAGS} genrang.c nausparse.o \ gtools.o nautil.o naututil.o naugraph.o rng.o ${LDFLAGS} complg : gtools.h complg.c gtools.o gtnauty.o nauty.o nautil.o \ naugraph.o nausparse.o ${CC} -o complg ${CFLAGS} complg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} biplabg : gtools.h biplabg.c gtools.o nautil.o naugraph.o gutil1.o ${CC} -o biplabg ${CFLAGS} biplabg.c \ gtools.o nautil.o naugraph.o gutil1.o ${LDFLAGS} NRswitchg : gtools.h NRswitchg.c gtools.o gtnauty.o nauty.o nautil.o \ nausparse.o naugraph.o ${CC} -o NRswitchg ${CFLAGS} NRswitchg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} deledgeg : gtools.h deledgeg.c gtools.o gtnauty.o nauty.o nautil.o \ naugraph.o nausparse.o ${CC} -o deledgeg ${CFLAGS} deledgeg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} addedgeg : gtools.h addedgeg.c gtools.o gtnauty.o nauty.o nautil.o \ naugraph.o gutil1.o nausparse.o ${CC} -o addedgeg ${CFLAGS} addedgeg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o gutil1.o nausparse.o ${LDFLAGS} newedgeg : gtools.h newedgeg.c nausparse.o \ gtools.o gtnauty.o nauty.o nautil.o naugraph.o ${CC} -o newedgeg ${CFLAGS} newedgeg.c gtools.o gtnauty.o \ nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} pickg : gtools.h testg.c splay.c nausparse.o \ gtools.o gtnauty.o nauty.o nautil.o naugraph.o gutil1.o gutil2.o ${CC} -o pickg ${SAFECFLAGS} testg.c gtools.o gtnauty.o gutil1.o \ gutil2.o nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} countg : gtools.h testg.c splay.c nausparse.o \ gtools.o gtnauty.o nauty.o nautil.o naugraph.o gutil1.o gutil2.o ${CC} -o countg ${SAFECFLAGS} testg.c gtools.o gtnauty.o gutil1.o \ gutil2.o nauty.o nautil.o naugraph.o nausparse.o ${LDFLAGS} directg : gtools.h naugroup.h directg.c \ gtools.o nauty.o nautil.o naugraph.o naugroup.o ${CC} -o directg ${CFLAGS} directg.c gtools.o \ nauty.o nautil.o naugraph.o naugroup.o ${LDFLAGS} multig : gtools.h naugroup.h multig.c \ gtools.o nauty.o nautil.o naugraph.o naugroup.o ${CC} -o multig ${CFLAGS} multig.c gtools.o \ nauty.o nautil.o naugraph.o naugroup.o ${LDFLAGS} planarg : gtools.h planarg.c gtools.o planarity.c ${CC} -o planarg ${CFLAGS} \ planarg.c planarity.c gtools.o ${LDFLAGS} showg : showg.c ${CC} -o showg ${CFLAGS} showg.c ${LDFLAGS} readg : echo "*** readg is now called showg ***" make showg gtoolsL1.o : gtools.h gtools.c ${CC} -c ${CFLAGS} ${L1} -o gtoolsL1.o gtools.c gtnautyL1.o : gtools.h gtnauty.c ${CC} -c ${CFLAGS} ${L1} -o gtnautyL1.o gtnauty.c sumlines : sumlines.c ${CC} -o sumlines ${CFLAGS} sumlines.c ${LDFLAGS} -lgmp nautyex1 : nauty.h nauty.o nautil.o naugraph.o nautyex1.c ${CC} -o nautyex1 ${CFLAGS} nautyex1.c nauty.o nautil.o \ naugraph.o ${LDFLAGS} nautyex2 : nauty.h nauty.o nautil.o naugraph.o nautyex2.c ${CC} -o nautyex2 ${CFLAGS} \ nautyex2.c nauty.o nautil.o naugraph.o ${LDFLAGS} naugroup.o : nauty.h naugroup.h naugroup.c ${CC} -c ${CFLAGS} naugroup.c nautyex3 : nauty.h nauty.o nautil.o naugraph.o naugroup.o nautyex3.c ${CC} -o nautyex3 ${CFLAGS} \ nautyex3.c nauty.o nautil.o naugraph.o naugroup.o ${LDFLAGS} nautyex4 : nauty.h nausparse.h nauty.o nautil.o \ nausparse.o naugroup.o nautyex4.c ${CC} -o nautyex4 ${CFLAGS} \ nautyex4.c nauty.o nautil.o nausparse.o naugroup.o ${LDFLAGS} nautyex5 : nauty.h nausparse.h nauty.o nautil.o \ nausparse.o naugroup.o nautyex5.c ${CC} -o nautyex5 ${CFLAGS} \ nautyex5.c nauty.o nautil.o nausparse.o naugroup.o ${LDFLAGS} dreadtest: dreadtest.c naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${CC} -o dreadtest ${SAFECFLAGS} dreadtest.c \ naututil.o nauty.o nautil.o nautinv.o naugraph.o rng.o ${LDFLAGS} ./dreadtest by * * making NUMINVARS have type int. Sorry, gcc. * * 10-Nov-90 - added calls to null routines (see comment on code) * * 27-Aug-92 : renamed to version 1.7, no changes to this file * * 5-Jun-93 : renamed to version 1.7+, no changes to this file * * 18-Aug-93 : renamed to version 1.8, no changes to this file * * 17-Sep-93 : changes for version 1.9 : * * - added invariant adjacencies() * * 7-Jun-96 : changes for version 2.0 : * * - added invariants cellfano() and cellfano2() * * - made y=10 the default * * 11-Jul-96 - added dynamic allocation * * - rewrote h command and added H command * * - implemented M and R commands * * 15-Aug-96 - changed z command to use sethash() * * 30-Aug-96 - no need to declare seed; already in naututil.h * * 12-Sep-96 - let i and I commands use userrefproc * * 9-Dec-96 - made y=infinity the default * * 6-Sep-97 - allocated arrays before accepting commands * * 7-Sep-97 - make g,canong,savedg 1-d arrays even statically * * 22-Sep-97 - undid error introduced on 7-Sep (worksize) * * 9-Jan-00 - used *_check() instead of *_null() * * 12-Feb-00 - minor code formatting * * 17-Aug-00 - now use tc_level from DEFAULTOPTIONS * * 16-Nov-00 - made changes listed in nauty.h * * 22-Apr-01 - include nautyinv.h * * - improve worksize processing for MAXN=0 * * 5-May-01 - k=0 1 automatic for *, also K=3 or K=0 * * 2-Jun-01 - added __ command for digraph converse * * 18-Oct-01 - moved WORKSIZE to here * * 21-Nov-01 - use NAUTYREQUIRED in *_check() calls * * 1-Sep-02 - Undid the previous change * * 17-Nov-03 - Changed INFINITY to NAUTY_INFINITY * * 15-Nov-04 - Completed all prototypes * * 23-Nov-06 - no usertcellproc() any more in version 2.4 * * * *****************************************************************************/ #include "naututil.h" /* which includes nauty.h, which includes stdio.h */ #include "nautinv.h" /* which includes nauty.h, which includes stdio.h */ #define PM(x) ((x) ? '+' : '-') #define SS(n,sing,plur) (n),((n)==1?(sing):(plur)) #define WORKSIZE 60 #ifdef CPUDEFS CPUDEFS /* data decls. for CPUTIME */ #endif #define INFILE fileptr[curfile] #define OUTFILE outfile #if !MAXN DYNALLSTAT(graph,g,g_sz); DYNALLSTAT(graph,canong,canong_sz); DYNALLSTAT(graph,savedg,savedg_sz); DYNALLSTAT(setword,workspace,workspace_sz); DYNALLSTAT(int,lab,lab_sz); DYNALLSTAT(int,ptn,ptn_sz); DYNALLSTAT(int,orbits,orbits_sz); DYNALLSTAT(int,savedlab,savedlab_sz); DYNALLSTAT(permutation,perm,perm_sz); DYNALLSTAT(set,active,active_sz); #else static graph g[MAXM*1L*MAXN]; static graph canong[MAXM*1L*MAXN]; static graph savedg[MAXM*1L*MAXN]; static setword workspace[MAXM*2L*WORKSIZE]; static int lab[MAXN]; static int ptn[MAXN]; static int orbits[MAXN]; static int savedlab[MAXN]; static permutation perm[MAXN]; static set active[MAXM]; #endif static DEFAULTOPTIONS_GRAPH(options); static statsblk stats; static int curfile; static FILE *fileptr[MAXIFILES]; static FILE *outfile; static char def_ext[] = DEFEXT; static boolean firstpath; /* used in usernode() */ #define U_NODE 1 /* masks for u values */ #define U_AUTOM 2 #define U_LEVEL 4 #define U_TCELL 8 /* At version 2.4, usertcellproc() is gone */ #define U_REF 16 #ifndef NODEPROC #define NODEPROC usernode #else extern void NODEPROC(graph*,int*,int*,int,int,int,int,int,int); #endif #ifndef AUTOMPROC #define AUTOMPROC userautom #else extern void AUTOMPROC(int,permutation*,int*,int,int,int); #endif #ifndef LEVELPROC #define LEVELPROC userlevel #else extern void LEVELPROC(int*,int*,int,int*,statsblk*,int,int,int,int,int,int); #endif #ifndef REFPROC #define REFPROC NULL #else extern void REFPROC(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); #endif #ifndef INVARPROC #define INVARPROC NULL #define INVARPROCNAME "none" #else extern void INVARPROC(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); #define INVARPROCNAME "user-defined" #endif static struct invarrec { void (*entrypoint)(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); char *name; } invarproc[] = {{INVARPROC, INVARPROCNAME}, {NULL, "none"}, {twopaths, "twopaths"}, {adjtriang, "adjtriang"}, {triples, "triples"}, {quadruples, "quadruples"}, {celltrips, "celltrips"}, {cellquads, "cellquads"}, {cellquins, "cellquins"}, {distances, "distances"}, {indsets, "indsets"}, {cliques, "cliques"}, {cellcliq, "cellcliq"}, {cellind, "cellind"}, {adjacencies, "adjacencies"}, {cellfano, "cellfano"}, {cellfano2, "cellfano2"}}; #define NUMINVARS ((int)(sizeof(invarproc)/sizeof(struct invarrec))) static void help(FILE*, int); static void userautom(int,permutation*,int*,int,int,int); static void usernode(graph*,int*,int*,int,int,int,int,int,int); static void userlevel(int*,int*,int,int*,statsblk*,int,int,int,int,int,int); #ifdef EXTRADECLS EXTRADECLS #endif /***************************************************************************** * * * This is a program which illustrates the use of nauty. * * Commands are read from stdin, and may be separated by white space, * * commas or not separated. Output is written to stdout. * * For a short description, see the nauty User's Guide. * * * *****************************************************************************/ int main(int argc, char *argv[]) { int m,n,newm,newn; boolean gvalid,ovalid,cvalid,pvalid,minus,prompt,doquot; int i,worksize,numcells,refcode,umask,qinvar; int oldorg; char *s1,*s2,*invarprocname; int c,d; long li; unsigned long uli; set *gp; double timebefore,timeafter; char filename[200]; int sgn,sgorg,nperm; int multiplicity; boolean options_writeautoms,options_writemarkers; long zseed; curfile = 0; fileptr[curfile] = stdin; prompt = DOPROMPT(INFILE); outfile = stdout; options_writeautoms = options_writemarkers = TRUE; n = m = 1; worksize = 2*WORKSIZE; #if !MAXN n = WORDSIZE; DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut"); DYNALLOC1(int,lab,lab_sz,n,"dreadnaut"); DYNALLOC1(int,ptn,ptn_sz,n,"dreadnaut"); DYNALLOC1(setword,workspace,workspace_sz, worksize,"dreadnaut"); DYNALLOC1(int,orbits,orbits_sz,n,"dreadnaut"); DYNALLOC1(permutation,perm,perm_sz,n,"dreadnaut"); DYNALLOC1(set,active,active_sz,m,"dreadnaut"); n = 1; #endif #ifdef INITSEED INITSEED; ran_init(seed); #endif umask = 0; pvalid = FALSE; gvalid = FALSE; ovalid = FALSE; cvalid = FALSE; minus = FALSE; labelorg = oldorg = 0; multiplicity = 1; #ifdef INITIALIZE INITIALIZE; #endif invarprocname = "none"; if (prompt) { fprintf(PROMPTFILE,"Dreadnaut version %s.\n",NAUTYVERSION); fprintf(PROMPTFILE,"> "); } nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); nautinv_check(WORDSIZE,1,1,NAUTYVERSIONID); nautil_check(WORDSIZE,1,1,NAUTYVERSIONID); naututil_check(WORDSIZE,1,1,NAUTYVERSIONID); while (curfile >= 0) if ((c = getc(INFILE)) == EOF || c == '\004') { fclose(INFILE); --curfile; if (curfile >= 0) prompt = DOPROMPT(INFILE); } else switch (c) { case '\n': /* possibly issue prompt */ if (prompt) fprintf(PROMPTFILE,"> "); minus = FALSE; break; case ' ': /* do nothing */ case '\t': #ifndef NLMAP case '\r': #endif case '\f': break; case '-': /* remember this for next time */ minus = TRUE; break; case '+': /* forget - */ case ',': case ';': minus = FALSE; break; case '<': /* new input file */ minus = FALSE; if (curfile == MAXIFILES - 1) fprintf(ERRFILE,"exceeded maximum input nesting of %d\n\n", MAXIFILES); if (!readstring(INFILE,filename,200)) { fprintf(ERRFILE, "missing file name on '>' command : ignored\n\n"); break; } if ((fileptr[curfile+1] = fopen(filename,"r")) == NULL) { for (s1 = filename; *s1 != '\0'; ++s1) {} for (s2 = def_ext; (*s1 = *s2) != '\0'; ++s1, ++s2) {} fileptr[curfile+1] = fopen(filename,"r"); } if (fileptr[curfile+1] != NULL) { ++curfile; prompt = DOPROMPT(INFILE); if (prompt) fprintf(PROMPTFILE,"> "); } else fprintf(ERRFILE,"can't open input file\n\n"); break; case '>': /* new output file */ if ((d = getc(INFILE)) != '>') ungetc((char)d,INFILE); if (minus) { minus = FALSE; if (outfile != stdout) { fclose(outfile); outfile = stdout; } } else { if (!readstring(INFILE,filename,200)) { fprintf(ERRFILE, "improper file name, reverting to stdout\n\n"); outfile = stdout; break; } OPENOUT(outfile,filename,d=='>'); if (outfile == NULL) { fprintf(ERRFILE, "can't open output file, reverting to stdout\n\n"); outfile = stdout; } } break; case '!': /* ignore rest of line */ do c = getc(INFILE); while (c != '\n' && c != EOF); if (c == '\n') ungetc('\n',INFILE); break; case 'n': /* read n value */ minus = FALSE; i = getint(INFILE); if (i <= 0 || (MAXN && i > MAXN) || (!MAXN && i > NAUTY_INFINITY-2)) fprintf(ERRFILE, " n can't be less than 1 or more than %d\n\n", MAXN ? MAXN : NAUTY_INFINITY-2); else { gvalid = FALSE; ovalid = FALSE; cvalid = FALSE; pvalid = FALSE; n = i; m = (n + WORDSIZE - 1) / WORDSIZE; #if !MAXN worksize = 2 * m * WORKSIZE; DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut"); DYNALLOC1(int,lab,lab_sz,n,"dreadnaut"); DYNALLOC1(int,ptn,ptn_sz,n,"dreadnaut"); DYNALLOC1(setword,workspace,workspace_sz, worksize,"dreadnaut"); DYNALLOC1(int,orbits,orbits_sz,n,"dreadnaut"); DYNALLOC1(permutation,perm,perm_sz,n,"dreadnaut"); DYNALLOC1(set,active,active_sz,m,"dreadnaut"); #endif } break; case 'g': /* read graph */ minus = FALSE; readgraph(INFILE,g,options.digraph,prompt,FALSE, options.linelength,m,n); gvalid = TRUE; cvalid = FALSE; ovalid = FALSE; break; case 'e': /* edit graph */ minus = FALSE; readgraph(INFILE,g,options.digraph,prompt,gvalid, options.linelength,m,n); gvalid = TRUE; cvalid = FALSE; ovalid = FALSE; break; case 'r': /* relabel graph and current partition */ minus = FALSE; if (gvalid) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif readvperm(INFILE,perm,prompt,n,&nperm); relabel(g,(pvalid ? lab : NULL),perm,canong,m,n); cvalid = FALSE; ovalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case 'R': /* form subgraph */ if (gvalid) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif readvperm(INFILE,perm,prompt,n,&nperm); if (minus && nperm == n || !minus && nperm == 0) fprintf(ERRFILE,"can't form null graph\n\n"); else if (minus) { sublabel(g,perm+nperm,n-nperm,canong,m,n); n = n - nperm; } else { sublabel(g,perm,nperm,canong,m,n); n = nperm; } cvalid = FALSE; pvalid = FALSE; ovalid = FALSE; m = (n + WORDSIZE - 1) / WORDSIZE; } else fprintf(ERRFILE,"g is not defined\n\n"); minus = FALSE; break; case '_': /* complement graph or converse digraph */ minus = FALSE; if ((d = getc(INFILE)) != '_') ungetc((char)d,INFILE); if (gvalid) { if (d == '_') converse(g,m,n); else complement(g,m,n); cvalid = FALSE; ovalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case '@': /* copy canong into savedg */ minus = FALSE; if (cvalid) { #if !MAXN DYNALLOC2(graph,savedg,savedg_sz,n,m,"dreadnaut"); DYNALLOC1(int,savedlab,savedlab_sz,n,"dreadnaut"); #endif sgn = n; for (li = (long)n * (long)m; --li >= 0;) savedg[li] = canong[li]; for (i = n; --i >= 0;) savedlab[i] = lab[i]; sgorg = labelorg; } else fprintf(ERRFILE,"h is not defined\n\n"); break; case '#': /* compare canong to savedg */ if ((d = getc(INFILE)) != '#') ungetc((char)d,INFILE); if (cvalid) { if (sgn > 0) { if (sgn != n) fprintf(OUTFILE, "h and h' have different sizes.\n"); else { for (li = (long)n * (long)m; --li >= 0;) if (savedg[li] != canong[li]) break; if (li >= 0) fprintf(OUTFILE,"h and h' are different.\n"); else { fprintf(OUTFILE, "h and h' are identical.\n"); if (d == '#') putmapping(OUTFILE,savedlab,sgorg, lab,labelorg,options.linelength,n); } } } else fprintf(ERRFILE,"h' is not defined\n\n"); } else fprintf(ERRFILE,"h is not defined\n\n"); break; case 'j': /* relabel graph randomly */ minus = FALSE; if (gvalid) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif ranperm(perm,n); relabel(g,(pvalid ? lab : NULL),perm,canong,m,n); cvalid = FALSE; ovalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case 'v': /* write vertex degrees */ minus = FALSE; if (gvalid) putdegs(OUTFILE,g,options.linelength,m,n); else fprintf(ERRFILE,"g is not defined\n\n"); break; case '%': /* do Mathon doubling operation */ minus = FALSE; if (gvalid) { #if !MAXN if (2L * ((long)n + 1L) > NAUTY_INFINITY-2) { fprintf(ERRFILE, "n can't be more than %d\n\n",NAUTY_INFINITY-2); break; } #else if (2L * ((long)n + 1L) > MAXN) { fprintf(ERRFILE,"n can't be more than %d\n\n",MAXN); break; } #endif newn = 2 * (n + 1); newm = (newn + WORDSIZE - 1) / WORDSIZE; #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif for (li = (long)n * (long)m; --li >= 0;) canong[li] = g[li]; #if !MAXN DYNALLOC2(graph,g,g_sz,newn,newm,"dreadnaut"); DYNALLOC1(int,lab,lab_sz,newn,"dreadnaut"); DYNALLOC1(int,ptn,ptn_sz,newn,"dreadnaut"); worksize = 2*WORKSIZE*newm; DYNALLOC1(setword,workspace,workspace_sz, worksize,"dreadnaut"); DYNALLOC1(int,orbits,orbits_sz,newn,"dreadnaut"); DYNALLOC1(permutation,perm,perm_sz,newn,"dreadnaut"); DYNALLOC1(set,active,active_sz,newm,"dreadnaut"); #endif mathon(canong,m,n,g,newm,newn); m = newm; n = newn; cvalid = FALSE; ovalid = FALSE; pvalid = FALSE; } else fprintf(ERRFILE,"g is not defined\n\n"); break; case 's': /* generate random graph */ minus = FALSE; i = getint(INFILE); if (i <= 0) i = 2; rangraph(g,options.digraph,i,m,n); gvalid = TRUE; cvalid = FALSE; ovalid = FALSE; break; case 'q': /* quit */ EXIT; break; case '"': /* copy comment to output */ minus = FALSE; copycomment(INFILE,OUTFILE,'"'); break; case 'I': /* do refinement and invariants procedure */ if (!pvalid) unitptn(lab,ptn,&numcells,n); cellstarts(ptn,0,active,m,n); #ifdef CPUTIME timebefore = CPUTIME; #endif doref(g,lab,ptn,0,&numcells,&qinvar,perm,active,&refcode, options.userrefproc ? options.userrefproc : (m == 1 ? refine1 : refine), options.invarproc,0,0, options.invararg,options.digraph,m,n); #ifdef CPUTIME timeafter = CPUTIME; #endif fprintf(OUTFILE," %d cell%s; code = %x", SS(numcells,"","s"),refcode); if (options.invarproc != NULL) fprintf(OUTFILE," (%s %s)",invarprocname, (qinvar == 2 ? "worked" : "failed")); #ifdef CPUTIME fprintf(OUTFILE,"; cpu time = %.2f seconds\n", timeafter-timebefore); #else fprintf(OUTFILE,"\n"); #endif if (numcells > 1) pvalid = TRUE; break; case 'i': /* do refinement */ if (!pvalid) unitptn(lab,ptn,&numcells,n); cellstarts(ptn,0,active,m,n); if (options.userrefproc) (*options.userrefproc) (g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); else if (m == 1) refine1(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); else refine(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); fprintf(OUTFILE," %d cell%s; code = %x\n", SS(numcells,"","s"),refcode); if (numcells > 1) pvalid = TRUE; break; case 'x': /* execute nauty */ minus = FALSE; ovalid = FALSE; cvalid = FALSE; if (!gvalid) { fprintf(ERRFILE,"g is not defined\n\n"); break; } if (pvalid) { fprintf(OUTFILE,"[fixing partition]\n"); options.defaultptn = FALSE; } else options.defaultptn = TRUE; options.outfile = outfile; if (options.getcanon) { #if !MAXN DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif } firstpath = TRUE; options.writeautoms = options_writeautoms; options.writemarkers = options_writemarkers; #ifdef CPUTIME timebefore = CPUTIME; #endif for (i = 0; i < multiplicity; ++i) { nauty(g,lab,ptn,NULL,orbits,&options,&stats,workspace, worksize,m,n,canong); options.writeautoms = FALSE; options.writemarkers = FALSE; } #ifdef CPUTIME timeafter = CPUTIME; #endif if (stats.errstatus != 0) fprintf(ERRFILE, "nauty returned error status %d [this can't happen]\n\n", stats.errstatus); else { if (options.getcanon) cvalid = TRUE; ovalid = TRUE; fprintf(OUTFILE,"%d orbit%s",SS(stats.numorbits,"","s")); if (stats.grpsize2 == 0) fprintf(OUTFILE,"; grpsize=%.0f",stats.grpsize1+0.1); else { while (stats.grpsize1 >= 10.0) { stats.grpsize1 /= 10.0; ++stats.grpsize2; } fprintf(OUTFILE,"; grpsize=%12.10fe%d", stats.grpsize1,stats.grpsize2); } fprintf(OUTFILE,"; %d gen%s", SS(stats.numgenerators,"","s")); fprintf(OUTFILE,"; %lu node%s",SS(stats.numnodes,"","s")); if (stats.numbadleaves) fprintf(OUTFILE," (%lu bad lea%s)", SS(stats.numbadleaves,"f","ves")); fprintf(OUTFILE,"; maxlev=%d\n", stats.maxlevel); fprintf(OUTFILE,"tctotal=%lu",stats.tctotal); if (options.getcanon) fprintf(OUTFILE,"; canupdates=%lu",stats.canupdates); #ifdef CPUTIME fprintf(OUTFILE,multiplicity == 1 ? "; cpu time = %.2f seconds\n" : "; cpu time = %.5f seconds\n", (timeafter-timebefore)/multiplicity); #else fprintf(OUTFILE,"\n"); #endif if (options.invarproc != NULL && options.maxinvarlevel != 0) { fprintf(OUTFILE,"invarproc \"%s\" succeeded %lu/%lu", invarprocname,stats.invsuccesses,stats.invapplics); if (stats.invarsuclevel > 0) fprintf(OUTFILE," beginning at level %d.\n", stats.invarsuclevel); else fprintf(OUTFILE,".\n"); } } break; case 'f': /* read initial partition */ if (minus) { pvalid = FALSE; minus = FALSE; } else { readptn(INFILE,lab,ptn,&numcells,prompt,n); pvalid = TRUE; } break; case 't': /* type graph */ minus = FALSE; if (!gvalid) fprintf(ERRFILE,"g is not defined\n\n"); else putgraph(OUTFILE,g,options.linelength,m,n); break; case 'T': /* type graph preceded by n, $ and g commands */ minus = FALSE; if (!gvalid) fprintf(ERRFILE,"g is not defined\n\n"); else { fprintf(OUTFILE,"n=%d $=%d g\n",n,labelorg); putgraph(OUTFILE,g,options.linelength,m,n); fprintf(OUTFILE,"$$\n"); } break; case 'u': /* call user procs */ if (minus) { umask = 0; minus = FALSE; } else { umask = getint(INFILE); if (umask < 0) umask = ~0; } if (umask & U_NODE) options.usernodeproc = NODEPROC; else options.usernodeproc = NULL; if (umask & U_AUTOM) options.userautomproc = AUTOMPROC; else options.userautomproc = NULL; if (umask & U_LEVEL) options.userlevelproc = LEVELPROC; else options.userlevelproc = NULL; if (umask & U_TCELL) fprintf(ERRFILE,"usertcellproc() gone at version 2.4\n\n"); if (umask & U_REF) options.userrefproc = REFPROC; else options.userrefproc = NULL; break; case 'o': /* type orbits */ minus = FALSE; if (ovalid) putorbits(OUTFILE,orbits,options.linelength,n); else fprintf(ERRFILE,"orbits are not defined\n\n"); break; case 'b': /* type canonlab and canong */ minus = FALSE; if (cvalid) putcanon(OUTFILE,lab,canong,options.linelength,m,n); else fprintf(ERRFILE,"h is not defined\n\n"); break; case 'z': /* type hashcode for canong */ minus = FALSE; if (cvalid) { zseed = n; for (i = 0, gp = canong; i < n; ++i, gp += m) zseed = sethash(gp,n,zseed,321); fprintf(OUTFILE,"[%7lx",zseed); for (i = 0, gp = canong; i < n; ++i, gp += m) zseed = sethash(gp,n,zseed,3109); fprintf(OUTFILE," %7lx",zseed); for (i = 0, gp = canong; i < n; ++i, gp += m) zseed = sethash(gp,n,zseed,4317); fprintf(OUTFILE," %7lx]\n",zseed); } else fprintf(ERRFILE,"h is not defined\n\n"); break; case 'c': /* set getcanon option */ options.getcanon = !minus; minus = FALSE; break; case 'w': /* read size of workspace */ minus = FALSE; worksize = getint(INFILE); #if !MAXN DYNALLOC1(setword,workspace,workspace_sz,worksize,"dreadnaut"); #else if (worksize > 2*MAXM*WORKSIZE) { fprintf(ERRFILE, "too big - setting worksize = %d\n\n", 2*MAXM*WORKSIZE); worksize = 2*MAXM*WORKSIZE; } #endif break; case 'l': /* read linelength for output */ options.linelength = getint(INFILE); minus = FALSE; break; case 'y': /* set tc_level field of options */ options.tc_level = getint(INFILE); minus = FALSE; break; case 'M': /* set multiplicity */ multiplicity = getint(INFILE); if (multiplicity <= 0) multiplicity = 1; minus = FALSE; break; case 'k': /* set invarlev fields of options */ options.mininvarlevel = getint(INFILE); options.maxinvarlevel = getint(INFILE); minus = FALSE; break; case 'K': /* set invararg field of options */ options.invararg = getint(INFILE); minus = FALSE; break; case '*': /* set invarproc field of options */ minus = FALSE; d = getint(INFILE); if (d >= -1 && d <= NUMINVARS-2) { options.invarproc = invarproc[d+1].entrypoint; invarprocname = invarproc[d+1].name; if (options.invarproc != NULL) { options.mininvarlevel = 0; options.maxinvarlevel = 1; if (options.invarproc == indsets || options.invarproc == cliques || options.invarproc == cellind || options.invarproc == cellcliq) options.invararg = 3; else options.invararg = 0; } } else fprintf(ERRFILE,"no such vertex-invariant\n\n"); break; case 'a': /* set writeautoms option */ options_writeautoms = !minus; minus = FALSE; break; case 'm': /* set writemarkers option */ options_writemarkers = !minus; minus = FALSE; break; case 'p': /* set cartesian option */ options.cartesian = !minus; minus = FALSE; break; case 'd': /* set digraph option */ if (options.digraph && minus) gvalid = FALSE; options.digraph = !minus; minus = FALSE; break; case '$': /* set label origin */ if ((d = getc(INFILE)) == '$') labelorg = oldorg; else { ungetc((char)d,INFILE); oldorg = labelorg; i = getint(INFILE); if (i < 0) fprintf(ERRFILE,"labelorg must be >= 0\n\n"); else labelorg = i; } break; case '?': /* type options, etc. */ minus = FALSE; fprintf(OUTFILE,"m=%d n=%d labelorg=%d",m,n,labelorg); if (!gvalid) fprintf(OUTFILE," g=undef"); else { uli = 0; for (i = 0, gp = g; i < n; ++i, gp += m) uli += setsize(gp,m); if (options.digraph) fprintf(OUTFILE," arcs=%lu",uli); else fprintf(OUTFILE," edges=%lu",uli/2); } fprintf(OUTFILE," options=(%cc%ca%cm%cp%cd", PM(options.getcanon),PM(options_writeautoms), PM(options_writemarkers),PM(options.cartesian), PM(options.digraph)); if (umask & 31) fprintf(OUTFILE," u=%d",umask&31); if (options.tc_level > 0) fprintf(OUTFILE," y=%d",options.tc_level); if (options.mininvarlevel != 0 || options.maxinvarlevel != 0) fprintf(OUTFILE," k=(%d,%d)", options.mininvarlevel,options.maxinvarlevel); if (options.invararg > 0) fprintf(OUTFILE," K=%d",options.invararg); if (multiplicity > 1) fprintf(OUTFILE," M=%d",multiplicity); fprintf(OUTFILE,")\n"); fprintf(OUTFILE,"linelen=%d worksize=%d input_depth=%d", options.linelength,worksize,curfile); if (options.invarproc != NULL) fprintf(OUTFILE," invarproc=%s",invarprocname); if (pvalid) fprintf(OUTFILE,"; %d cell%s",SS(numcells,"","s")); else fprintf(OUTFILE,"; 1 cell"); fprintf(OUTFILE,"\n"); if (OUTFILE != PROMPTFILE) fprintf(PROMPTFILE,"m=%d n=%d depth=%d labelorg=%d\n", m,n,curfile,labelorg); break; case '&': /* list the partition and possibly the quotient */ if ((d = getc(INFILE)) == '&') doquot = TRUE; else { ungetc((char)d,INFILE); doquot = FALSE; } minus = FALSE; if (pvalid) putptn(OUTFILE,lab,ptn,0,options.linelength,n); else fprintf(OUTFILE,"unit partition\n"); if (doquot) { if (!pvalid) unitptn(lab,ptn,&numcells,n); putquotient(OUTFILE,g,lab,ptn,0,options.linelength,m,n); } break; case 'h': /* type help information */ case 'H': minus = FALSE; help(PROMPTFILE,c == 'H'); break; default: /* illegal command */ fprintf(ERRFILE,"'%c' is illegal - type 'h' for help\n\n",c); flushline(INFILE); if (prompt) fprintf(PROMPTFILE,"> "); break; } /* end of switch */ exit(0); } /***************************************************************************** * * * help(f,i) writes help information to file f (i = 0,1). * * * *****************************************************************************/ static void help(FILE *f, int i) { #define H(ss) fprintf(f," %s\n",ss); if (i == 0) { H("+- a : write automs v : write degrees *=# : select invariant:") H(" b : write canong w=# : set worksize") H("+- c : canonise x : run nauty -1 = user-defined") H("+- d : digraph or loops y=# : set tc_level 0 = none") H(" e : edit graph z : write hashcode 1 = twopaths") H("-f, f=#, f=[...] : set colours 2 = adjtriang(K=0,1)") H(" g : read graph $=# : set origin 3 = triples") H(" h,H : help $$ : restore origin 4 = quadruples") H(" i : refine ? : type options 5 = celltrips") H(" I : refine using invar _ : compl __ : conv 6 = cellquads") H(" j : relabel randomly % : Mathon doubling 7 = cellquins") H("k=# # : set invar levels & : type colouring 8 = distances(K)") H(" K=# : set invar param && : + quotient matrix 9 = indsets(K)") H(" l=# : set line length >ff : write to file 10 = cliques(K)") H("+- m : write markers >>ff : append to file 11 = cellcliq(K)") H(" n=# : set order -> : revert to stdout 12 = cellind(K)") H(" o : write orbits numnodes,numcells,stats->numorbits,stats->numgenerators); } nauty24r2/addedgeg.c0000600000604200001440000001672411274163463013211 0ustar bdmusers/* addedgeg.c nauty version 2.5; B D McKay, March 2009. */ #define USAGE "addedgeg [-lq] [-D#] [-btfF] [-z#] [infile [outfile]]" #define HELPTEXT \ " For each edge nonedge e, output G+e if it satisfies certain conditions\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -l Canonically label outputs\n\ -D# Specify an upper bound on the maximum degree of the output\n\ -b Output has no new cycles of odd length\n\ -t Output has no new 3-cycle if input doesn't\n\ -f Output has no new 4-cycle if input doesn't\n\ -F Output has no new 5-cycle if input doesn't\n\ -z# Output has no new cycles of length less than #\n\ -btfFz can be used in arbitrary combinations\n\ -q Suppress auxiliary information\n" /*************************************************************************/ #include "gtools.h" #include "gutils.h" /*************************************************************************/ static void no3path(graph *g, int m, int n, int v, int *dist) /* For each i, set dist[i]=0 if there is a 3-path from v to i */ { set *gv,*gv1,*gv2; int v1,v2,v3; gv = GRAPHROW(g,v,m); for (v1 = -1; (v1 = nextelement(gv,m,v1)) >= 0; ) { gv1 = GRAPHROW(g,v1,m); for (v2 = -1; (v2 = nextelement(gv1,m,v2)) >= 0; ) { if (v2 == v) continue; gv2 = GRAPHROW(g,v2,m); for (v3 = -1; (v3 = nextelement(gv2,m,v3)) >= 0; ) if (v3 != v && v3 != v1) dist[v3] = 0; } } } /*************************************************************************/ static void no4path(graph *g, int m, int n, int v, int *dist) /* For each i, set dist[i]=0 if there is a 4-path from v to i */ { set *gv,*gv1,*gv2,*gv3; int v1,v2,v3,v4; gv = GRAPHROW(g,v,m); for (v1 = -1; (v1 = nextelement(gv,m,v1)) >= 0; ) { gv1 = GRAPHROW(g,v1,m); for (v2 = -1; (v2 = nextelement(gv1,m,v2)) >= 0; ) { if (v2 == v) continue; gv2 = GRAPHROW(g,v2,m); for (v3 = -1; (v3 = nextelement(gv2,m,v3)) >= 0; ) { if (v3 == v || v3 == v1) continue; gv3 = GRAPHROW(g,v3,m); for (v4 = -1; (v4 = nextelement(gv3,m,v4)) >= 0; ) if (v4 != v && v4 != v1 && v4 != v2) dist[v4] = 0; } } } } /*************************************************************************/ int main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile,*outfile; boolean badargs,dolabel,quiet,Dswitch; boolean bswitch,tswitch,fswitch,Fswitch,zswitch; int mincycle; int i,j,m,n,v,w,argnum; int codetype,outcode; graph *g,*gq; nauty_counter nin,nout; char *arg,sw; setword *gv,*gw; int maxdeg,actmaxdeg,degv; double t; #if MAXN graph h[MAXN*MAXM]; int deg[MAXN],dist[MAXN]; boolean okdist[MAXN+1]; #else DYNALLSTAT(graph,h,h_sz); DYNALLSTAT(int,deg,deg_sz); DYNALLSTAT(boolean,okdist,okdist_sz); DYNALLSTAT(int,dist,dist_sz); #endif HELP; infilename = outfilename = NULL; badargs = FALSE; Dswitch = dolabel = quiet = zswitch = FALSE; bswitch = tswitch = fswitch = Fswitch = FALSE; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('l',dolabel) else SWBOOLEAN('q',quiet) else SWBOOLEAN('b',bswitch) else SWBOOLEAN('t',tswitch) else SWBOOLEAN('f',fswitch) else SWBOOLEAN('F',Fswitch) else SWINT('z',zswitch,mincycle,">E addedgeg -z") else SWINT('D',Dswitch,maxdeg,">E addedgeg -D") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!quiet) { fprintf(stderr,">A addedgeg"); if (dolabel) fprintf(stderr," -l"); if (Dswitch) fprintf(stderr," -D%d",maxdeg); if (bswitch || tswitch || fswitch || Fswitch || zswitch) { fprintf(stderr," -"); if (bswitch) fprintf(stderr,"b"); if (tswitch) fprintf(stderr,"t"); if (fswitch) fprintf(stderr,"f"); if (Fswitch) fprintf(stderr,"F"); if (zswitch) fprintf(stderr,"z%d",mincycle); } if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (codetype&HAS_HEADER) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } if (!Dswitch) maxdeg = NAUTY_INFINITY; if (dolabel) nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); nin = nout = 0; t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; #if !MAXN DYNALLOC1(int,deg,deg_sz,n,"addedgeg"); DYNALLOC1(boolean,okdist,okdist_sz,n+1,"addedgeg"); 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; } if (actmaxdeg > maxdeg) continue; okdist[0] = okdist[1] = FALSE; for (i = 2; i <= n; ++i) okdist[i] = TRUE; if (bswitch) for (i = 2; i < n; i += 2) okdist[i] = FALSE; if (tswitch && n >= 3) okdist[2] = FALSE; if (fswitch && n >= 4) okdist[3] = FALSE; if (Fswitch && n >= 5) okdist[4] = FALSE; if (zswitch) for (i = 2; i < mincycle-1 && i < n; ++i) okdist[i] = FALSE; for (v = 0, gv = g; v < n-1; ++v, gv += m) { if (deg[v] >= maxdeg) continue; find_dist(g,m,n,v,dist); for (w = v+1; w < n; ++w) dist[w] = okdist[dist[w]] && (deg[w] < maxdeg); if (fswitch) no3path(g,m,n,v,dist); if (Fswitch) no4path(g,m,n,v,dist); for (w = v+1; w < n; ++w) { if (!dist[w]) continue; gw = GRAPHROW(g,w,m); ADDELEMENT(gv,w); ADDELEMENT(gw,v); gq = g; if (dolabel) { #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"addedgeg"); #endif fcanonise(g,m,n,h,NULL,FALSE); /*FIXME (loops)*/ gq = h; } if (outcode == SPARSE6) writes6(outfile,gq,m,n); else writeg6(outfile,gq,m,n); ++nout; DELELEMENT(gv,w); DELELEMENT(gw,v); } } FREES(g); } t = CPUTIME - t; #if LONG_LONG_COUNTERS if (!quiet) fprintf(stderr, ">Z %lld graphs read from %s, %lld written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,t); #else if (!quiet) fprintf(stderr, ">Z %ld graphs read from %s, %ld written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,t); #endif exit(0); } nauty24r2/sumlines.c0000600000604200001440000011607111274163463013320 0ustar bdmusers/* sumlines.c - total the numbers appearing in various input lines. */ /* B. D. McKay. Version of Aug 3, 2009. */ #ifndef GMP #define GMP 1 /* Non-zero if gmp multi-precise integers are allowed. In this case you need the GNU multi-precision library, available with -lgmp if it is installed. */ #endif #define USAGE \ "sumlines [-w] [-v] [-d] [-n] [-f fmtfile]... file file file ..." #define HELPTEXT \ " Sum lines matching specified formats.\n\ \n\ Any number of input files can be given. \"-\" means stdin.\n\ If there are no files given, just stdin is assumed.\n\ File names can contain wildcards, in which case all matching files\n\ are used in numerically sorted order.\n\ \n\ Formats are read from four sources in this order:\n\ (1) Any files mentioned with -f on the command line (any number).\n\ (2) The file named in the environment variable SUMLINES.FMT (if any)\n\ (3) The file sumlines.fmt in the current directory (if it exists)\n\ (4) The file sumlines.fmt in the home directory (if it exists)\n\ All these are read if they exist and the results concatenated.\n\ Formats exactly matching earlier formats (except perhaps for flags)\n\ are not used.\n\ \n\ Each format occupies exactly two lines. The first line gives a\n\ list of flags (DEFAULT FINAL ERROR UNIQUE COUNT CONTINUE NUMERIC\n\ SILENT ENDFILE P=# separated by spaces, commas or |s).\n\ The second line gives the format itself.\n\ \n\ Example. This totals the summary lines of autoson runs:\n\ DEFAULT # comment \n\ cpu=%fu,%fs,%fx pf=%d\n\ There can also be blank lines and lines with only comments, but\n\ not between the flags line and the format itself.\n\ \n\ -d don't read sumlines.fmt or ~/sumlines.fmt or $SUMLINES.FMT \n\ -w suppresses warning messages about no matching lines or no\n\ matching final lines.\n\ -n don't write the number of matching lines for each format.\n\ -v produces a list of all the formats.\n" #define DEFAULT 0 /* No special flags */ #define FINAL 1 /* At least one of these must be in each input file */ #define ERROR 2 /* Must be none of these */ #define UNIQUE 4 /* The %s and %c parts must be unique over all inputs */ #define COUNT 8 /* The output only states how many lines matched */ #define CONTINUE 16 /* Try to match later formats too */ #define NUMERIC 32 /* Use numerical comparison (see numstrcmp() below) */ #define SILENT 64 /* Don't report, just check */ #define ENDFILE 128 /* Usually appears at end of output */ /* The formats are tried against each input line one at a time, and the first one that matches is accepted. The entire line must match. If the CONTINUE flag is present, the input line is also matched against further formats. Except in the case of formats with the COUNT flag, each format that matches any lines produces output giving the total value of each of the integers %d or real numbers %f in the lines which match. If there are any %s or %c controls in the format, the output is given separately for each value of the matching strings which appear in the input lines. %m is like %d but allows arbitrarily large integers. %x is like %d but the maximum rather than the sum is accumulated. %p is like %d but the value is accumulated modulo some base. In the case of the COUNT flag, the program only reports the number of input lines which matched the format. If a format has the UNIQUE flag, no two input lines may match with the same values of the %s and %c controls present. Otherwise a warning message is written for each duplicate match. The sequence P=# where # is an integer value defines the base for the %p directive. There can be no spaces in the sequence "P=#". The default base is 2. %d - matches an integer (small enough for 64 bits) %x - same as %d but accumulates maximum rather than the sum %p - same as %d but accumulates the value modulo a base %m - matches a integer of unbounded size (if GMP!=0) %f - matches a real number of the form ddddd.ddd or -ddddd.ddd %v - same as %f but reports the average rather than the sum %sx - matches a string, where 'x' is any character. If 'x' is not a space, match zero or more characters from the current position up but not including the first 'x'. If 'x' is a space, match one or more characters from the current position up to and including the first non-space character which is followed by a space. %c - matches a non-white character %% - matches the character '%' % - (with a space following the '%') matches zero or more spaces or tabs, as many as appear in the input. In the output, this sequence appears as one space. % - (appearing exactly at the end of the format) matches zero or more spaces at the end of the line. In the output, nothing. %*d, %*m, %*x, %*p, %*f, %*sx, %*c - these are similar to the versions without the '*' except that the value is ignored (not used for summing, and not used to divide the output). In the output, this field appears as a single character '*'. %# - matches an unsigned integer. For each format containing this control, a report is made of any breaks or duplicates in the sequence of matching numbers. (So this is useful for checking a sequence of case numbers.) At most one %# may appear in each format. %l - matches a list of arbitrarily many (%d sized) integers At least one FINAL format must match in each file or a warning is given (unless -w is used, in which case no warning is given). A format marked ENDFILE will cause sumlines to act as if it started reading from a new input file. This can have some effects on the order of output lines. */ #define HAS(i,flgs) ((format[i].flags&(flgs)) != 0) #include #include #include #include #include #include #include #if GMP #include #endif #if defined(__alpha) typedef long integer; #define DOUT "%ld" /* Formats used to output %d/%x/%p,%f,%v quantities */ #define FOUT "%.2f" #define VOUT "%.4f" #elif defined(__sun) || defined(__GNUC__) || (__STDC_VERSION__ > 199900L) typedef long long integer; #define DOUT "%lld" #define FOUT "%.2f" #define VOUT "%.4f" #else typedef long long integer; #define DOUT "%Ld" #define FOUT "%.2f" #define VOUT "%.4f" #endif static char *dout,*fout,*vout; static integer maxint; /* set by find_maxint() */ #define INCR(x,inc) \ {if ((x) > 0 && maxint-(x) < (inc) || (x) < 0 && (maxint)+(x) < -(inc)) \ {fprintf(stderr,">E overflow with %d or %p format\n"); exit(1);} \ x += (inc);} /* x += inc with safety check */ typedef int boolean; #define FALSE 0 #define TRUE 1 typedef struct { int nvals; integer *val; } integerlist; typedef union { double f; integer d; integerlist *l; #if GMP mpz_t *m; #endif } number; #define D 0 /* Code for "integer" */ #define F 1 /* Code for "real" */ #define M 2 /* Code for "multiprecision integer" */ #define X 3 /* Code for "integer, take maximum" */ #define V 4 /* Code for "real, take average" */ #define P 5 /* Code for "integer, modulo some base" */ #define LD 6 /* Code for "list of integer" */ #define MAXLINELEN 100000 /* Maximum input line size (longer lines are broken in bits) */ #define MAXVALUES 16 /* Maximum total number of %d,%x,%p,%m,%v,%f or %l items in a format */ #define MAXFORMATS 1000 static struct fmt_st { integer pmod; int flags; char *fmt; } format[MAXFORMATS]; typedef struct countrec { struct countrec *left,*right,*parent; char *fmt; unsigned long count; number total[MAXVALUES]; } countnode; static countnode *count_root[MAXFORMATS]; static unsigned long matching_lines[MAXFORMATS]; static integer total_position[MAXFORMATS]; static integer lastseq[MAXFORMATS]; #if GMP static mpz_t mp_value[MAXVALUES]; #endif static integerlist il[MAXVALUES]; #define A 0 #define L 1 #define R 2 #define LL 3 #define LR 4 #define RL 5 #define RR 6 #ifndef GLOB_BRACE /* Allow {} processing -- Linux extension */ #define GLOB_BRACE 0 #endif #ifndef GLOB_TILDE /* Allow ~ processing -- Linux extension */ #define GLOB_TILDE 0 #endif #ifndef GLOB_NOMATCH #define GLOB_NOMATCH 0 /* Some versions don't have a special return for this */ #endif #define GLOB_FLAGS (GLOB_ERR|GLOB_NOSORT|GLOB_BRACE|GLOB_TILDE) #define HELP if (argc > 1 && (strcmp(argv[1],"-help")==0 \ || strcmp(argv[1],"--help")==0)) \ { printf("\nUsage: %s\n\n%s",USAGE,HELPTEXT); return 0;} /****************************************************************************/ static int numstrcmp(char *s1, char *s2) /* Same behaviour as strcmp(), except that when an unsigned integer is found in each string, the numerical values are compared instead of the ascii values. Overflow is impossible. Leading spaces before numbers are considered part of the numbers. A number in one string is considered less than a non-number in the other string. */ { int c1,c2; char *a1,*a2; while (1) { for (a1 = s1; *a1 == ' '; ++a1) {} if (isdigit(*a1)) { for (s1 = a1+1; isdigit(*s1); ++s1) {} } else { a1 = s1; ++s1; } for (a2 = s2; *a2 == ' '; ++a2) {} if (isdigit(*a2)) { for (s2 = a2+1; isdigit(*s2); ++s2) {} } else { a2 = s2; ++s2; } if (!isdigit(*a1)) { if (!isdigit(*a2)) { if (*a1 < *a2) return -1; if (*a1 > *a2) return 1; if (*a1 == '\0') return 0; } else return 1; } else { if (!isdigit(*a2)) return -1; else { for (; *a1 == '0'; ++a1) {} for (; *a2 == '0'; ++a2) {} if (s1-a1 < s2-a2) return -1; if (s1-a1 > s2-a2) return 1; for (; a1 < s1 && *a1 == *a2; ++a1, ++a2) {} if (a1 < s1) { if (*a1 < *a2) return -1; else return 1; } } } } } /****************************************************************************/ static void writeline(char *outf, number *val, unsigned long count) /* Write an output line with the given format and values */ { int i,n; n = 0; for (; *outf != '\0'; ++outf) { if (*outf == '%') { ++outf; if (*outf == '%' || *outf == '#') putchar(*outf); else if (*outf == 'd' || *outf == 'x' || *outf == 'p') printf(dout,val[n++].d); else if (*outf == 'f') printf(fout,val[n++].f); else if (*outf == 'v') printf(vout,val[n++].f/count); else if (*outf == 'l') { for (i = 0; i < val[n].l->nvals; ++i) { if (i > 0) printf(" "); printf(dout,val[n].l->val[i]); } ++n; } #if GMP else if (*outf == 'm') mpz_out_str(NULL,10,*(val[n++].m)); #endif else { fprintf(stderr,">E unknown output format %%%c\n",*outf); exit(1); } } else putchar(*outf); } } /*********************************************************************/ static void print_counts(countnode *root, boolean printcounts) /* Use a non-recursive inorder traversal to print the tree */ { int code; countnode *p; p = root; code = A; while (p) { switch (code) /* deliberate flow-ons */ { case A: if (p->left) { p = p->left; break; } case L: if (printcounts) printf("%5lu: ",p->count); writeline(p->fmt,p->total,p->count); if (p->right) { p = p->right; code = A; break; } case R: if (p->parent && p->parent->left == p) code = L; else code = R; p = p->parent; break; } } } /*********************************************************************/ static void print_common(countnode *root) /* Print the common ends of the formats in the tree */ { int code; countnode *p; char *s0,*s1,*t0,*t1; int i,comm0,comm1,minlen,maxlen; if (root == NULL) return; p = root; code = A; s0 = s1 = p->fmt; while (*s1 != '\0') ++s1; comm0 = comm1 = minlen = maxlen = s1-s0; while (p) { switch (code) /* deliberate flow-ons */ { case A: if (p->left) { p = p->left; break; } case L: t0 = t1 = p->fmt; for (i = 0; i < comm0; ++i) if (s0[i] != t0[i]) break; comm0 = i; while (*t1 != '\0') ++t1; for (i = 1; i <= comm1; ++i) if (s1[-i] != t1[-i]) break; comm1 = i-1; if (t1-t0 < minlen) minlen = t1-t0; if (t1-t0 > maxlen) maxlen = t1-t0; if (p->right) { p = p->right; code = A; break; } case R: if (p->parent && p->parent->left == p) code = L; else code = R; p = p->parent; break; } } if (comm0 + comm1 > minlen) comm1 = minlen - comm0; for (i = 0; i < comm0; ++i) printf("%c",s0[i]); if (comm0 + comm1 < maxlen) printf("*"); for (i = comm1; i > 0; --i) printf("%c",s1[-i]); } /*********************************************************************/ static void splay(countnode *p) /* Splay the node p. It becomes the new root. */ { countnode *q,*r,*s; countnode *a,*b,*c,*d; int code; #define LCHILD(x,y) {(x)->left = y; if (y) (y)->parent = x;} #define RCHILD(x,y) {(x)->right = y; if (y) (y)->parent = x;} while (p->parent) { a = p->left; b = p->right; q = p->parent; if (q->left == p) { code = L; c = q->right; } else { code = R; c = q->left; } r = q->parent; if (r) { if (r->left == q) code = (code == L ? LL : LR); else code = (code == L ? RL : RR); s = r->parent; p->parent = s; if (s) { if (s->left == r) s->left = p; else s->right = p; } } else { p->parent = NULL; } switch (code) { case L: RCHILD(p,q); LCHILD(q,b); break; case R: LCHILD(p,q); RCHILD(q,a); break; case LL: RCHILD(p,q); RCHILD(q,r); LCHILD(q,b); LCHILD(r,c); break; case RR: LCHILD(p,q); LCHILD(q,r); RCHILD(r,c); RCHILD(q,a); break; case LR: LCHILD(p,q); RCHILD(p,r); RCHILD(q,a); LCHILD(r,b); break; case RL: LCHILD(p,r); RCHILD(p,q); RCHILD(r,a); LCHILD(q,b); break; } } } /*********************************************************************/ static void add_one(countnode **to_root, char *fmt, integer pmod, int nval, number *val, int *valtype, int which, boolean numcompare) /* Add one match to the node with the given format, creating it if it is new. The tree is then splayed to ensure good efficiency. */ { int i,j,cmp,len; countnode *p,*ppar,*new_node; integer w; p = *to_root; cmp = 0; while (p != NULL) { cmp = (numcompare ? numstrcmp(fmt,p->fmt) : strcmp(fmt,p->fmt)); if (cmp == 0) { if (HAS(which,UNIQUE) && p->count == 1) printf("ERROR: Multiple matches for %s",fmt); for (i = 0; i < nval; ++i) if (valtype[i] == D) {INCR(p->total[i].d,val[i].d);} else if (valtype[i] == X) {if (val[i].d > p->total[i].d) p->total[i].d = val[i].d;} else if (valtype[i] == P) {w = val[i].d % pmod; INCR(p->total[i].d,w); p->total[i].d %= pmod;} else if (valtype[i] == LD) { if (p->total[i].l->nvals < val[i].l->nvals) { if ((p->total[i].l->val = (integer*)realloc(p->total[i].l->val, sizeof(integer)*val[i].l->nvals)) == NULL) { fprintf(stderr,"Malloc failed\n"); exit(1); } } for (j = 0; j < p->total[i].l->nvals && j < val[i].l->nvals; ++j) INCR(p->total[i].l->val[j],val[i].l->val[j]); if (p->total[i].l->nvals < val[i].l->nvals) { for (j = p->total[i].l->nvals; j < val[i].l->nvals; ++j) p->total[i].l->val[j] = val[i].l->val[j]; p->total[i].l->nvals = val[i].l->nvals; } } #if GMP else if (valtype[i] == M) mpz_add(*(p->total[i].m),*(p->total[i].m),*(val[i].m)); #endif else p->total[i].f += val[i].f; /* F and V */ ++p->count; splay(p); *to_root = p; return; } else if (cmp < 0) { ppar = p; p = p->left; } else { ppar = p; p = p->right; } } if ((new_node = (countnode*)malloc(sizeof(countnode))) == NULL) { fprintf(stderr,">E malloc failed in add_one()\n"); exit(1); } if ((new_node->fmt = (char*)malloc(strlen(fmt)+1)) == NULL) { fprintf(stderr,">E malloc failed in add_one()\n"); exit(1); } new_node->count = 1; strcpy(new_node->fmt,fmt); for (i = 0; i < nval; ++i) { #if GMP if (valtype[i] == M) { if ((new_node->total[i].m = (mpz_t*)malloc(sizeof(mpz_t))) == NULL) { fprintf(stderr,"Malloc failed\n"); exit(1); } mpz_init_set(*(new_node->total[i].m),*(val[i].m)); } else #endif if (valtype[i] == LD) { if ((new_node->total[i].l = (integerlist*)malloc(sizeof(integerlist))) == NULL) { fprintf(stderr,"Malloc failed\n"); exit(1); } if ((new_node->total[i].l->val = (integer*)malloc(sizeof(integer)*val[i].l->nvals)) == NULL) { fprintf(stderr,"Malloc failed\n"); exit(1); } new_node->total[i].l->nvals = val[i].l->nvals; for (j = 0; j < val[i].l->nvals; ++j) new_node->total[i].l->val[j] = val[i].l->val[j]; } else new_node->total[i] = val[i]; } new_node->left = new_node->right = NULL; if (cmp == 0) { *to_root = new_node; new_node->parent = NULL; } else if (cmp < 0) { ppar->left = new_node; new_node->parent = ppar; } else { ppar->right = new_node; new_node->parent = ppar; } splay(new_node); *to_root = new_node; } /****************************************************************************/ static int scanline(char *s, char *f, number *val, int *valtype, integer *seqno, char *outf) /* Perform sscanf-like scan of line. The whole format must match. outf is set to be an output format with unassigned values replaced by '*' and %s replaced by what it matches. Assigned values except %s are put into val[] with their types in valtype[]. The number of values (not counting %#) is returned. Integers matching %# are put into *seqno, with an error if there are more than one, and -1 if there are none. If the format doesn't match, -1 is returned. WARNING: the gmp and ilist values are pointers to static data, so they need to be copied if the values array is copied. See the comments at the start of the program for more information. */ { int n; /* Number of values assigned */ int fracdigits,digit; boolean doass,neednonsp,neg,oflow,badgmp; integer ival; double dval,digval; char ends,*saves; static boolean gmp_warning = FALSE; integer *ilist; size_t ilist_sz; int nilist; #if GMP char mp_line[MAXLINELEN+1],*mp; #endif n = 0; *seqno = -1; badgmp = oflow = FALSE; while (*f != '\0') { if (*f == '%') { ++f; if (*f == '*') { doass = FALSE; ++f; } else doass = TRUE; if (*f == '%') { if (!doass) { fprintf(stderr,"Bad format item %%*\n"); exit(1); } if (*s++ != '%') return -1; ++f; *outf++ = '%'; *outf++ = '%'; } else if (*f == '\n') { if (!doass) { fprintf(stderr,"Bad format item %*\n"); exit(1); } while (*s != '\0') { if (*s != ' ' && *s != '\n') return -1; ++s; } --s; } else if (*f == 'c') { if (*s == ' ' || *s == '\t' || *s == '\n') return -1; if (doass) *outf++ = *s; else *outf++ = '*'; ++f; ++s; } else if (*f == 's') { ends = *(f+1); if (ends == ' ') { while (*s == ' ' || *s == '\t') { if (doass) *outf++ = *s; ++s; } } while (*s != '\n' && *s != ends) { if (doass) *outf++ = *s; ++s; } if (!doass) *outf++ = '*'; ++f; } #if GMP else if (*f == 'd' || *f == 'x' || *f == 'p') { #else else if (*f == 'd' || *f == 'x' || *f == 'p' || *f == 'm') { if (*f == 'm' && !gmp_warning) { fprintf(stderr, ">W not compiled with GMP, treating %%m like %%d\n"); gmp_warning = TRUE; } #endif while (*s == ' ' || *s == '\t') ++s; if (!isdigit(*s) && *s != '-' && *s != '+') return -1; neg = (*s == '-'); if (*s == '-' || *s == '+') ++s; ival = 0; while (isdigit(*s)) { digit = *s++ - '0'; if (ival > (maxint-digit)/10) oflow = TRUE; else ival = ival*10 + digit; } if (doass) { *outf++ = '%'; if (*f == 'd' || *f == 'm') { *outf++ = 'd'; valtype[n] = D; } else if (*f == 'x') { *outf++ = 'x'; valtype[n] = X; } else { *outf++ = 'p'; valtype[n] = P; } val[n++].d = (neg ? -ival : ival); } else *outf++ = '*'; ++f; } else if (*f == 'l') { nilist = 0; if ((ilist = (integer*)malloc(200*sizeof(integer))) == NULL) { fprintf(stderr,"Malloc failed\n"); exit(1); } ilist_sz = 200; for (;;) { saves = s; while (*s == ' ' || *s == '\t') ++s; if (!isdigit(*s) && *s != '-' && *s != '+') { s = saves; break; } neg = (*s == '-'); if (*s == '-' || *s == '+') ++s; ival = 0; while (isdigit(*s)) { digit = *s++ - '0'; if (ival > (maxint-digit)/10) oflow = TRUE; else ival = ival*10 + digit; } if (neg) ival = -ival; if (nilist == ilist_sz) { if ((ilist = (integer*)realloc((void*)ilist, (ilist_sz+500)*sizeof(integer))) == NULL) { fprintf(stderr,"Malloc failed\n"); exit(1); } ilist_sz += 500; } ilist[nilist++] = ival; } if (doass) { valtype[n] = LD; val[n].l = &il[n]; val[n].l->nvals = nilist; if (val[n].l->val) free(val[n].l->val); val[n].l->val = ilist; ++n; *outf++ = '%'; *outf++ = 'l'; } else { free(ilist); *outf++ = '*'; } ++f; } #if GMP else if (*f == 'm') { while (*s == ' ' || *s == '\t') ++s; if (!isdigit(*s) && *s != '-' && *s != '+') return -1; mp = mp_line; if (*s == '-') *mp++ = *s++; else if (*s == '+') s++; while (isdigit(*s)) *mp++ = *s++; *mp = '\0'; if (doass) { valtype[n] = M; val[n].m = &mp_value[n]; if (mpz_set_str(mp_value[n],mp_line,10) < 0) badgmp = TRUE; ++n; *outf++ = '%'; *outf++ = 'm'; } else *outf++ = '*'; ++f; } #endif else if (*f == '#') { while (*s == ' ' || *s == '\t') ++s; if (!isdigit(*s)) return -1; ival = 0; while (isdigit(*s)) { digit = *s++ - '0'; if (ival > (maxint-digit)/10) oflow = TRUE; else ival = ival*10 + digit; } if (*seqno >= 0) { fprintf(stderr, ">E %# can only be used once per format\n"); exit(1); } *seqno = ival; *outf++ = '#'; ++f; } else if (*f == 'f' || *f == 'v') { while (*s == ' ' || *s == '\t') ++s; if (!isdigit(*s) && *s != '.' && *s != '-' && *s != '+') return -1; neg = (*s == '-'); if (*s == '-' || *s == '+') ++s; dval = 0.0; while (isdigit(*s)) dval = dval*10.0 + (*s++ - '0'); if (*s == '.') { digval = 1.0; ++s; while (isdigit(*s)) { digval /= 10.0; dval += (*s++ - '0') * digval; } } if (doass) { valtype[n] = (*f == 'f' ? F : V); val[n++].f = (neg ? -dval : dval); *outf++ = '%'; *outf++ = *f; } else *outf++ = '*'; ++f; } else if (*f == ' ') { while (*s == ' ' || *s == '\t') ++s; *outf++ = ' '; ++f; } else { fprintf(stderr,"Bad format item %%%c\n",*f); exit(1); } } else { if (*s != *f) return -1; *outf++ = *f; ++s; ++f; } } if (*s != '\0') return -1; *outf = '\0'; if (oflow) { fprintf(stderr,"Integer too large\n"); exit(1); } if (badgmp) { fprintf(stderr,"Illegal multiprecision integer\n"); exit(1); } return n; } /****************************************************************************/ #if 0 find_maxint(void) { /* Put the maximum possible integer value into maxint. */ /* Old version. */ integer x; x = 1; while (x > 0) x <<= 1; x -= 1; if (x <= 0) { fprintf(stderr,">E find_maxint() failed\n"); exit(1); } maxint = x; } #else find_maxint(void) { /* Put the maximum possible integer value into maxint. */ /* New version with no integer overflow. */ integer x,y; x = ((integer)1) << (8*sizeof(integer) - 2); y = x - 1; x += y; if (x <= 0) { fprintf(stderr,">E find_maxint() failed\n"); exit(1); } maxint = x; } #endif /****************************************************************************/ static void sort_formats(int *order, int numformats) /* Make order[0..numformats-1] a permutation of 0..numformats-1 being a good order to display the results. */ { double score[MAXFORMATS]; int h,i,j,iw; for (i = 0; i < numformats; ++i) { if (matching_lines[i] == 0) score[i] = -1.0; else score[i] = i + ((10.0*total_position[i]) / matching_lines[i]) * numformats; order[i] = i; } j = numformats / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < numformats; ++i) { iw = order[i]; for (j = i; score[order[j-h]] > score[iw]; ) { order[j] = order[j-h]; if ((j -= h) < h) break; } order[j] = iw; } h /= 3; } while (h > 0); } /****************************************************************************/ static void read_formats(char *filename, int *numformatsp, boolean mustexist) /* Read formats from the given file. */ { FILE *f; int i,c,flags; char flagname[52]; char line[MAXLINELEN+3]; integer pmod; char *s; boolean oflow,badpmod; int digit; if (strcmp(filename,"-") == 0) f = stdin; else if ((f = fopen(filename,"r")) == NULL) { if (mustexist) { fprintf(stderr,">E Can't open %s for reading.\n",filename); exit(1); } return; } line[MAXLINELEN+2] = '\0'; for (;;) { if ((c = getc(f)) == EOF) break; while (c == ' ' || c == '\t') c = getc(f); if (c == '\n') continue; if (c == EOF) break; if (c == '#') { while (c != '\n' && c != EOF) c = getc(f); continue; } ungetc(c,f); flags = 0; pmod = 2; for (;;) { while ((c = getc(f)) == ' ' || c == '|' || c == ',' || c == '\t') {} if (c == '#') while (c != '\n' && c != EOF) c = getc(f); if (c == '\n' || c == EOF) break; ungetc(c,f); /* There appear to be some issues with the [ flag in fscanf, * as to whether a null is appended. We'll take no chances. */ for (i = 0; i < 52; ++i) flagname[i] = '\0'; fscanf(f,"%50[A-Za-z0-9=]",flagname); if (strcmp(flagname,"DEFAULT") == 0) {} else if (strcmp(flagname,"FINAL") == 0) flags |= FINAL; else if (strcmp(flagname,"ERROR") == 0) flags |= ERROR; else if (strcmp(flagname,"UNIQUE") == 0) flags |= UNIQUE; else if (strcmp(flagname,"COUNT") == 0) flags |= COUNT; else if (strcmp(flagname,"CONTINUE") == 0) flags |= CONTINUE; else if (strcmp(flagname,"NUMERIC") == 0) flags |= NUMERIC; else if (strcmp(flagname,"SILENT") == 0) flags |= SILENT; else if (strcmp(flagname,"ENDFILE") == 0) flags |= ENDFILE; else if (flagname[0] == 'P' && flagname[1] == '=') { pmod = 0; oflow = FALSE; badpmod = (flagname[2] == '\0'); for (s = flagname+2; *s != '\0'; ++s) { if (isdigit(*s)) { digit = *s - '0'; if (pmod > (maxint-digit)/10) oflow = TRUE; else pmod = pmod*10 + digit; } else badpmod = TRUE; } if (badpmod) { fprintf(stderr,">E Bad value for P= directive: %s\n", flagname+2); exit(1); } else if (oflow) { fprintf(stderr,">E Value for P= is too large\n"); exit(1); } } else { fprintf(stderr,">E Unknown flag \"%s\" in %s\n", flagname,filename); exit(1); } } if (fgets(line,MAXLINELEN,f) == NULL) { fprintf(stderr,">E Missing format in %s\n",filename); exit(1); } for (i = 0; i < *numformatsp; ++i) if (strcmp(line,format[i].fmt) == 0) break; if (i < *numformatsp) continue; if (*numformatsp == MAXFORMATS) { fprintf(stderr,">E Increase MAXFORMATS\n"); exit(1); } format[*numformatsp].flags = flags; format[*numformatsp].pmod = pmod; if ((format[*numformatsp].fmt = (char*)malloc(strlen(line)+1)) == NULL) { fprintf(stderr,">E malloc() failed in read_formats()\n"); exit(1); } strcpy(format[*numformatsp].fmt,line); ++*numformatsp; } if (f != stdin) fclose(f); } /****************************************************************************/ static void read_local_formats(int *numformatsp) /* Read formats from sumlines.fmt in current directory */ { read_formats("sumlines.fmt",numformatsp,FALSE); } /****************************************************************************/ static void read_global_formats(int *numformatsp) /* Read formats from sumlines.fmt in home directory */ { struct passwd *pwd; char filename[257+12]; if ((pwd = getpwuid(getuid())) < 0) { fprintf(stderr,">E Can't find home directory\n"); exit(1); } sprintf(filename,"%s/sumlines.fmt",pwd->pw_dir); read_formats(filename,numformatsp,FALSE); } /****************************************************************************/ static void read_env_formats(int *numformatsp) /* Read formats from $SUMLINES.FMT if it exists */ { char *filename; if ((filename = getenv("SUMLINES.FMT")) != 0) read_formats(filename,numformatsp,FALSE); } /****************************************************************************/ static boolean readline(FILE *f, char *line, int size, int *nulls) /* Get a line. Read at most size-1 chars until EOF or \n. If \n is read, it is stored. Then \0 is appended. *nulls is set to the number of NUL chars (which are also stored). */ { int i,c; *nulls = 0; for (i = 0; i < size-1; ++i) { c = getc(f); if (c == EOF) break; line[i] = c; if (c == '\0') ++*nulls; if (c == '\n') {++i; break;} } line[i] = '\0'; return i > 0; } /****************************************************************************/ static int pnumstrcmp(const void *a, const void *b) /* numstrcmp on strings pointed at by a and b */ { return numstrcmp(*(char**)a,*(char**)b); } /****************************************************************************/ static void doglob(char *patt, glob_t *globlk) /* Find all files matching the given pattern, numeric sorting. Give a warning message if there are none. */ { int ret; ret = glob(patt,GLOB_FLAGS,NULL,globlk); if (ret != 0) globlk->gl_pathc = 0; if (ret == GLOB_NOSPACE) { fprintf(stderr,"ERROR: ran out of space during glob()\n"); exit(1); } if (ret == GLOB_ERR) { fprintf(stderr,"ERROR: during glob(%s)\n",patt); exit(1); } if (ret != 0 && ret != GLOB_NOMATCH) { fprintf(stderr,"ERROR: value %d from glob(%s)\n",ret,patt); exit(1); } if (globlk->gl_pathc == 0) printf("WARNING: no files match %s\n",patt); if (globlk->gl_pathc >= 2) qsort(globlk->gl_pathv,globlk->gl_pathc,sizeof(char*),pnumstrcmp); } /****************************************************************************/ main(int argc, char *argv[]) { int i,j,nvals,argnum; number val[MAXVALUES]; int valtype[MAXVALUES]; char line[MAXLINELEN+2]; char outf[MAXLINELEN+MAXVALUES+6]; unsigned long matched,unmatched,finalmatched; unsigned long errorlines,totalerrorlines; unsigned long line_number,nullcount,numfiles,ifile; char *filename; FILE *infile; int numformats,firstarg,nulls; boolean havefinal,nowarn,listformats,readfiles; integer seq; int order[MAXFORMATS]; glob_t globlk,globlk_stdin,*pglob; char *glob_stdin_v[2]; boolean printcounts; HELP; find_maxint(); firstarg = 1; numformats = 0; nowarn = FALSE; listformats = FALSE; readfiles = TRUE; printcounts = TRUE; globlk_stdin.gl_pathc = 1; globlk_stdin.gl_pathv = glob_stdin_v; glob_stdin_v[0] = "-"; glob_stdin_v[1] = NULL; dout = DOUT; fout = FOUT; vout = VOUT; for (; firstarg < argc; ++firstarg) { if (argv[firstarg][0] == '-' && argv[firstarg][1] == 'f') { if (argv[firstarg][2] != '\0') read_formats(&argv[firstarg][2],&numformats,TRUE); else if (firstarg == argc - 1) { fprintf(stderr,">E No argument for -f\n"); exit(1); } else { ++firstarg; read_formats(argv[firstarg],&numformats,TRUE); } } else if (strcmp(argv[firstarg],"-w") == 0) nowarn = TRUE; else if (strcmp(argv[firstarg],"-v") == 0) listformats = TRUE; else if (strcmp(argv[firstarg],"-d") == 0) readfiles = FALSE; else if (strcmp(argv[firstarg],"-n") == 0) printcounts = FALSE; else if (strcmp(argv[firstarg],"-V") == 0) vout = argv[++firstarg]; else if (strcmp(argv[firstarg],"-F") == 0) fout = argv[++firstarg]; else if (strcmp(argv[firstarg],"-D") == 0) dout = argv[++firstarg]; else break; } #if GMP for (i = 0; i < MAXVALUES; ++i) mpz_init(mp_value[i]); #endif for (i = 0; i < MAXVALUES; ++i) { il[i].nvals = 0; il[i].val = NULL; } if (readfiles) read_local_formats(&numformats); if (readfiles) read_env_formats(&numformats); if (readfiles) read_global_formats(&numformats); if (listformats) { printf("%d formats:\n",numformats); for (i = 0; i < numformats; ++i) printf("%03x %s",format[i].flags,format[i].fmt); } if (numformats == 0) { fprintf(stderr,">E No formats\n"); exit(1); } havefinal = FALSE; for (i = 0; i < numformats; ++i) { count_root[i] = NULL; matching_lines[i] = 0; total_position[i] = 0; if (HAS(i,FINAL)) havefinal = TRUE; } unmatched = totalerrorlines = 0; numfiles = 0; for (argnum = firstarg; argnum < (argc == firstarg ? argc+1 : argc); ++argnum) { if (argnum >= argc || strcmp(argv[argnum],"-") == 0) pglob = &globlk_stdin; else { pglob = &globlk; doglob(argv[argnum],pglob); } for (ifile = 0; ifile < pglob->gl_pathc; ++ifile) { matched = finalmatched = errorlines = 0; ++numfiles; if (strcmp(pglob->gl_pathv[ifile],"-") == 0) { filename = "stdin"; infile = stdin; } else { filename = pglob->gl_pathv[ifile]; if ((infile = fopen(filename,"r")) == NULL) { fprintf(stderr,">E Can't open %s\n",filename); exit(1); } } line_number = 0; nullcount = 0; while (readline(infile,line,MAXLINELEN,&nulls)) { nullcount += nulls; line[MAXLINELEN] = '\n'; line[MAXLINELEN+1] = '\0'; if (line[0] == '\n') continue; ++line_number; for (i = 0; i < numformats; ++i) { nvals = scanline(line,format[i].fmt,val,valtype,&seq,outf); if (nvals >= 0) { if (HAS(i,ENDFILE)) line_number = 0; ++matched; if (HAS(i,FINAL)) ++finalmatched; if (HAS(i,ERROR)) ++errorlines; ++matching_lines[i]; total_position[i] += line_number; add_one(&count_root[i],outf,format[i].pmod,nvals, val,valtype,i,HAS(i,NUMERIC)); if (matching_lines[i] > 1 && seq >= 0 && seq != lastseq[i]+1) { printf("WARNING: Sequence number"); if (seq == lastseq[i]) { printf(" "); printf(dout,seq); printf(" is repeated.\n"); } else if (seq != lastseq[i]+2) { printf("s "); printf(dout,lastseq[i]+1); printf("-"); printf(dout,seq-1); printf(" are missing.\n"); } else { printf(" "); printf(dout,seq-1); printf(" is missing.\n"); } } lastseq[i] = seq; if (!HAS(i,CONTINUE)) break; } } if (i == numformats) ++unmatched; } if (errorlines != 0) printf("ERRORS: Error lines in file %s\n",filename); else if (matched == 0 && !nowarn) printf("WARNING: No matching lines in file %s\n",filename); else if (finalmatched == 0 && havefinal && !nowarn) printf("WARNING: No final lines in file %s\n",filename); if (nullcount > 0) printf("WARNING: %ld NULs found in file %s\n", nullcount,filename); if (infile != stdin) fclose(infile); totalerrorlines += errorlines; } if (pglob == &globlk) globfree(pglob); } sort_formats(order,numformats); for (j = 0; j < numformats; ++j) { i = order[j]; if (HAS(i,SILENT)) continue; if (HAS(i,COUNT)) { if (matching_lines[i] > 0) printf("%5lu lines matched ",matching_lines[i]); print_common(count_root[i]); } else print_counts(count_root[i],printcounts); } if (unmatched > 0) printf("%5lu non-empty lines not matched\n",unmatched); if (argc > firstarg) printf("%5lu files read altogether\n",numfiles); if (totalerrorlines > 0) printf("%5lu errors found\n",totalerrorlines); exit(0); } nauty24r2/complg.c0000600000604200001440000001013011274163463012727 0ustar bdmusers/* complg.c version 1.0; B D McKay, Jan 1997. */ #define USAGE "complg [-lrq] [infile [outfile]]" #define HELPTEXT \ " Take the complements of a file of graphs.\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -r Only complement if the complement has fewer edges.\n\ -l Canonically label outputs.\n\ -q Suppress auxiliary information.\n" /*************************************************************************/ #include "gtools.h" /**************************************************************************/ void compl(graph *g, int m, int n, graph *h) /* h := complement of g */ { int i,j; setword *gi,*hi; #if MAXN set all[MAXM]; #else DYNALLSTAT(set,all,all_sz); DYNALLOC1(set,all,all_sz,m,"complg"); #endif EMPTYSET(all,m); for (i = 0; i < n; ++i) ADDELEMENT(all,i); gi = (setword*) g; hi = (setword*) h; for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) hi[j] = gi[j] ^ all[j]; DELELEMENT(hi,i); gi += m; hi += m; } } /**************************************************************************/ int main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile,*outfile; boolean dolabel,badargs,restricted,quiet; int j,m,n,argnum; int codetype,outcode; graph *g; long nin,ned,ii; char *arg,sw; static graph *gq; double t; #if MAXN graph gc[MAXN*MAXM],h[MAXN*MAXM]; #else DYNALLSTAT(graph,gc,gc_sz); DYNALLSTAT(graph,h,h_sz); #endif HELP; infilename = outfilename = NULL; dolabel = badargs = FALSE; restricted = quiet = FALSE; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('r',restricted) else SWBOOLEAN('l',dolabel) else SWBOOLEAN('q',quiet) else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!quiet) { fprintf(stderr,">A complg"); if (restricted || dolabel) fprintf(stderr," -"); if (restricted) fprintf(stderr,"r"); if (dolabel) fprintf(stderr,"l"); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (codetype&HAS_HEADER) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } if (dolabel) nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); nin = 0; t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; #if !MAXN DYNALLOC2(graph,gc,gc_sz,n,m,"complg"); #endif if (restricted) { ned = 0; for (ii = (long)n*m; --ii >= 0; ) ned += POPCOUNT(g[ii]); if (ned+ned > (long)n*(n-1)) { compl(g,m,n,gc); gq = gc; } else gq = g; } else { compl(g,m,n,gc); gq = gc; } if (dolabel) { #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"complg"); #endif fcanonise(gq,m,n,h,NULL,FALSE); gq = h; } if (outcode == SPARSE6) writes6(outfile,gq,m,n); else writeg6(outfile,gq,m,n); FREES(g); } t = CPUTIME - t; if (!quiet) fprintf(stderr, ">Z %ld graphs converted from %s to %s in %3.2f sec.\n", nin,infilename,outfilename,t); exit(0); } nauty24r2/nauty.c0000600000604200001440000013537011405400302012602 0ustar bdmusers/***************************************************************************** * * * Main source file for version 2.4 of nauty. * * * * Copyright (1984-2010) Brendan McKay. All rights reserved. Permission * * Subject to the waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 10-Nov-87 : final changes for version 1.2 * * 5-Dec-87 : renamed to version 1.3 (no changes to this file) * * 28-Sep-88 : renamed to version 1.4 (no changes to this file) * * 23-Mar-89 : changes for version 1.5 : * * - add use of refine1 instead of refine for m==1 * * - changes for new optionblk syntax * * - disable tc_level use for digraphs * * - interposed doref() interface to refine() so that * * options.invarproc can be supported * * - declared local routines static * * 28-Mar-89 : - implemented mininvarlevel/maxinvarlevel < 0 options * * 2-Apr-89 : - added invarproc fields in stats * * 5-Apr-89 : - modified error returns from nauty() * * - added error message to ERRFILE * * - changed MAKEEMPTY uses to EMPTYSET * * 18-Apr-89 : - added MTOOBIG and CANONGNIL * * 8-May-89 : - changed firstcode[] and canoncode[] to short * * 10-Nov-90 : changes for version 1.6 : * * - added dummy routine nauty_null (see dreadnaut.c) * * 2-Sep-91 : changes for version 1.7 : * * - moved MULTIPLY into nauty.h * * 27-Mar-92 : - changed 'n' into 'm' in error message in nauty() * * 5-Jun-93 : renamed to version 1.7+ (no changes to this file) * * 18-Aug-93 : renamed to version 1.8 (no changes to this file) * * 17-Sep-93 : renamed to version 1.9 (no changes to this file) * * 13-Jul-96 : changes for version 2.0 : * * - added dynamic allocation * * 21-Oct-98 : - made short into shortish for BIGNAUTY as needed * * 7-Jan-00 : - allowed n=0 * * - added nauty_check() and a call to it * * 12-Feb-00 : - used better method for target cell memory allocation * * - did a little formating of the code * * 27-May-00 : - fixed error introduced on Feb 12. * * - dynamic allocations in nauty() are now deallocated * * before return if n >= 320. * * 16-Nov-00 : - use function prototypes, change UPROC to void. * * - added argument to tcellproc(), removed nvector * * - now use options.dispatch, options.groupopts is gone. * * 22-Apr-01 : - Added code for compilation into Magma * * - Removed nauty_null() and EXTDEFS * * 2-Oct-01 : - Improved error message for bad dispatch vector * * 21-Nov-01 : - use NAUTYREQUIRED in nauty_check() * * 20-Dec-02 : changes for version 2.2: * * - made tcnode0 global * * - added nauty_freedyn() * * 17-Nov-03 : changed INFINITY to NAUTY_INFINITY * * 14-Sep-04 : extended prototypes even to recursive functions * * 16-Oct-04 : disallow NULL dispatch vector * * 11-Nov-05 : changes for version 2.3: * * - init() and cleanup() optional calls * * 23-Nov-06 : changes for version 2.4: * * - use maketargetcell() instead of tcellproc() * * 29-Nov-06 : add extra_autom, extra_level, extra_options * * 10-Dec-06 : remove BIGNAUTY * * * *****************************************************************************/ #define ONE_WORD_SETS #include "nauty.h" #ifdef NAUTY_IN_MAGMA #include "cleanup.e" #define NAUTY_ABORT (-11) #endif typedef struct tcnode_struct { struct tcnode_struct *next; set *tcellptr; } tcnode; /* aproto: header new_nauty_protos.h */ #ifndef NAUTY_IN_MAGMA #if !MAXN static int firstpathnode0(int*, int*, int, int, tcnode*); static int othernode0(int*, int*, int, int, tcnode*); #else static int firstpathnode(int*, int*, int, int); static int othernode(int*, int*, int, int); #endif static void firstterminal(int*, int); static int processnode(int*, int*, int, int); static void recover(int*, int); static void writemarker(int, int, int, int, int, int); #endif #if MAXM==1 #define M 1 #else #define M m #endif #define OPTCALL(proc) if (proc != NULL) (*proc) /* copies of some of the options: */ static boolean getcanon,digraph,writeautoms,domarkers,cartesian; static int linelength,tc_level,mininvarlevel,maxinvarlevel,invararg; static void (*usernodeproc)(graph*,int*,int*,int,int,int,int,int,int); static void (*userautomproc)(int,permutation*,int*,int,int,int); static void (*userlevelproc) (int*,int*,int,int*,statsblk*,int,int,int,int,int,int); static void (*invarproc) (graph*,int*,int*,int,int,int,permutation*,int,boolean,int,int); static FILE *outfile; static dispatchvec dispatch; /* local versions of some of the arguments: */ static int m,n; static graph *g,*canong; static int *orbits; static statsblk *stats; /* temporary versions of some stats: */ static unsigned long invapplics,invsuccesses; static int invarsuclevel; /* working variables: */ static int gca_first, /* level of greatest common ancestor of current node and first leaf */ gca_canon, /* ditto for current node and bsf leaf */ noncheaplevel, /* level of greatest ancestor for which cheapautom == FALSE */ allsamelevel, /* level of least ancestor of first leaf for which all descendant leaves are known to be equivalent */ eqlev_first, /* level to which codes for this node match those for first leaf */ eqlev_canon, /* level to which codes for this node match those for the bsf leaf. */ comp_canon, /* -1,0,1 according as code at eqlev_canon+1 is <,==,> that for bsf leaf. Also used for similar purpose during leaf processing */ samerows, /* number of rows of canong which are correct for the bsf leaf BDM:correct description? */ canonlevel, /* level of bsf leaf */ stabvertex, /* point fixed in ancestor of first leaf at level gca_canon */ cosetindex; /* the point being fixed at level gca_first */ static boolean needshortprune; /* used to flag calls to shortprune */ #if !MAXN DYNALLSTAT(set,defltwork,defltwork_sz); DYNALLSTAT(permutation,workperm,workperm_sz); DYNALLSTAT(set,fixedpts,fixedpts_sz); DYNALLSTAT(permutation,firstlab,firstlab_sz); DYNALLSTAT(permutation,canonlab,canonlab_sz); DYNALLSTAT(short,firstcode,firstcode_sz); DYNALLSTAT(short,canoncode,canoncode_sz); DYNALLSTAT(shortish,firsttc,firsttc_sz); DYNALLSTAT(set,active,active_sz); /* In the dynamically allocated case (MAXN=0), each level of recursion needs one set (tcell) to represent the target cell. This is implemented by using a linked list of tcnode anchored at the root of the search tree. Each node points to its child (if any) and to the dynamically allocated tcell. Apart from the the first node of the list, each node always has a tcell good for m up to alloc_m. tcnodes and tcells are kept between calls to nauty, except that they are freed and reallocated if m gets bigger than alloc_m. */ static tcnode tcnode0 = {NULL,NULL}; static int alloc_m = 0; #else static set defltwork[2*MAXM]; /* workspace in case none provided */ static permutation workperm[MAXN]; /* various scratch uses */ static set fixedpts[MAXM]; /* points which were explicitly fixed to get current node */ static permutation firstlab[MAXN], /* label from first leaf */ canonlab[MAXN]; /* label from bsf leaf */ static short firstcode[MAXN+2], /* codes for first leaf */ canoncode[MAXN+2]; /* codes for bsf leaf */ static shortish firsttc[MAXN+2]; /* index of target cell for left path */ static set active[MAXM]; /* used to contain index to cells now active for refinement purposes */ #endif static set *workspace,*worktop; /* first and just-after-last addresses of work area to hold automorphism data */ static set *fmptr; /* pointer into workspace */ /***************************************************************************** * * * This procedure finds generators for the automorphism group of a * * vertex-coloured graph and optionally finds a canonically labelled * * isomorph. A description of the data structures can be found in * * nauty.h and in the "nauty User's Guide". The Guide also gives * * many more details about its use, and implementation notes. * * * * Parameters - means read-only, means write-only, means both: * * g - the graph * * lab,ptn - used for the partition nest which defines the colouring * * of g. The initial colouring will be set by the program, * * using the same colour for every vertex, if * * options->defaultptn!=FALSE. Otherwise, you must set it * * yourself (see the Guide). If options->getcanon!=FALSE, * * the contents of lab on return give the labelling of g * * corresponding to canong. This does not change the * * initial colouring of g as defined by (lab,ptn), since * * the labelling is consistent with the colouring. * * active - If this is not NULL and options->defaultptn==FALSE, * * it is a set indicating the initial set of active colours. * * See the Guide for details. * * orbits - On return, orbits[i] contains the number of the * * least-numbered vertex in the same orbit as i, for * * i=0,1,...,n-1. * * options - A list of options. See nauty.h and/or the Guide * * for details. * * stats - A list of statistics produced by the procedure. See * * nauty.h and/or the Guide for details. * * workspace - A chunk of memory for working storage. * * worksize - The number of setwords in workspace. See the Guide * * for guidance. * * m - The number of setwords in sets. This must be at * * least ceil(n / WORDSIZE) and at most MAXM. * * n - The number of vertices. This must be at least 1 and * * at most MAXN. * * canong - The canononically labelled isomorph of g. This is * * only produced if options->getcanon!=FALSE, and can be * * given as NULL otherwise. * * * * FUNCTIONS CALLED: firstpathnode(),updatecan() * * * *****************************************************************************/ void nauty(graph *g_arg, int *lab, int *ptn, set *active_arg, int *orbits_arg, optionblk *options, statsblk *stats_arg, set *ws_arg, int worksize, int m_arg, int n_arg, graph *canong_arg) { int i; int numcells; int retval; int initstatus; #if !MAXN tcnode *tcp,*tcq; #endif /* determine dispatch vector */ if (options->dispatch == NULL) { fprintf(ERRFILE,">E nauty: null dispatch vector\n"); fprintf(ERRFILE,"Maybe you need to recompile\n"); exit(1); } else dispatch = *(options->dispatch); if (options->userrefproc) dispatch.refine = options->userrefproc; else if (dispatch.refine1 && m_arg == 1) dispatch.refine = dispatch.refine1; if (dispatch.refine == NULL || dispatch.updatecan == NULL || dispatch.targetcell == NULL || dispatch.cheapautom == NULL) { fprintf(ERRFILE,">E bad dispatch vector\n"); exit(1); } /* check for excessive sizes: */ #if !MAXN if (m_arg > NAUTY_INFINITY/WORDSIZE+1) { stats_arg->errstatus = MTOOBIG; fprintf(ERRFILE,"nauty: need m <= %d, but m=%d\n\n", NAUTY_INFINITY/WORDSIZE+1,m_arg); return; } if (n_arg > NAUTY_INFINITY-2 || n_arg > WORDSIZE * m_arg) { stats_arg->errstatus = NTOOBIG; fprintf(ERRFILE,"nauty: need n <= min(%d,%d*m), but n=%d\n\n", NAUTY_INFINITY-2,WORDSIZE,n_arg); return; } #else if (m_arg > MAXM) { stats_arg->errstatus = MTOOBIG; fprintf(ERRFILE,"nauty: need m <= %d\n\n",MAXM); return; } if (n_arg > MAXN || n_arg > WORDSIZE * m_arg) { stats_arg->errstatus = NTOOBIG; fprintf(ERRFILE, "nauty: need n <= min(%d,%d*m)\n\n",MAXM,WORDSIZE); return; } #endif if (n_arg == 0) /* Special code for zero-sized graph */ { stats_arg->grpsize1 = 1.0; stats_arg->grpsize2 = 0; stats_arg->numorbits = 0; stats_arg->numgenerators = 0; stats_arg->errstatus = 0; stats_arg->numnodes = 1; stats_arg->numbadleaves = 0; stats_arg->maxlevel = 1; stats_arg->tctotal = 0; stats_arg->canupdates = (options->getcanon != 0); stats_arg->invapplics = 0; stats_arg->invsuccesses = 0; stats_arg->invarsuclevel = 0; return; } /* take copies of some args, and options: */ m = m_arg; n = n_arg; nautil_check(WORDSIZE,m,n,NAUTYVERSIONID); OPTCALL(dispatch.check)(WORDSIZE,m,n,NAUTYVERSIONID); #if !MAXN DYNALLOC1(set,defltwork,defltwork_sz,2*m,"nauty"); DYNALLOC1(set,fixedpts,fixedpts_sz,m,"nauty"); DYNALLOC1(set,active,active_sz,m,"nauty"); DYNALLOC1(permutation,workperm,workperm_sz,n,"nauty"); DYNALLOC1(permutation,firstlab,firstlab_sz,n,"nauty"); DYNALLOC1(permutation,canonlab,canonlab_sz,n,"nauty"); DYNALLOC1(short,firstcode,firstcode_sz,n+2,"nauty"); DYNALLOC1(short,canoncode,canoncode_sz,n+2,"nauty"); DYNALLOC1(shortish,firsttc,firsttc_sz,n+2,"nauty"); if (m > alloc_m) { tcp = tcnode0.next; while (tcp != NULL) { tcq = tcp->next; FREES(tcp->tcellptr); FREES(tcp); tcp = tcq; } alloc_m = m; tcnode0.next = NULL; } #endif /* OLD g = g_arg; */ orbits = orbits_arg; stats = stats_arg; getcanon = options->getcanon; digraph = options->digraph; writeautoms = options->writeautoms; domarkers = options->writemarkers; cartesian = options->cartesian; linelength = options->linelength; if (digraph) tc_level = 0; else tc_level = options->tc_level; outfile = (options->outfile == NULL ? stdout : options->outfile); usernodeproc = options->usernodeproc; userautomproc = options->userautomproc; userlevelproc = options->userlevelproc; invarproc = options->invarproc; if (options->mininvarlevel < 0 && options->getcanon) mininvarlevel = -options->mininvarlevel; else mininvarlevel = options->mininvarlevel; if (options->maxinvarlevel < 0 && options->getcanon) maxinvarlevel = -options->maxinvarlevel; else maxinvarlevel = options->maxinvarlevel; invararg = options->invararg; if (getcanon) if (canong_arg == NULL) { stats_arg->errstatus = CANONGNIL; fprintf(ERRFILE, "nauty: canong=NULL but options.getcanon=TRUE\n\n"); return; } /* initialize everything: */ if (options->defaultptn) { for (i = 0; i < n; ++i) /* give all verts same colour */ { lab[i] = i; ptn[i] = NAUTY_INFINITY; } ptn[n-1] = 0; EMPTYSET(active,m); ADDELEMENT(active,0); numcells = 1; } else { ptn[n-1] = 0; numcells = 0; for (i = 0; i < n; ++i) if (ptn[i] != 0) ptn[i] = NAUTY_INFINITY; else ++numcells; if (active_arg == NULL) { EMPTYSET(active,m); for (i = 0; i < n; ++i) { ADDELEMENT(active,i); while (ptn[i]) ++i; } } else for (i = 0; i < M; ++i) active[i] = active_arg[i]; } g = canong = NULL; initstatus = 0; OPTCALL(dispatch.init)(g_arg,&g,canong_arg,&canong, lab,ptn,active,options,&initstatus,m,n); if (initstatus) { stats->errstatus = initstatus; return; } if (g == NULL) g = g_arg; if (canong == NULL) canong = canong_arg; for (i = 0; i < n; ++i) orbits[i] = i; stats->grpsize1 = 1.0; stats->grpsize2 = 0; stats->numgenerators = 0; stats->numnodes = 0; stats->numbadleaves = 0; stats->tctotal = 0; stats->canupdates = 0; stats->numorbits = n; EMPTYSET(fixedpts,m); noncheaplevel = 1; eqlev_canon = -1; /* needed even if !getcanon */ if (worksize >= 2 * m) workspace = ws_arg; else { workspace = defltwork; worksize = 2 * m; } worktop = workspace + (worksize - worksize % (2 * m)); fmptr = workspace; /* here goes: */ stats->errstatus = 0; needshortprune = FALSE; invarsuclevel = NAUTY_INFINITY; invapplics = invsuccesses = 0; #if !MAXN retval = firstpathnode0(lab,ptn,1,numcells,&tcnode0); #else retval = firstpathnode(lab,ptn,1,numcells); #endif #ifdef NAUTY_IN_MAGMA if (retval != NAUTY_ABORT) #endif { if (getcanon) { (*dispatch.updatecan)(g,canong,canonlab,samerows,M,n); for (i = 0; i < n; ++i) lab[i] = canonlab[i]; } stats->invarsuclevel = (invarsuclevel == NAUTY_INFINITY ? 0 : invarsuclevel); stats->invapplics = invapplics; stats->invsuccesses = invsuccesses; } #if !MAXN #ifndef NAUTY_IN_MAGMA if (n >= 320) #endif { nautil_freedyn(); OPTCALL(dispatch.freedyn)(); nauty_freedyn(); } #endif OPTCALL(dispatch.cleanup)(g_arg,&g,canong_arg,&canong, lab,ptn,options,stats,m,n); } /***************************************************************************** * * * firstpathnode(lab,ptn,level,numcells) produces a node on the leftmost * * path down the tree. The parameters describe the level and the current * * colour partition. The set of active cells is taken from the global set * * 'active'. If the refined partition is not discrete, the leftmost child * * is produced by calling firstpathnode, and the other children by calling * * othernode. * * For MAXN=0 there is an extra parameter: the address of the parent tcell * * structure. * * The value returned is the level to return to. * * * * FUNCTIONS CALLED: (*usernodeproc)(),doref(),cheapautom(), * * firstterminal(),nextelement(),breakout(), * * firstpathnode(),othernode(),recover(),writestats(), * * (*userlevelproc)(),(*tcellproc)(),shortprune() * * * *****************************************************************************/ static int #if !MAXN firstpathnode0(int *lab, int *ptn, int level, int numcells, tcnode *tcnode_parent) #else firstpathnode(int *lab, int *ptn, int level, int numcells) #endif { int tv; int tv1,index,rtnlevel,tcellsize,tc,childcount,qinvar,refcode; #if !MAXN set *tcell; tcnode *tcnode_this; tcnode_this = tcnode_parent->next; if (tcnode_this == NULL) { if ((tcnode_this = (tcnode*)ALLOCS(1,sizeof(tcnode))) == NULL || (tcnode_this->tcellptr = (set*)ALLOCS(alloc_m,sizeof(set))) == NULL) alloc_error("tcell"); tcnode_parent->next = tcnode_this; tcnode_this->next = NULL; } tcell = tcnode_this->tcellptr; #else set tcell[MAXM]; #endif ++stats->numnodes; /* refine partition : */ doref(g,lab,ptn,level,&numcells,&qinvar,workperm, active,&refcode,dispatch.refine,invarproc, mininvarlevel,maxinvarlevel,invararg,digraph,M,n); firstcode[level] = (short)refcode; if (qinvar > 0) { ++invapplics; if (qinvar == 2) { ++invsuccesses; if (mininvarlevel < 0) mininvarlevel = level; if (maxinvarlevel < 0) maxinvarlevel = level; if (level < invarsuclevel) invarsuclevel = level; } } tc = -1; if (numcells != n) { /* locate new target cell, setting tc to its position in lab, tcell to its contents, and tcellsize to its size: */ maketargetcell(g,lab,ptn,level,tcell,&tcellsize, &tc,tc_level,digraph,-1,dispatch.targetcell,M,n); stats->tctotal += tcellsize; } firsttc[level] = tc; /* optionally call user-defined node examination procedure: */ OPTCALL(usernodeproc) (g,lab,ptn,level,numcells,tc,(int)firstcode[level],M,n); if (numcells == n) /* found first leaf? */ { firstterminal(lab,level); OPTCALL(userlevelproc)(lab,ptn,level,orbits,stats,0,1,1,n,0,n); return level-1; } if (noncheaplevel >= level && !(*dispatch.cheapautom)(ptn,level,digraph,n)) noncheaplevel = level + 1; /* use the elements of the target cell to produce the children: */ index = 0; for (tv1 = tv = nextelement(tcell,M,-1); tv >= 0; tv = nextelement(tcell,M,tv)) { if (orbits[tv] == tv) /* ie, not equiv to previous child */ { breakout(lab,ptn,level+1,tc,tv,active,M); ADDELEMENT(fixedpts,tv); cosetindex = tv; if (tv == tv1) { #if !MAXN rtnlevel = firstpathnode0(lab,ptn,level+1,numcells+1, tcnode_this); #else rtnlevel = firstpathnode(lab,ptn,level+1,numcells+1); #endif childcount = 1; gca_first = level; stabvertex = tv1; } else { #if !MAXN rtnlevel = othernode0(lab,ptn,level+1,numcells+1, tcnode_this); #else rtnlevel = othernode(lab,ptn,level+1,numcells+1); #endif ++childcount; } DELELEMENT(fixedpts,tv); if (rtnlevel < level) return rtnlevel; if (needshortprune) { needshortprune = FALSE; shortprune(tcell,fmptr-M,M); } recover(ptn,level); } if (orbits[tv] == tv1) /* ie, in same orbit as tv1 */ ++index; } MULTIPLY(stats->grpsize1,stats->grpsize2,index); if (tcellsize == index && allsamelevel == level + 1) --allsamelevel; if (domarkers) writemarker(level,tv1,index,tcellsize,stats->numorbits,numcells); OPTCALL(userlevelproc)(lab,ptn,level,orbits,stats,tv1,index,tcellsize, numcells,childcount,n); return level-1; } /***************************************************************************** * * * othernode(lab,ptn,level,numcells) produces a node other than an ancestor * * of the first leaf. The parameters describe the level and the colour * * partition. The list of active cells is found in the global set 'active'. * * The value returned is the level to return to. * * * * FUNCTIONS CALLED: (*usernodeproc)(),doref(),refine(),recover(), * * processnode(),cheapautom(),(*tcellproc)(),shortprune(), * * nextelement(),breakout(),othernode(),longprune() * * * *****************************************************************************/ static int #if !MAXN othernode0(int *lab, int *ptn, int level, int numcells, tcnode *tcnode_parent) #else othernode(int *lab, int *ptn, int level, int numcells) #endif { int tv; int tv1,refcode,rtnlevel,tcellsize,tc,qinvar; short code; #if !MAXN set *tcell; tcnode *tcnode_this; tcnode_this = tcnode_parent->next; if (tcnode_this == NULL) { if ((tcnode_this = (tcnode*)ALLOCS(1,sizeof(tcnode))) == NULL || (tcnode_this->tcellptr = (set*)ALLOCS(alloc_m,sizeof(set))) == NULL) alloc_error("tcell"); tcnode_parent->next = tcnode_this; tcnode_this->next = NULL; } tcell = tcnode_this->tcellptr; #else set tcell[MAXM]; #endif #ifdef NAUTY_IN_MAGMA if (main_seen_interrupt) return NAUTY_ABORT; #endif ++stats->numnodes; /* refine partition : */ doref(g,lab,ptn,level,&numcells,&qinvar,workperm,active, &refcode,dispatch.refine,invarproc,mininvarlevel,maxinvarlevel, invararg,digraph,M,n); code = (short)refcode; if (qinvar > 0) { ++invapplics; if (qinvar == 2) { ++invsuccesses; if (level < invarsuclevel) invarsuclevel = level; } } if (eqlev_first == level - 1 && code == firstcode[level]) eqlev_first = level; if (getcanon) { if (eqlev_canon == level - 1) { if (code < canoncode[level]) comp_canon = -1; else if (code > canoncode[level]) comp_canon = 1; else { comp_canon = 0; eqlev_canon = level; } } if (comp_canon > 0) canoncode[level] = code; } tc = -1; /* If children will be required, find new target cell and set tc to its position in lab, tcell to its contents, and tcellsize to its size: */ if (numcells < n && (eqlev_first == level || getcanon && comp_canon >= 0)) { if (!getcanon || comp_canon < 0) { maketargetcell(g,lab,ptn,level,tcell,&tcellsize,&tc, tc_level,digraph,firsttc[level],dispatch.targetcell,M,n); if (tc != firsttc[level]) eqlev_first = level - 1; } else maketargetcell(g,lab,ptn,level,tcell,&tcellsize,&tc, tc_level,digraph,-1,dispatch.targetcell,M,n); stats->tctotal += tcellsize; } /* optionally call user-defined node examination procedure: */ OPTCALL(usernodeproc)(g,lab,ptn,level,numcells,tc,(int)code,M,n); /* call processnode to classify the type of this node: */ rtnlevel = processnode(lab,ptn,level,numcells); if (rtnlevel < level) /* keep returning if necessary */ return rtnlevel; if (needshortprune) { needshortprune = FALSE; shortprune(tcell,fmptr-M,M); } if (!(*dispatch.cheapautom)(ptn,level,digraph,n)) noncheaplevel = level + 1; /* use the elements of the target cell to produce the children: */ for (tv1 = tv = nextelement(tcell,M,-1); tv >= 0; tv = nextelement(tcell,M,tv)) { breakout(lab,ptn,level+1,tc,tv,active,M); ADDELEMENT(fixedpts,tv); #if !MAXN rtnlevel = othernode0(lab,ptn,level+1,numcells+1,tcnode_this); #else rtnlevel = othernode(lab,ptn,level+1,numcells+1); #endif DELELEMENT(fixedpts,tv); if (rtnlevel < level) return rtnlevel; /* use stored automorphism data to prune target cell: */ if (needshortprune) { needshortprune = FALSE; shortprune(tcell,fmptr-M,M); } if (tv == tv1) longprune(tcell,fixedpts,workspace,fmptr,M); recover(ptn,level); } return level-1; } /***************************************************************************** * * * Process the first leaf of the tree. * * * * FUNCTIONS CALLED: NONE * * * *****************************************************************************/ static void firstterminal(int *lab, int level) { int i; stats->maxlevel = level; gca_first = allsamelevel = eqlev_first = level; firstcode[level+1] = 077777; firsttc[level+1] = -1; for (i = 0; i < n; ++i) firstlab[i] = lab[i]; if (getcanon) { canonlevel = eqlev_canon = gca_canon = level; comp_canon = 0; samerows = 0; for (i = 0; i < n; ++i) canonlab[i] = lab[i]; for (i = 0; i <= level; ++i) canoncode[i] = firstcode[i]; canoncode[level+1] = 077777; stats->canupdates = 1; } } /***************************************************************************** * * * Process a node other than the first leaf or its ancestors. It is first * * classified into one of five types and then action is taken appropriate * * to that type. The types are * * * * 0: Nothing unusual. This is just a node internal to the tree whose * * children need to be generated sometime. * * 1: This is a leaf equivalent to the first leaf. The mapping from * * firstlab to lab is thus an automorphism. After processing the * * automorphism, we can return all the way to the closest invocation * * of firstpathnode. * * 2: This is a leaf equivalent to the bsf leaf. Again, we have found an * * automorphism, but it may or may not be as useful as one from a * * type-1 node. Return as far up the tree as possible. * * 3: This is a new bsf node, provably better than the previous bsf node. * * After updating canonlab etc., treat it the same as type 4. * * 4: This is a leaf for which we can prove that no descendant is * * equivalent to the first or bsf leaf or better than the bsf leaf. * * Return up the tree as far as possible, but this may only be by * * one level. * * * * Types 2 and 3 can't occur if getcanon==FALSE. * * The value returned is the level in the tree to return to, which can be * * anywhere up to the closest invocation of firstpathnode. * * * * FUNCTIONS CALLED: isautom(),updatecan(),testcanlab(),fmperm(), * * writeperm(),(*userautomproc)(),orbjoin(), * * shortprune(),fmptn() * * * *****************************************************************************/ static int processnode(int *lab, int *ptn, int level, int numcells) { int i,code,save,newlevel; boolean ispruneok; int sr; code = 0; if (eqlev_first != level && (!getcanon || comp_canon < 0)) code = 4; else if (numcells == n) { if (eqlev_first == level) { for (i = 0; i < n; ++i) workperm[firstlab[i]] = lab[i]; if (gca_first >= noncheaplevel || (*dispatch.isautom)(g,workperm,digraph,M,n)) code = 1; } if (code == 0) if (getcanon) { sr = 0; if (comp_canon == 0) { if (level < canonlevel) comp_canon = 1; else { (*dispatch.updatecan) (g,canong,canonlab,samerows,M,n); samerows = n; comp_canon = (*dispatch.testcanlab)(g,canong,lab,&sr,M,n); } } if (comp_canon == 0) { for (i = 0; i < n; ++i) workperm[canonlab[i]] = lab[i]; code = 2; } else if (comp_canon > 0) code = 3; else code = 4; } else code = 4; } if (code != 0 && level > stats->maxlevel) stats->maxlevel = level; switch (code) { case 0: /* nothing unusual noticed */ return level; case 1: /* lab is equivalent to firstlab */ if (fmptr == worktop) fmptr -= 2 * M; fmperm(workperm,fmptr,fmptr+M,M,n); fmptr += 2 * M; if (writeautoms) writeperm(outfile,workperm,cartesian,linelength,n); stats->numorbits = orbjoin(orbits,workperm,n); ++stats->numgenerators; OPTCALL(userautomproc)(stats->numgenerators,workperm,orbits, stats->numorbits,stabvertex,n); return gca_first; case 2: /* lab is equivalent to canonlab */ if (fmptr == worktop) fmptr -= 2 * M; fmperm(workperm,fmptr,fmptr+M,M,n); fmptr += 2 * M; save = stats->numorbits; stats->numorbits = orbjoin(orbits,workperm,n); if (stats->numorbits == save) { if (gca_canon != gca_first) needshortprune = TRUE; return gca_canon; } if (writeautoms) writeperm(outfile,workperm,cartesian,linelength,n); ++stats->numgenerators; OPTCALL(userautomproc)(stats->numgenerators,workperm,orbits, stats->numorbits,stabvertex,n); if (orbits[cosetindex] < cosetindex) return gca_first; if (gca_canon != gca_first) needshortprune = TRUE; return gca_canon; case 3: /* lab is better than canonlab */ ++stats->canupdates; for (i = 0; i < n; ++i) canonlab[i] = lab[i]; canonlevel = eqlev_canon = gca_canon = level; comp_canon = 0; canoncode[level+1] = 077777; samerows = sr; break; case 4: /* non-automorphism terminal node */ ++stats->numbadleaves; break; } /* end of switch statement */ /* only cases 3 and 4 get this far: */ if (level != noncheaplevel) { ispruneok = TRUE; if (fmptr == worktop) fmptr -= 2 * M; fmptn(lab,ptn,noncheaplevel,fmptr,fmptr+M,M,n); fmptr += 2 * M; } else ispruneok = FALSE; save = (allsamelevel > eqlev_canon ? allsamelevel-1 : eqlev_canon); newlevel = (noncheaplevel <= save ? noncheaplevel-1 : save); if (ispruneok && newlevel != gca_first) needshortprune = TRUE; return newlevel; } /***************************************************************************** * * * Recover the partition nest at level 'level' and update various other * * parameters. * * * * FUNCTIONS CALLED: NONE * * * *****************************************************************************/ static void recover(int *ptn, int level) { int i; for (i = 0; i < n; ++i) if (ptn[i] > level) ptn[i] = NAUTY_INFINITY; if (level < noncheaplevel) noncheaplevel = level + 1; if (level < eqlev_first) eqlev_first = level; if (getcanon) { if (level < gca_canon) gca_canon = level; if (level <= eqlev_canon) { eqlev_canon = level; comp_canon = 0; } } } /***************************************************************************** * * * Write statistics concerning an ancestor of the first leaf. * * * * level = its level * * tv = the vertex fixed to get the first child = the smallest-numbered * * vertex in the target cell * * cellsize = the size of the target cell * * index = the number of vertices in the target cell which were equivalent * * to tv = the index of the stabiliser of tv in the group * * fixing the colour partition at this level * * * * numorbits = the number of orbits of the group generated by all the * * automorphisms so far discovered * * * * numcells = the total number of cells in the equitable partition at this * * level * * * * FUNCTIONS CALLED: itos(),putstring() * * * *****************************************************************************/ static void writemarker(int level, int tv, int index, int tcellsize, int numorbits, int numcells) { char s[30]; #define PUTINT(i) itos(i,s); putstring(outfile,s) #define PUTSTR(x) putstring(outfile,x) PUTSTR("level "); PUTINT(level); PUTSTR(": "); if (numcells != numorbits) { PUTINT(numcells); PUTSTR(" cell"); if (numcells == 1) PUTSTR("; "); else PUTSTR("s; "); } PUTINT(numorbits); PUTSTR(" orbit"); if (numorbits == 1) PUTSTR("; "); else PUTSTR("s; "); PUTINT(tv+labelorg); PUTSTR(" fixed; index "); PUTINT(index); if (tcellsize != index) { PUTSTR("/"); PUTINT(tcellsize); } PUTSTR("\n"); } /***************************************************************************** * * * nauty_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void nauty_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in nauty.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in nauty.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in nauty.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: nauty.c version mismatch\n"); exit(1); } } /***************************************************************************** * * * extra_autom(p,n) - add an extra automophism, hard to do correctly * * * *****************************************************************************/ void extra_autom(permutation *p, int n) { if (writeautoms) writeperm(outfile,p,cartesian,linelength,n); stats->numorbits = orbjoin(orbits,p,n); ++stats->numgenerators; OPTCALL(userautomproc)(stats->numgenerators,p,orbits, stats->numorbits,stabvertex,n); } /***************************************************************************** * * * extra_level(level,lab,ptn,numcells,tv1,index,tcellsize,childcount) * * creates an artificial level in the search. This is dangerous. * * * *****************************************************************************/ void extra_level(int level, int *lab, int *ptn, int numcells, int tv1, int index, int tcellsize, int childcount, int n) { MULTIPLY(stats->grpsize1,stats->grpsize2,index); if (domarkers) writemarker(level,tv1,index,tcellsize,stats->numorbits,numcells); OPTCALL(userlevelproc)(lab,ptn,level,orbits,stats,tv1,index,tcellsize, numcells,childcount,n); } /***************************************************************************** * * * nauty_freedyn() frees all the dynamic memory used in this module. * * * *****************************************************************************/ void nauty_freedyn(void) { #if !MAXN tcnode *tcp,*tcq; tcp = tcnode0.next; while (tcp != NULL) { tcq = tcp->next; FREES(tcp->tcellptr); FREES(tcp); tcp = tcq; } alloc_m = 0; tcnode0.next = NULL; DYNFREE(firsttc,firsttc_sz); DYNFREE(canoncode,canoncode_sz); DYNFREE(firstcode,firstcode_sz); DYNFREE(workperm,workperm_sz); DYNFREE(canonlab,canonlab_sz); DYNFREE(firstlab,firstlab_sz); DYNFREE(defltwork,defltwork_sz); DYNFREE(fixedpts,fixedpts_sz); DYNFREE(active,active_sz); #endif } nauty24r2/gutil2.c0000600000604200001440000001756611274163463012700 0ustar bdmusers/* gutil2.c: Some more graph utilities. */ #include "gtools.h" #include "gutils.h" /**************************************************************************/ int loopcount(graph *g, int m, int n) /* Number of loops */ { set *gi; int i,nl; nl = 0; for (i = 0, gi = g; i < n; ++i, gi += m) if (ISELEMENT(gi,i)) ++nl; return nl; } /**************************************************************************/ 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. */ { long count; setword gs,w; int i; gs = g[start]; w = gs & last; count = POPCOUNT(w); body &= ~bit[start]; w = gs & body; while (w) { TAKEBIT(i,w); count += pathcount1(g,i,body,last&~bit[i]); } return count; } /**************************************************************************/ long cyclecount1(graph *g, int n) /* The total number of cycles in g (assumed no loops), m=1 only */ { setword body,nbhd; long total; int i,j; body = ALLMASK(n); total = 0; for (i = 0; i < n-2; ++i) { body ^= bit[i]; nbhd = g[i] & body; while (nbhd) { TAKEBIT(j,nbhd); total += pathcount1(g,j,body,nbhd); } } return total; } /**************************************************************************/ long cyclecount(graph *g, int m, int n) /* The total number of cycles in g (assumed no loops) */ { if (m == 1) return cyclecount1(g,n); gt_abort("cycle counting is only implemented for n <= WORDSIZE"); return 0; } /**************************************************************************/ long numtriangles1(graph *g, int n) /* The number of triangles in g */ { int i,j; setword gi,w; long total; total = 0; for (i = 0; i < n-2; ++i) { gi = g[i] & BITMASK(i); while (gi) { TAKEBIT(j,gi); w = g[j] & gi; if (w) total += POPCOUNT(w); } } return total; } /**************************************************************************/ long numtriangles(graph *g, int m, int n) /* The number of triangles in g */ { int i,j,k,kw; setword *gi,*gj,w; long total; if (m == 1) return numtriangles1(g,n); total = 0; for (i = 0, gi = g; i < n-2; ++i, gi += m) for (j = i; (j = nextelement(gi,m,j)) > 0; ) { gj = GRAPHROW(g,j,m); kw = SETWD(j); w = gi[kw] & gj[kw] & BITMASK(SETBT(j)); if (w) total += POPCOUNT(w); for (k = kw+1; k < m; ++k) { w = gi[k] & gj[k]; if (w) total += POPCOUNT(w); } } return total; } /**************************************************************************/ 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. */ { int j,k; int mina,maxa,minn,maxn; int cn; set *gi,*gj; setword w; mina = minn = n+1; maxa = maxn = -1; for (j = 0, gj = g; j < n; ++j, gj += m) for (gi = g; gi != gj; gi += m) { cn = 0; for (k = 0; k < m; ++k) { w = gi[k] & gj[k]; if (w) cn += POPCOUNT(w); } if (ISELEMENT(gi,j)) { if (cn < mina) mina = cn; if (cn > maxa) maxa = cn; } else { if (cn < minn) minn = cn; if (cn > maxn) maxn = cn; } } *minadj = mina; *maxadj = maxa; *minnon = minn; *maxnon = maxn; } /**************************************************************************/ void delete1(graph *g, graph *h, int v, int n) /* Delete vertex v from g, result in h */ { setword mask1,mask2,gi; int i; mask1 = ALLMASK(v); mask2 = BITMASK(v); for (i = 0; i < v; ++i) { gi = g[i]; h[i] = (gi & mask1) | ((gi & mask2) << 1); } for (i = v; i < n-1; ++i) { gi = g[i+1]; h[i] = (gi & mask1) | ((gi & mask2) << 1); } } /**************************************************************************/ void contract1(graph *g, graph *h, int v, int w, int n) /* Contract distinct vertices v and w (not necessarily adjacent) with result in h. No loops are created. */ { int x,y; setword bitx,bity,mask1,mask2; int i; if (w < v) { x = w; y = v; } else { x = v; y = w; } bitx = bit[x]; bity = bit[y]; mask1 = ALLMASK(y); mask2 = BITMASK(y); for (i = 0; i < n; ++i) if (g[i] & bity) h[i] = (g[i] & mask1) | bitx | ((g[i] & mask2) << 1); else h[i] = (g[i] & mask1) | ((g[i] & mask2) << 1); h[x] |= h[y]; for (i = y+1; i < n; ++i) h[i-1] = h[i]; h[x] &= ~bitx; } /**************************************************************************/ static int knm[18][16]; /* knm[n,m] = conncontent(K_n - m*K_2) */ static boolean knm_computed = FALSE; 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 */ { graph h[WORDSIZE]; setword gj; int i,j,v1,v2,x,y; int minv,mindeg,deg,goodv; long ne; if (m > 1) ABORT("conncontent only implemented for m=1"); /* First handle tiny graphs */ if (n <= 3) { if (n == 1) return 1; if (n == 2) return (g[0] ? -1 : 0); if (!g[0] || !g[1] || !g[2]) return 0; /* disconnected */ if (g[0]^g[1]^g[2]) return 1; /* path */ return 2; /* triangle */ } /* Now compute ne = number of edges mindeg = minimum degree minv = a vertex of minimum degree goodv = a vertex with a clique neighbourhood (-1 if none) */ mindeg = n; ne = 0; goodv = -1; for (j = 0; j < n; ++j) { gj = g[j]; deg = POPCOUNT(gj); ne += deg; if (deg < mindeg) { mindeg = deg; minv = j; if (deg == 1) goodv = j; } if (deg >= 3 && deg <= 4 && goodv < 0) { while (gj) { TAKEBIT(i,gj); if (gj & ~g[i]) break; } if (!gj) goodv = j; } } ne /= 2; /* Cases of isolated vertex or tree */ 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) { j = -1; for (i = 2; i < n; ++i) j *= -i; return j; } if (mindeg == n-2 && n < 16) { if (!knm_computed) { knm_computed = TRUE; knm[1][0] = 1; for (i = 2; i < 16; ++i) { knm[i][0] = -knm[i-1][0] * (i-1); for (j = 1; j+j <= i; ++j) knm[i][j] = knm[i][j-1] + knm[i-1][j-1]; } } return knm[n][(n*n-n)/2-ne]; } /* Case of vertex with clique neighbourhood */ if (goodv >= 0) { delete1(g,h,goodv,n); return -POPCOUNT(g[goodv]) * conncontent(h,m,n-1); } /* Case of minimum degree 2 */ if (mindeg == 2) { x = FIRSTBIT(g[minv]); y = FIRSTBIT(g[minv]^bit[x]); if (x > minv) --x; if (y > minv) --y; delete1(g,h,minv,n); v1 = conncontent(h,m,n-1); if (h[x] & bit[y]) return -2*v1; /* adjacent neighbours */ h[x] |= bit[y]; h[y] |= bit[x]; v2 = conncontent(h,m,n-1); return -v1 - v2; } /* Case of more than 2/3 dense but not complete */ if (3*ne > n*n-n) { j = FIRSTBIT(g[minv] ^ bit[minv] ^ ALLMASK(n)); /* non-neighbour */ g[minv] ^= bit[j]; g[j] ^= bit[minv]; v1 = conncontent(g,m,n); g[minv] ^= bit[j]; g[j] ^= bit[minv]; contract1(g,h,minv,j,n); v2 = conncontent(h,m,n-1); return v1 + v2; } /* All remaining cases */ j = FIRSTBIT(g[minv]); /* neighbour */ g[minv] ^= bit[j]; g[j] ^= bit[minv]; v1 = conncontent(g,m,n); g[minv] ^= bit[j]; g[j] ^= bit[minv]; contract1(g,h,minv,j,n); v2 = conncontent(h,m,n-1); return v1 - v2; } nauty24r2/NRswitchg.c0000600000604200001440000001027711274163463013372 0ustar bdmusers/* NRswitchg.c nauty version 2.4; B D McKay, Dec 2005 */ #define USAGE "NRswitchg [-lq] [infile [outfile]]" #define HELPTEXT \ " For each v, complement the edges from N(v) to V(G)-N(v)-v.\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -l Canonically label outputs.\n\ -q Suppress auxiliary information.\n" /*************************************************************************/ #include "gtools.h" /**************************************************************************/ void NRswitch(graph *g, int m, int n, int v, graph *h) /* h := g with N-R edge set complemented */ { register int i,j; register setword *gv,*gi,*hi; #if MAXN set Nset[MAXM]; set Rset[MAXM]; #else DYNALLSTAT(set,Nset,Nset_sz); DYNALLSTAT(set,Rset,Rset_sz); DYNALLOC1(set,Nset,Nset_sz,m,"NRswitchg"); DYNALLOC1(set,Rset,Rset_sz,m,"NRswitchg"); #endif EMPTYSET(Rset,m); for (i = 0; i < n; ++i) ADDELEMENT(Rset,i); gv = GRAPHROW(g,v,m); for (j = 0; j < m; ++j) { Nset[j] = gv[j]; Rset[j] ^= gv[j]; } FLIPELEMENT(Rset,v); gi = (setword*) g; hi = (setword*) h; for (i = 0; i < n; ++i) { if (i == v) for (j = 0; j < m; ++j) hi[j] = gi[j]; else if (ISELEMENT(Nset,i)) for (j = 0; j < m; ++j) hi[j] = gi[j] ^ Rset[j]; else for (j = 0; j < m; ++j) hi[j] = gi[j] ^ Nset[j]; gi += m; hi += m; } } /**************************************************************************/ int main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile,*outfile; boolean badargs,dolabel,quiet; int j,m,n,v,argnum; int codetype,outcode; graph *g; long nin,nout; char *arg,sw; static graph *gq; double t; #if MAXN graph gc[MAXN*MAXM],h[MAXN*MAXM]; #else DYNALLSTAT(graph,gc,gc_sz); DYNALLSTAT(graph,h,h_sz); #endif HELP; infilename = outfilename = NULL; badargs = FALSE; dolabel = quiet = FALSE; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('l',dolabel) else SWBOOLEAN('q',quiet) else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!quiet) { fprintf(stderr,">A NRswitchg"); if (dolabel) fprintf(stderr," -l"); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (codetype&HAS_HEADER) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } if (dolabel) nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); nin = nout = 0; t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; #if !MAXN DYNALLOC2(graph,gc,gc_sz,n,m,"NRswitchg"); #endif for (v = 0; v < n; ++v) { NRswitch(g,m,n,v,gc); gq = gc; if (dolabel) { #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"compl"); #endif fcanonise(gq,m,n,h,NULL,FALSE); gq = h; } if (outcode == SPARSE6) writes6(outfile,gq,m,n); else writeg6(outfile,gq,m,n); ++nout; } FREES(g); } t = CPUTIME - t; if (!quiet) fprintf(stderr, ">Z %ld graphs read from %s, %ld written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,t); exit(0); } nauty24r2/nautest2.c0000600000604200001440000000260111274163463013217 0ustar bdmusers/* Test for basic nauty and dreadnaut functions (but not nauty itself) */ #include "naututil.h" long seed; int main(int argc, char *argv[]) { int i,j,bad; setword w; int curfile; FILE *f; #ifdef CPUDEFS CPUDEFS #endif printf("NAUTYVERSION=%s NAUTYVERSIONID=%d\n", NAUTYVERSION,NAUTYVERSIONID); printf("MAXN=%d MAXM=%d WORDSIZE=%d NAUTY_INFINITY=%d\n", MAXN,MAXM,WORDSIZE,NAUTY_INFINITY); printf("defined:"); #ifdef __STDC__ printf(" __STDC__"); #endif #ifdef BIGNAUTY printf(" BIGNAUTY"); #endif #ifdef SYS_UNIX printf(" SYS_UNIX"); #endif #ifdef SYS_CRAY printf(" SYS_CRAY"); #endif #ifdef SETWORD_SHORT printf(" SETWORD_SHORT"); #endif #ifdef SETWORD_INT printf(" SETWORD_INT"); #endif #ifdef SETWORD_LONG printf(" SETWORD_LONG"); #endif #ifdef SETWORD_LONGLONG printf(" SETWORD_LONGLONG"); #endif printf("\n"); #ifdef DOPROMPT curfile = 0; printf("DOPROMPT(stdin)=%d DOPROMPT(stdout)=%d\n", DOPROMPT(stdin),DOPROMPT(stdout)); #else printf("DOPROMPT is not defined\n"); #endif #ifdef CPUTIME printf("CPUTIME = %f\n",CPUTIME); #else printf("CPUTIME is not defined\n"); #endif #ifdef INITSEED INITSEED; printf("INITSEED: seed=%ld\n",seed); #else printf("INITSEED is not defined\n"); #endif #ifdef OPENOUT OPENOUT(f,"nautest.txt",0); fprintf(f,"test\n"); #else printf("OPENOUT is not defined\n"); #endif exit(0); } nauty24r2/naututil.h0000600000604200001440000002773211274163470013336 0ustar bdmusers/***************************************************************************** * This is the header file for versions 2.4 of naututil.c and dreadnaut.c. * * naututil.h. Generated from naututil-h.in by configure. *****************************************************************************/ /* The parts between the ==== lines are modified by configure when creating naututil.h out of naututil-h.in. If configure is not being used, it is necessary to check they are correct. ====================================================================*/ /* Check whether various headers are available */ #define HAVE_ISATTY 1 /* if isatty() is available */ #define HAVE_TIMES 1 /* if times() is available */ #define HAVE_TIME 1 /* if time() is available */ #define HAVE_GETRUSAGE 1 /* if getrusage() is available */ #define HAVE_GETTIMEOFDAY 1 /* if gettimeofday() */ /*==================================================================*/ /***************************************************************************** * * * Copyright (1984-2007) Brendan McKay. All rights reserved. * * Subject to the waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 10-Nov-87 : final changes for version 1.2 * * 5-Dec-87 : changes for version 1.3 : * * - added declarations of readinteger() and readstring() * * - added definition of DEFEXT : default file-name * * extension for dreadnaut input files * * 28-Sep-88 : changes for version 1.4 : * * - added support for PC Turbo C * * 29-Nov-88 : - added getc macro for AZTEC C on MAC * * 23-Mar-89 : changes for version 1.5 : * * - added DREADVERSION macro * * - added optional ANSI function prototypes * * - changed file name to naututil.h * * - moved ALLOCS to nauty.h and defined DYNALLOC * * 25-Mar-89 : - added declaration of twopaths() * * 29-Mar-89 : - added declaration of putmapping() * * 4-Apr-89 : - added declarations of triples, quadruples, adjtriang * * - only define ERRFILE if not in nauty.h * * 25-Apr-89 : - added declarations of cellquads,distances,getbigcells * * 26-Apr-89 : - added declarations of indsets,cliques,cellquins * * - removed declarations of ptncode and equitable * * 27-Apr-89 : - added declaration of putquotient * * 18-Aug-89 : - added new arg to putset, and changed mathon * * 2-Mar-90 : - added declarations of celltrips, cellcliq, cellind * * - changed declarations to use EXTPROC * * 12-Mar-90 : - added changes for Cray version * * 20-Mar-90 : - added changes for THINK version * * 27-Mar-90 : - split SYS_MSDOS into SYS_PCMS4 and SYS_PCMS5 * * 13-Oct-90 : changes for version 1.6 : * * - changed CPUTIME to use HZ on Unix for times() * * 14-Oct-90 : - added SYS_APOLLO variant * * 19-Oct-90 : - changed CPUTIME defs for BSDUNIX to avoid conficting * * declarations of size_t and ptrdiff_t in gcc * * 27-Aug-92 : changes for version 1.7 : * * - added SYS_IBMC variant * * - removed workaround for bad gcc installation * * 5-Jun-93 : changes for version 1.8 : * * - changed CRAY version of CPUTIME to use CLK_TCK * * if HZ could not be found (making 1.7+) * * 30-Jul-93 : - added SYS_ALPHA variant * * 17-Sep-93 : changes for version 1.9 : * * - declared adjacencies() * * 24-Feb-94 : changes for version 1.10 : * * - added version SYS_AMIGAAZT (making 1.9+) * * 19-Apr-95 : - added C++ prototype wrapper * * 6-Mar-96 : - added SYS_ALPHA32 code * * 23-Jul-96 : changes for version 2.0 : * * - changed readstring() declaration * * - removed DYNALLOC definition * * - added sublabel() definition * * 15-Aug-96 : - added sethash() definition * * 30-Aug-96 : - added KRAN and D. Knuth routines * * 16-Sep-96 : - fixed the above! * * 7-Feb-96 : - declared nautinv_null() and setnbhd() * * 4-Sep-97 : - arg of time() is type time_t*, was long* * * 22-Sep-97 : - defined fileno() and time_t for SYS_PCTURBO * * 10-Dec-97 : - revised KRAN for new rng.c from Knuth * * 18-Feb-98 : - changed time() to time_t for Unix * * 21-Oct-98 : - changed short to shortish as needed * * 9-Jan-00 : - declared nautinv_check() and naututil_check() * * 16-Nov-00 : - applied changes logged in nauty.h * * 22-Apr-01 : changes for version 2.1 : * * - prototypes for nautinv.c are now in nautinv.h * * - CPUTIME for UNIX uses CLK_TCK (needs revision!) * * 2-Jun-01 : - prototype for converse() * * 18-Oct-01 : - complete revision; sysdeps in separate files * * 28-Aug-02 : changes for version 2.2 : * * - revised for autoconf * * 17-Nov-02 : added explicit "extern" where it was implicit before * * 11-Apr-02 : added rangraph2() * * 10-Sep-07 : Define CPUTIME=0.0 for hosts that don't provide it * * * *****************************************************************************/ #include "nauty.h" /* which includes stdio.h */ /* At this point we can assume that , , , , or and if necessary have been included if they exist. */ #ifdef __cplusplus extern "C" { #endif extern void complement(graph*,int,int); extern void converse(graph*,int,int); extern void copycomment(FILE*,FILE*,int); extern void flushline(FILE*); extern void fixit(int*,int*,int*,int,int); extern int getint(FILE*); extern long hash(set*,long,int); extern void mathon(graph*,int,int,graph*,int,int); extern void naututil_check(int,int,int,int); extern void putcanon(FILE*,int*,graph*,int,int,int); extern void putdegs(FILE*,graph*,int,int,int); extern void putgraph(FILE*,graph*,int,int,int); extern void putmapping(FILE*,int*,int,int*,int,int,int); extern void putorbits(FILE*,int*,int,int); extern void putptn(FILE*,int*,int*,int,int,int); extern void putquotient(FILE*,graph*,int*,int*,int,int,int,int); extern void putset(FILE*,set*,int*,int,int,boolean); extern long ran_arr_cycle(void); extern void ran_array(long*,int); extern void ran_init(long); extern void rangraph(graph*,boolean,int,int,int); extern void rangraph2(graph*,boolean,int,int,int,int); extern void ranperm(permutation*,int); extern void readgraph(FILE*,graph*,boolean,boolean,boolean,int,int,int); extern boolean readinteger(FILE*,int*); extern void readperm(FILE*,permutation*,boolean,int); extern void readptn(FILE*,int*,int*,int*,boolean,int); extern void readvperm(FILE*,permutation*,boolean,int,int*); extern boolean readstring(FILE*,char*,int); extern void relabel(graph*,int*,permutation*,graph*,int,int); extern long sethash(set*,int,long,int); extern int setinter(set*,set*,int); extern int setsize(set*,int); extern void sublabel(graph*,permutation*,int,graph*,int,int); extern void unitptn(int*,int*,int*,int); #ifdef __cplusplus } #endif #define PROMPTFILE stdout /* where to write prompts */ #ifndef ERRFILE #define ERRFILE stderr /* where to write error messages */ #endif #define MAXIFILES 10 /* how many input files can be open at once */ #define EXIT exit(0) /* how to stop normally */ #define DEFEXT ".dre" /* extension for dreadnaut files */ extern long *ran_arr_ptr; /* declared in rng.c */ extern long seed; /* declared in naututil.c */ #define NEXTRAN (*ran_arr_ptr>=0 ? *ran_arr_ptr++ : ran_arr_cycle()) #define KRAN(k) (NEXTRAN%(k)) /************************************************************************* The following macros may represent differences between system. This file contains the UNIX/POSIX editions. For other systems, a separate file of definitions is read in first. That file should define the variables NAUTY_*_DEFINED for sections that are to replace the UNIX versions. See the provided examples for more details. If your system does not have a predefined macro you can use to cause a definitions file to be read, you have to make up one and arrange for it to be defined when this file is read. The system-dependent files can also redefine the macros just ahead of this comment. **************************************************************************/ #ifdef __weirdmachine__ #include "weird.h" /* Some weird machine (ILLUSTRATION ONLY) */ #endif /*************************************************************************/ #ifndef NAUTY_PROMPT_DEFINED #if HAVE_ISATTY #define DOPROMPT(fp) (isatty(fileno(fp)) && isatty(fileno(PROMPTFILE))) #else #define DOPROMPT(fp) (curfile==0) #endif #endif /*NAUTY_PROMPT_DEFINED*/ /*************************************************************************/ #ifndef NAUTY_OPEN_DEFINED #define OPENOUT(fp,name,append) fp = fopen(name,(append)?"a":"w") #endif /*NAUTY_OPEN_DEFINED*/ /*************************************************************************/ #ifndef NAUTY_CPU_DEFINED #if HAVE_TIMES #include #define CPUDEFS static struct tms timebuffer; #ifndef CLK_TCK #include #endif #if !defined(CLK_TCK) && defined(_SC_CLK_TCK) #define CLK_TCK sysconf(_SC_CLK_TCK) #endif #ifndef CLK_TCK #define CLK_TCK 60 #endif #define CPUTIME (times(&timebuffer),\ (double)(timebuffer.tms_utime + timebuffer.tms_stime) / CLK_TCK) #else #if HAVE_GETRUSAGE #include #include #define CPUDEFS struct rusage ruse; #define CPUTIME (getrusage(RUSAGE_SELF,&ruse),\ ruse.ru_utime.tv_sec + ruse.ru_stime.tv_sec + \ 1e-6 * (ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec)) #endif #endif #ifndef CPUTIME #define CPUTIME 0.0 #endif #endif /*NAUTY_CPU_DEFINED*/ /*************************************************************************/ #ifndef NAUTY_SEED_DEFINED #if HAVE_GETTIMEOFDAY #include #define INITSEED \ {struct timeval nauty_tv; \ struct timezone nauty_tz; \ gettimeofday(&nauty_tv,&nauty_tz); \ seed = (nauty_tv.tv_sec<<10) + (nauty_tv.tv_usec>>10) & 017777777777L;} #else #if HAVE_TIME #include #define INITSEED seed = ((time((time_t*)NULL)<<1) | 1) & 017777777777L #endif #endif #endif /*NAUTY_SEED_DEFINED*/ nauty24r2/listg.c0000600000604200001440000003200111274163463012571 0ustar bdmusers/* listg.c version 1.4; B D McKay, June 2007 */ #define USAGE "listg [-fp#:#l#o#Ftq] [-a|-A|-c|-d|-e|-M|-s] [infile [outfile]]" #define HELPTEXT \ " Write graphs in human-readable format.\n\ \n\ -f : assume inputs have same size (only used from a file\n\ and only if -p is given)\n\ -p#, -p#:#, -p#-# : only display one graph or a sequence of\n\ graphs. The first graph is number 1. A second number\n\ which is empty or zero means infinity.\n\ -a : write as adjacency matrix, not as list of adjacencies\n\ -A : same as -a with a space between entries\n\ -l# : specify screen width limit (default 78, 0 means no limit)\n\ This is not currently implemented with -a or -A.\n\ -o# : specify number of first vertex (default is 0).\n\ -d : write output to satisfy dreadnaut \n\ -c : write ascii form with minimal line-breaks\n\ -e : write a list of edges, preceded by the order and the\n\ number of edges\n\ -M : write in Magma format\n\ -W : write matrix in Maple format\n\ -t : write upper triangle only (affects -a, -A, -d and default)\n\ -s : write only the numbers of vertices and edges\n\ -F : write a form-feed after each graph except the last\n\ -q : suppress auxiliary output\n\ \n\ -a, -A, -c, -d, -M, -W and -e are incompatible.\n" #define MAPLE_MATRIX 1 /* 1 for Matrix(..), 0 for array(..) */ /************************************************************************* June 26, 2007 : Fix error in putve() reported by Evan Heidtmann *************************************************************************/ #include "gtools.h" #define LABELORG 0 /* number of first vertex (any integer >= 0) */ #define LINELEN CONSOLWIDTH /* max characters per line (0 = no limit) */ static FILE *infile,*outfile; static unsigned long nin; extern int labelorg; /***************************************************************************** * * * putsetx(f,set1,curlenp,linelength,m,compress,start) writes the set * * set1 to file f using at most linelength characters per line (excluding * * '\n'). Set elements less than or equal to start are ignored. * * *curlenp is the number of characters on the line so far; it is updated. * * A range j1,j1+1,...,j2 for j2-j1>=2 is written as "j1:j2" if compress * * is nonzero (eg. TRUE); otherwise each element is written separately. * * No final '\n' is written. labelorg is used. * * * * FUNCTIONS CALLED: nextelement(),itos() * * * *****************************************************************************/ void putsetx(FILE *f, set *set1, int *curlenp, int linelength, int m, boolean compress, int start) { int slen,j1,j2; char s[40]; boolean first; first = TRUE; j1 = start; while ((j1 = nextelement(set1,m,j1)) >= 0) { j2 = j1; if (compress) { while (nextelement(set1,m,j2) == j2 + 1) ++j2; if (j2 == j1+1) j2 = j1; } slen = itos(j1 + labelorg,s); if (j2 >= j1 + 2) { s[slen] = ':'; slen += 1 + itos(j2 + labelorg,&s[slen+1]); } if (*curlenp + slen + 1 >= linelength) { fprintf(f,"\n "); *curlenp = 1; } if (first) { fprintf(f,"%s",s); *curlenp += slen; first = FALSE; } else { fprintf(f," %s",s); *curlenp += slen + 1; } j1 = j2; } } /***************************************************************************** * * * STOLEN FROM naututil.c * * putgraphx(f,g,linelength,m,n) writes a list of the edges of g to f * * using at most linelength characters per line (excluding '\n'). * * If triang, only write the upper triangle. * * labelorg is used. * * * *****************************************************************************/ void putgraphx(FILE *f, graph *g, int linelength, boolean triang, int m, int n) { int i,curlen; set *pg; for (i = 0, pg = g; i < n; ++i, pg += m) { fprintf(f,"%3d : ",i + labelorg); curlen = 7; putsetx(f,pg,&curlen,linelength,m,FALSE,triang ? i-1 : -1); fprintf(f,";\n"); } } /***************************************************************************/ void putedges(FILE *f, graph *g, boolean ptn, int linelength, int m, int n) /* Write list of edges, preceded by the numbers of vertices and edges and optionally by "1" if "ptn" is TRUE. Use labelorg */ { int i,j,curlen,ne; char s[20]; set *pg; ne = 0; for (i = 0, pg = g; i < n; ++i, pg += m) { for (j = i-1; (j = nextelement(pg,m,j)) >= 0;) ++ne; } if (ptn) fprintf(f,"%d %d 1\n",n,ne); else fprintf(f,"%d %d\n",n,ne); curlen = 0; for (i = 0, pg = g; i < n; ++i, pg += m) { for (j = i-1; (j = nextelement(pg,m,j)) >= 0;) { if (curlen > linelength - 10 && linelength > 0) { fprintf(f,"\n"); curlen = 0; } if (curlen > 0) { fprintf(f," "); curlen += 2; } curlen += itos(i+labelorg,s); fprintf(f,s); fprintf(f," "); curlen += 1 + itos(j+labelorg,s); fprintf(f,s); } } fprintf(f,"\n"); } /***************************************************************************/ void putcgraph(FILE *f, graph *g, int linelength, int m, int n) /* write compressed form, using labelorg */ { int i,curlen; int semicolons; char s[20]; set *pg; curlen = itos(n,s)+2; fprintf(f,";n%sg",s); semicolons = 0; for (i = 0, pg = g; i < n; ++i, pg += m) { if (nextelement(pg,m,i-1) >= 0) { while (semicolons > 0) { if (curlen >= linelength-1 && linelength > 0) { fprintf(f,"\n "); curlen = 1; } fprintf(f,";"); ++curlen; --semicolons; } putsetx(f,pg,&curlen,linelength,m,FALSE,i-1); semicolons = 1; } else ++semicolons; } fprintf(f,".\n"); } /**************************************************************************/ static void putve(FILE *f, unsigned long id, graph *g, int m, int n) /* Write the numbers of vertices and edges */ { unsigned long ne; setword x,*pg; ne = 0; for (pg = g + m*(long)n; --pg >= g;) if ((x = *pg) != 0) ne += POPCOUNT(x); fprintf(f,"Graph %lu has %d vertices and %lu edges.\n",id,n,ne/2); } /**************************************************************************/ static void putam(FILE *f, graph *g, int linelength, boolean space, boolean triang, int m, int n) /* write adjacency matrix */ { set *gi; int i,j; boolean first; for (i = 0, gi = (set*)g; i < n - (triang!=0); ++i, gi += m) { first = TRUE; for (j = triang ? i+1 : 0; j < n; ++j) { if (!first && space) putc(' ',f); else first = FALSE; if (ISELEMENT(gi,j)) putc('1',f); else putc('0',f); } putc('\n',f); } } /**************************************************************************/ static void putMagma(FILE *outfile, graph *g, int linelength, int m, int n, long index) { int i,j; set *gi; boolean first; fprintf(outfile,"g%ld := Graph<%d|[\n",index,n); for (i = 0, gi = (set*)g; i < n; ++i, gi += m) { fprintf(outfile,"{"); first = TRUE; for (j = i; (j = nextelement(gi,m,j)) >= 0; ) { if (!first) fprintf(outfile,","); first = FALSE; fprintf(outfile,"%d",j+1); } fprintf(outfile,"}"); if (i != n-1) fprintf(outfile,",\n"); } fprintf(outfile,"]>;\n"); } /**************************************************************************/ static void putMaple(FILE *outfile, graph *g, int linelength, int m, int n, long index) { int i,j; set *gi; boolean first; #if MAPLE_MATRIX fprintf(outfile,"f%ld := Matrix(%d,%d,[\n",index,n,n); #else fprintf(outfile,"f%ld := array(1..%d,1..%d,[\n",index,n,n); #endif for (i = 0, gi = (set*)g; i < n; ++i, gi += m) { fprintf(outfile,"["); first = TRUE; for (j = 0; j < n; ++j) { if (!first) fprintf(outfile,","); first = FALSE; fprintf(outfile,"%d",(ISELEMENT(gi,j)?1:0)); } fprintf(outfile,"]"); if (i != n-1) fprintf(outfile,",\n"); } fprintf(outfile,"]);\n"); } /**************************************************************************/ /**************************************************************************/ int main(int argc, char *argv[]) { graph *g; int m,n,codetype; int argnum,j; char *arg,sw; boolean badargs; unsigned long maxin; long pval1,pval2; boolean fswitch,pswitch,cswitch,dswitch; boolean aswitch,lswitch,oswitch,Fswitch; boolean Aswitch,eswitch,tswitch,qswitch; boolean sswitch,Mswitch,Wswitch,Eswitch; int linelength; char *infilename,*outfilename; HELP; fswitch = pswitch = cswitch = dswitch = FALSE; aswitch = lswitch = oswitch = Fswitch = FALSE; Aswitch = eswitch = tswitch = qswitch = FALSE; sswitch = Mswitch = Wswitch = Eswitch = FALSE; infilename = outfilename = NULL; linelength = LINELEN; labelorg = 0; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('a',aswitch) else SWBOOLEAN('A',Aswitch) else SWBOOLEAN('c',cswitch) else SWBOOLEAN('d',dswitch) else SWBOOLEAN('e',eswitch) else SWBOOLEAN('E',Eswitch) else SWBOOLEAN('f',fswitch) else SWBOOLEAN('F',Fswitch) else SWBOOLEAN('t',tswitch) else SWBOOLEAN('q',qswitch) else SWBOOLEAN('M',Mswitch) else SWBOOLEAN('W',Wswitch) else SWBOOLEAN('s',sswitch) else SWRANGE('p',":-",pswitch,pval1,pval2,"listg -p") else SWINT('l',lswitch,linelength,"listg -l") else SWINT('o',oswitch,labelorg,"listg -o") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (labelorg < 0) gt_abort(">E listg: negative origin forbidden.\n"); if ((aswitch!=0) + (Aswitch!=0) + (eswitch!=0) + (Mswitch!=0) + (Wswitch!=0) + (sswitch!=0) + (dswitch!=0) + (cswitch!=0) + (Eswitch!=0) > 1) gt_abort(">E listg: -aAMWeEcds are incompatible\n"); if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); fprintf(stderr," Try listg -help for more detailed help.\n"); exit(1); } if (!pswitch || pval1 < 1) pval1 = 1; if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,fswitch, pswitch ? pval1 : 1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } nin = 0; if (!pswitch || pval2 == NOLIMIT) maxin = NOLIMIT; else if (pval1 < 1) maxin = pval2; else maxin = pval2 - pval1 + 1; while (nin < maxin || maxin == NOLIMIT) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; if (Fswitch && nin > 1) fprintf(outfile,"\f"); if (cswitch) putcgraph(outfile,g,linelength,m,n); else if (dswitch) { if (qswitch) fprintf(outfile,"%d\n",n); else { fprintf(outfile,"\n!Graph %lu.\n",pval1+nin-1); fprintf(outfile,"n=%d $=%d g\n",n,labelorg); } putgraphx(outfile,g,linelength,tswitch,m,n); if (!qswitch) fprintf(outfile,"$$\n"); } else if (Mswitch) putMagma(outfile,g,linelength,m,n,pval1+nin-1); else if (Wswitch) putMaple(outfile,g,linelength,m,n,pval1+nin-1); else if (sswitch) putve(outfile,pval1+nin-1,g,m,n); else { if (qswitch) { if (!eswitch && !Eswitch) fprintf(outfile,"%d\n",n); } else fprintf(outfile,"\nGraph %lu, order %d.\n", pval1+nin-1,n); if (aswitch|Aswitch) putam(outfile,g,linelength,Aswitch,tswitch,m,n); else if (eswitch || Eswitch) putedges(outfile,g,Eswitch,linelength,m,n); else putgraphx(outfile,g,linelength,tswitch,m,n); } FREES(g); } exit(0); } nauty24r2/nauty-h.in0000600000604200001440000013565011427225073013232 0ustar bdmusers/************************************************************************** * This is the header file for Version 2.4 of nauty(). * * @configure_input@ **************************************************************************/ #ifndef _NAUTY_H_ /* only process this file once */ #define _NAUTY_H_ /* The parts between the ==== lines are modified by configure when creating nauty.h out of nauty-h.in. If configure is not being used, it is necessary to check they are correct. ====================================================================*/ /* Check whether various headers are available */ #define HAVE_UNISTD_H @header_unistd_h@ /* */ #define HAVE_SYSTYPES_H @header_sys_types_h@ /* */ #define HAVE_STDDEF_H @header_stddef_h@ /* */ #define HAVE_STDLIB_H @header_stdlib_h@ /* */ #define HAVE_STRING_H @header_string_h@ /* */ #define MALLOC_DEC @malloc_dec@ /* 1 = malloc() is declared in stdlib.h, 2 = in malloc.h, 0 = in neither place */ #define HAS_MATH_INF @has_math_inf@ /* INFINITY is defined in math.h or some system header likely to be used */ #define HAS_STDIO_UNLOCK @stdio_nolock@ /* Whether there are getc_unlocked, putc_unlocked,flockfile and funlockfile*/ #define SIZEOF_INT @ac_cv_sizeof_int@ #define SIZEOF_LONG @ac_cv_sizeof_long@ #define SIZEOF_LONG_LONG @ac_cv_sizeof_long_long@ /* 0 if nonexistent */ #define HAVE_CONST @have_const@ /* compiler properly supports const */ /*==================================================================*/ /* The following line must be uncommented for compiling into Magma. */ /* #define NAUTY_IN_MAGMA */ #ifdef NAUTY_IN_MAGMA #include "defs.h" #include "system.h" #include "bs.h" #define OLDEXTDEFS #else #include #define P_(x) x #endif #if defined(__cray) || defined(__cray__) || defined(cray) #define SYS_CRAY /* Cray UNIX, portable or standard C */ #endif #if defined(__unix) || defined(__unix__) || defined(unix) #define SYS_UNIX #endif #if !HAVE_CONST #define const #endif /***************************************************************************** * * * AUTHOR: Brendan D. McKay * * School of Computer Science * * Australian National University * * Canberra, ACT 0200, Australia * * phone: +61 2 6125 3845 fax: +61 2 6125 0010 * * email: bdm@cs.anu.edu.au * * * * Copyright (1984-2010) Brendan McKay. All rights reserved. Permission * * is hereby given for use and/or distribution with the exception of * * sale for profit or application with nontrivial military significance. * * You must not remove this copyright notice, and you must document any * * changes that you make to this program. * * This software is subject to this copyright only, irrespective of * * any copyright attached to any package of which this is a part. * * * * This program is only provided "as is". No responsibility will be taken * * by the author, his employer or his pet rabbit* for any misfortune which * * befalls you because of its use. I don't think it will delete all your * * files, burn down your computer room or turn your children against you, * * but if it does: stiff cheddar. On the other hand, I very much welcome * * bug reports, or at least I would if there were any bugs. * * * RIP, 1989 * * * * If you wish to acknowledge use of this program in published articles, * * please do so by citing the User's Guide: * * * * B. D. McKay, nauty User's Guide (Version 2.4), * http://cs.anu.edu.au/~bdm/nauty/. * * * CHANGE HISTORY * * 10-Nov-87 : final changes for version 1.2 * * 5-Dec-87 : renamed to version 1.3 (no changes to this file) * * 28-Sep-88 : added PC Turbo C support, making version 1.4 * * 23-Mar-89 : changes for version 1.5 : * * - reworked M==1 code * * - defined NAUTYVERSION string * * - made NAUTYH_READ to allow this file to be read twice * * - added optional ANSI function prototypes * * - added validity check for WORDSIZE * * - added new fields to optionblk structure * * - updated DEFAULTOPTIONS to add invariants fields * * - added (set*) cast to definition of GRAPHROW * * - added definition of ALLOCS and FREES * * 25-Mar-89 : - added declaration of new function doref() * * - added UNION macro * * 29-Mar-89 : - reduced the default MAXN for small machines * * - removed OUTOFSPACE (no longer used) * * - added SETDIFF and XOR macros * * 2-Apr-89 : - extended statsblk structure * * 4-Apr-89 : - added IS_* macros * * - added ERRFILE definition * * - replaced statsblk.outofspace by statsblk.errstatus * * 5-Apr-89 : - deleted definition of np2vector (no longer used) * * - introduced EMPTYSET macro * * 12-Apr-89 : - eliminated MARK, UNMARK and ISMARKED (no longer used) * * 18-Apr-89 : - added MTOOBIG and CANONGNIL * * 12-May-89 : - made ISELEM1 and ISELEMENT return 0 or 1 * * 2-Mar-90 : - added EXTPROC macro and used it * * 12-Mar-90 : - added SYS_CRAY, with help from N. Sloane and A. Grosky * * - added dummy groupopts field to optionblk * * - select some ANSI things if __STDC__ exists * * 20-Mar-90 : - changed default MAXN for Macintosh versions * * - created SYS_MACTHINK for Macintosh THINK compiler * * 27-Mar-90 : - split SYS_MSDOS into SYS_PCMS4 and SYS_PCMS5 * * 13-Oct-90 : changes for version 1.6: * * - fix definition of setword for WORDSIZE==64 * * 14-Oct-90 : - added SYS_APOLLO version to avoid compiler bug * * 15-Oct-90 : - improve detection of ANSI conformance * * 17-Oct-90 : - changed temp name in EMPTYSET to avoid A/UX bug * * 16-Apr-91 : changes for version 1.7: * * - made version SYS_PCTURBO use free(), not cfree() * * 2-Sep-91 : - noted that SYS_PCMS5 also works for Quick C * * - moved MULTIPLY to here from nauty.c * * 12-Jun-92 : - changed the top part of this comment * * 27-Aug-92 : - added version SYS_IBMC, thanks to Ivo Duentsch * * 5-Jun-93 : - renamed to version 1.7+, only change in naututil.h * * 29-Jul-93 : changes for version 1.8: * * - fixed error in default 64-bit version of FIRSTBIT * * (not used in any version before ALPHA) * * - installed ALPHA version (thanks to Gordon Royle) * * - defined ALLOCS,FREES for SYS_IBMC * * 3-Sep-93 : - make calloc void* in ALPHA version * * 17-Sep-93 : - renamed to version 1.9, * * changed only dreadnaut.c and nautinv.c * * 24-Feb-94 : changes for version 1.10: * * - added version SYS_AMIGAAZT, thanks to Carsten Saager * * (making 1.9+) * * 19-Apr-95 : - added prototype wrapper for C++, * * thanks to Daniel Huson * * 5-Mar-96 : - added SYS_ALPHA32 version (32-bit setwords on Alpha) * * 13-Jul-96 : changes for version 2.0: * * - added dynamic allocation * * - ERRFILE must be defined * * - added FLIPELEM1 and FLIPELEMENT macros * * 13-Aug-96 : - added SWCHUNK? macros * * - added TAKEBIT macro * * 28-Nov-96 : - include sys/types.h if not ANSI (tentative!) * * 24-Jan-97 : - and stdlib.h if ANSI * * - removed use of cfree() from UNIX variants * * 25-Jan-97 : - changed options.getcanon from boolean to int * * Backwards compatibility is ok, as boolean and int * * are the same. Now getcanon=2 means to get the label * * and not care about the group. Sometimes faster. * * 6-Feb-97 : - Put in #undef for FALSE and TRUE to cope with * * compilers that illegally predefine them. * * - declared nauty_null and nautil_null * * 2-Jul-98 : - declared ALLBITS * * 21-Oct-98 : - allow WORDSIZE==64 using unsigned long long * * - added BIGNAUTY option for really big graphs * * 11-Dec-99 : - made bit, leftbit and bytecount static in each file * * 9-Jan-00 : - declared nauty_check() and nautil_check() * * 12-Feb-00 : - Used #error for compile-time checks * * - Added DYNREALLOC * * 4-Mar-00 : - declared ALLMASK(n) * * 27-May-00 : - declared CONDYNFREE * * 28-May-00 : - declared nautil_freedyn() * * 16-Aug-00 : - added OLDNAUTY and changed canonical labelling * * 16-Nov-00 : - function prototypes are now default and unavoidable * * - removed UPROC, now assume all compilers know void * * - removed nvector, now just int (as it always was) * * - added extra parameter to targetcell() * * - removed old versions which were only to skip around * * bugs that should have been long fixed: * * SYS_APOLLO and SYS_VAXBSD. * * - DEFAULTOPIONS now specifies no output * * - Removed obsolete SYS_MACLSC version * * 21-Apr-01 : - Added code to satisfy compilation into Magma. This * * is activated by defining NAUTY_IN_MAGMA above. * * - The *_null routines no longer exist * * - Default maxinvarlevel is now 1. (This has no effect * * unless an invariant is specified.) * * - Now labelorg has a concrete declaration in nautil.c * * and EXTDEFS is not needed * * 5-May-01 : - NILFUNCTION, NILSET, NILGRAPH now obsolete. Use NULL. * * 11-Sep-01 : - setword is unsigned int in the event that UINT_MAX * * is defined and indicates it is big enough * * 17-Oct-01 : - major rewrite for 2.1. SYS_* variables gone! * * Some modernity assumed, eg size_t * * 8-Aug-02 : - removed MAKEEMPTY (use EMPTYSET instead) * * - deleted OLDNAUTY everywhere * * 27-Aug-02 : - converted to use autoconf. Now the original of this * * file is nauty-h.in. Run configure to make nauty.h. * * 20-Dec-02 : - increased INFINITY * * some reorganization to please Magma * * - declared nauty_freedyn() * * 17-Nov-03 : - renamed INFINITY to NAUTY_INFINITY * * 29-May-04 : - added definition of SETWORD_FORMAT * * 14-Sep-04 : - extended prototypes even to recursive functions * * 16-Oct-04 : - added DEFAULTOPTIONS_GRAPH * * 24-Oct-04 : Starting 2.3 * * - remove register declarations as modern compilers * * tend to find them a nuisance * * - Don't define the obsolete symbol INFINITY if it is * * defined already * * 17-Nov-04 : - make 6 counters in statsblk unsigned long * * 17-Jan-04 : - add init() and cleanup() to dispatchvec * * 12-Nov-05 : - Changed NAUTY_INFINITY to 2^30+2 in BIGNAUTY case * * 22-Nov-06 : Starting 2.4 * * - removed usertcellproc from options * * changed bestcell to targetcell in dispatch vector * * declare targetcell and maketargetcell * * 29-Nov-06 : - add extraoptions to optionblk * * - add declarations of extra_autom and extra_level * * 10-Dec-06 : - BIGNAUTY is gone! Now permutation=shortish=int. * * NAUTY_INFINITY only depends on whether sizeof(int)=2. * * 27-Jun-08 : - define nauty_counter and LONG_LONG_COUNTERS * * 30-Jun-08 : - declare version 2.4 * * 14-Jun-10 : Maintenance release 2.4r1 * * 7-Aug-10 : Maintenance release 2.4r2 * * * * @configure_input@ * * *****************************************************************************/ /***************************************************************************** * * * 16-bit, 32-bit and 64-bit versions can be selected by defining WORDSIZE. * * The largest graph that can be handled has MAXN vertices. * * Both WORDSIZE and MAXN can be defined on the command line. * * WORDSIZE must be 16, 32 or 64; MAXN must be <= NAUTY_INFINITY-2; * * * * With a very slight loss of efficiency (depending on platform), nauty * * can be compiled to dynamically allocate arrays. Predefine MAXN=0 to * * achieve this effect, which is default behaviour from version 2.0. * * In that case, graphs of size up to NAUTY_INFINITY-2 can be handled * * if the the memory is available. * * * * If only very small graphs need to be processed, use MAXN<=WORDSIZE * * since this causes substantial code optimizations. * * * * Conventions and Assumptions: * * * * A 'setword' is the chunk of memory that is occupied by one part of * * a set. This is assumed to be >= WORDSIZE bits in size. * * * * The rightmost (loworder) WORDSIZE bits of setwords are numbered * * 0..WORDSIZE-1, left to right. It is necessary that the 2^WORDSIZE * * setwords with the other bits zero are totally ordered under <,=,>. * * This needs care on a 1's-complement machine. * * * * The int variables m and n have consistent meanings throughout. * * Graphs have n vertices always, and sets have m setwords always. * * * * A 'set' consists of m contiguous setwords, whose bits are numbered * * 0,1,2,... from left (high-order) to right (low-order), using only * * the rightmost WORDSIZE bits of each setword. It is used to * * represent a subset of {0,1,...,n-1} in the usual way - bit number x * * is 1 iff x is in the subset. Bits numbered n or greater, and * * unnumbered bits, are assumed permanently zero. * * * * A 'graph' consists of n contiguous sets. The i-th set represents * * the vertices adjacent to vertex i, for i = 0,1,...,n-1. * * * * A 'permutation' is an array of n ints repesenting a permutation of * * the set {0,1,...,n-1}. The value of the i-th entry is the number to * * which i is mapped. * * * * If g is a graph and p is a permutation, then g^p is the graph in * * which vertex i is adjacent to vertex j iff vertex p[i] is adjacent * * to vertex p[j] in g. * * * * A partition nest is represented by a pair (lab,ptn), where lab and ptn * * are int arrays. The "partition at level x" is the partition whose * * cells are {lab[i],lab[i+1],...,lab[j]}, where [i,j] is a maximal * * subinterval of [0,n-1] such that ptn[k] > x for i <= k < j and * * ptn[j] <= x. The partition at level 0 is given to nauty by the user. * * This is refined for the root of the tree, which has level 1. * * * *****************************************************************************/ #define NAUTYVERSIONID 2400 /* 1000 times the version number */ #define NAUTYREQUIRED 2400 /* Minimum compatible version */ #ifndef NAUTY_IN_MAGMA #if HAVE_SYSTYPES_H #include #endif #if HAVE_UNISTD_H #include #endif #if HAVE_STDDEF_H #include #endif #if HAVE_STDLIB_H #include #endif #if HAVE_STRING_H #include #else #include #endif #endif /* WORDSIZE is the number of set elements per setword (16, 32 or 64). Starting at version 2.2, WORDSIZE and setword are defined as follows: If WORDSIZE is so far undefined, use 32 unless longs have more than 32 bits, in which case use 64. Define setword thus: WORDSIZE==16 : unsigned short WORDSIZE==32 : unsigned int unless it is too small, in which case unsigned long WORDSIZE==64 : the first of unsigned int, unsigned long, unsigned long long, which is large enough. */ #ifdef NAUTY_IN_MAGMA #undef WORDSIZE #define WORDSIZE WORDBITS #endif #ifdef WORDSIZE #if (WORDSIZE != 16) && (WORDSIZE != 32) && (WORDSIZE != 64) #error "WORDSIZE must be 16, 32 or 64" #endif #else /* WORDSIZE undefined */ #if SIZEOF_LONG>4 #define WORDSIZE 64 #else #define WORDSIZE 32 #endif #endif /* WORDSIZE */ #ifdef NAUTY_IN_MAGMA typedef t_uint setword; #define SETWORD_INT /* Don't assume this is correct in Magma. */ #else /* NAUTY_IN_MAGMA */ #if WORDSIZE==16 typedef unsigned short setword; #define SETWORD_SHORT #endif #if WORDSIZE==32 #if SIZEOF_INT>=4 typedef unsigned int setword; #define SETWORD_INT #else typedef unsigned long setword; #define SETWORD_LONG #endif #endif #if WORDSIZE==64 #if SIZEOF_INT>=8 typedef unsigned int setword; #define SETWORD_INT #else #if SIZEOF_LONG>=8 typedef unsigned long setword; #define SETWORD_LONG #else typedef unsigned long long setword; #define SETWORD_LONGLONG #endif #endif #endif #endif /* NAUTY_IN_MAGMA else */ #if SIZEOF_LONG_LONG>=8 && SIZEOF_LONG==4 typedef unsigned long long nauty_counter; #define LONG_LONG_COUNTERS 1 #else typedef unsigned long nauty_counter; #define LONG_LONG_COUNTERS 0 #endif #if WORDSIZE==16 #define NAUTYVERSION "2.4 (16 bits)" #endif #if WORDSIZE==32 #define NAUTYVERSION "2.4 (32 bits)" #endif #if WORDSIZE==64 #define NAUTYVERSION "2.4 (64 bits)" #endif #ifndef MAXN /* maximum allowed n value; use 0 for dynamic sizing. */ #define MAXN 0 #define MAXM 0 #else #define MAXM ((MAXN+WORDSIZE-1)/WORDSIZE) /* max setwords in a set */ #endif /* MAXN */ /* Starting at version 2.2, set operations work for all set sizes unless ONE_WORD_SETS is defined. In the latter case, if MAXM=1, set ops work only for single-setword sets. In any case, macro versions ending with 1 work for single-setword sets and versions ending with 0 work for all set sizes. */ #if WORDSIZE==16 #define SETWD(pos) ((pos)>>4) /* number of setword containing bit pos */ #define SETBT(pos) ((pos)&0xF) /* position within setword of bit pos */ #define TIMESWORDSIZE(w) ((w)<<4) #endif #if WORDSIZE==32 #define SETWD(pos) ((pos)>>5) #define SETBT(pos) ((pos)&0x1F) #define TIMESWORDSIZE(w) ((w)<<5) #endif #if WORDSIZE==64 #define SETWD(pos) ((pos)>>6) #define SETBT(pos) ((pos)&0x3F) #define TIMESWORDSIZE(w) ((w)<<6) /* w*WORDSIZE */ #endif #ifdef NAUTY_IN_MAGMA #define BITT bs_bit #else #define BITT bit #endif #define ADDELEMENT1(setadd,pos) (*(setadd) |= BITT[pos]) #define DELELEMENT1(setadd,pos) (*(setadd) &= ~BITT[pos]) #define FLIPELEMENT1(setadd,pos) (*(setadd) ^= BITT[pos]) #define ISELEMENT1(setadd,pos) ((*(setadd) & BITT[pos]) != 0) #define EMPTYSET1(setadd,m) *(setadd) = 0; #define GRAPHROW1(g,v,m) ((set*)(g) + (v)) #define ADDELEMENT0(setadd,pos) ((setadd)[SETWD(pos)] |= BITT[SETBT(pos)]) #define DELELEMENT0(setadd,pos) ((setadd)[SETWD(pos)] &= ~BITT[SETBT(pos)]) #define FLIPELEMENT0(setadd,pos) ((setadd)[SETWD(pos)] ^= BITT[SETBT(pos)]) #define ISELEMENT0(setadd,pos) (((setadd)[SETWD(pos)] & BITT[SETBT(pos)]) != 0) #define EMPTYSET0(setadd,m) \ {setword *es; \ for (es = (setword*)(setadd)+(m); --es >= (setword*)(setadd);) *es=0;} #define GRAPHROW0(g,v,m) ((set*)(g) + (long)(v)*(long)(m)) #if (MAXM==1) && defined(ONE_WORD_SETS) #define ADDELEMENT ADDELEMENT1 #define DELELEMENT DELELEMENT1 #define FLIPELEMENT FLIPELEMENT1 #define ISELEMENT ISELEMENT1 #define EMPTYSET EMPTYSET1 #define GRAPHROW GRAPHROW1 #else #define ADDELEMENT ADDELEMENT0 #define DELELEMENT DELELEMENT0 #define FLIPELEMENT FLIPELEMENT0 #define ISELEMENT ISELEMENT0 #define EMPTYSET EMPTYSET0 #define GRAPHROW GRAPHROW0 #endif #ifdef NAUTY_IN_MAGMA #undef EMPTYSET #define EMPTYSET(setadd,m) {t_int _i; bsp_makeempty(setadd,m,_i);} #endif #define NOTSUBSET(word1,word2) ((word1) & ~(word2)) /* test if the 1-bits in setword word1 do not form a subset of those in word2 */ #define INTERSECT(word1,word2) ((word1) &= (word2)) /* AND word2 into word1 */ #define UNION(word1,word2) ((word1) |= (word2)) /* OR word2 into word1 */ #define SETDIFF(word1,word2) ((word1) &= ~(word2)) /* - word2 into word1 */ #define XOR(word1,word2) ((word1) ^= (word2)) /* XOR word2 into word1 */ #define ZAPBIT(word,x) ((word) &= ~BITT[x]) /* delete bit x in setword */ #define TAKEBIT(iw,w) {iw = FIRSTBIT(w); w ^= BITT[iw];} #ifdef SETWORD_LONGLONG #define MSK3232 0xFFFFFFFF00000000ULL #define MSK1648 0xFFFF000000000000ULL #define MSK0856 0xFF00000000000000ULL #define MSK1632 0x0000FFFF00000000ULL #define MSK0840 0xFF0000000000ULL #define MSK1616 0xFFFF0000ULL #define MSK0824 0xFF000000ULL #define MSK0808 0xFF00ULL #define MSK63C 0x7FFFFFFFFFFFFFFFULL #define MSK31C 0x7FFFFFFFULL #define MSK15C 0x7FFFULL #define MSK64 0xFFFFFFFFFFFFFFFFULL #define MSK32 0xFFFFFFFFULL #define MSK16 0xFFFFULL #endif #ifdef SETWORD_LONG #define MSK3232 0xFFFFFFFF00000000UL #define MSK1648 0xFFFF000000000000UL #define MSK0856 0xFF00000000000000UL #define MSK1632 0x0000FFFF00000000UL #define MSK0840 0xFF0000000000UL #define MSK1616 0xFFFF0000UL #define MSK0824 0xFF000000UL #define MSK0808 0xFF00UL #define MSK63C 0x7FFFFFFFFFFFFFFFUL #define MSK31C 0x7FFFFFFFUL #define MSK15C 0x7FFFUL #define MSK64 0xFFFFFFFFFFFFFFFFUL #define MSK32 0xFFFFFFFFUL #define MSK16 0xFFFFUL #endif #if defined(SETWORD_INT) || defined(SETWORD_SHORT) #define MSK3232 0xFFFFFFFF00000000U #define MSK1648 0xFFFF000000000000U #define MSK0856 0xFF00000000000000U #define MSK1632 0x0000FFFF00000000U #define MSK0840 0xFF0000000000U #define MSK1616 0xFFFF0000U #define MSK0824 0xFF000000U #define MSK0808 0xFF00U #define MSK63C 0x7FFFFFFFFFFFFFFFU #define MSK31C 0x7FFFFFFFU #define MSK15C 0x7FFFU #define MSK64 0xFFFFFFFFFFFFFFFFU #define MSK32 0xFFFFFFFFU #define MSK16 0xFFFFU #endif #if defined(SETWORD_LONGLONG) #if WORDSIZE==16 #define SETWORD_FORMAT "%04llx" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08llx" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16llx" #endif #endif #if defined(SETWORD_LONG) #if WORDSIZE==16 #define SETWORD_FORMAT "%04lx" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08lx" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16lx" #endif #endif #if defined(SETWORD_INT) #if WORDSIZE==16 #define SETWORD_FORMAT "%04x" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08x" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16x" #endif #endif #if defined(SETWORD_SHORT) #if WORDSIZE==16 #define SETWORD_FORMAT "%04hx" #endif #if WORDSIZE==32 #define SETWORD_FORMAT "%08hx" #endif #if WORDSIZE==64 #define SETWORD_FORMAT "%16hx" #endif #endif /* POPCOUNT(x) = number of 1-bits in a setword x FIRSTBIT(x) = number of first 1-bit in non-zero setword (0..WORDSIZE-1) BITMASK(x) = setword whose rightmost WORDSIZE-x-1 (numbered) bits are 1 and the rest 0 (0 <= x < WORDSIZE) (I.e., bits 0..x are unselected and the rest selected.) ALLBITS = all (numbered) bits in a setword */ #if WORDSIZE==64 #define POPCOUNT(x) (bytecount[(x)>>56 & 0xFF] + bytecount[(x)>>48 & 0xFF] \ + bytecount[(x)>>40 & 0xFF] + bytecount[(x)>>32 & 0xFF] \ + bytecount[(x)>>24 & 0xFF] + bytecount[(x)>>16 & 0xFF] \ + bytecount[(x)>>8 & 0xFF] + bytecount[(x) & 0xFF]) #define FIRSTBIT(x) ((x) & MSK3232 ? \ (x) & MSK1648 ? \ (x) & MSK0856 ? \ 0+leftbit[((x)>>56) & 0xFF] : \ 8+leftbit[(x)>>48] \ : (x) & MSK0840 ? \ 16+leftbit[(x)>>40] : \ 24+leftbit[(x)>>32] \ : (x) & MSK1616 ? \ (x) & MSK0824 ? \ 32+leftbit[(x)>>24] : \ 40+leftbit[(x)>>16] \ : (x) & MSK0808 ? \ 48+leftbit[(x)>>8] : \ 56+leftbit[x]) #define BITMASK(x) (MSK63C >> (x)) #define ALLBITS MSK64 #define SWCHUNK0(w) ((long)((w)>>48)&0xFFFFL) #define SWCHUNK1(w) ((long)((w)>>32)&0xFFFFL) #define SWCHUNK2(w) ((long)((w)>>16)&0xFFFFL) #define SWCHUNK3(w) ((long)(w)&0xFFFFL) #endif #if WORDSIZE==32 #define POPCOUNT(x) (bytecount[(x)>>24 & 0xFF] + bytecount[(x)>>16 & 0xFF] \ + bytecount[(x)>>8 & 0xFF] + bytecount[(x) & 0xFF]) #define FIRSTBIT(x) ((x) & MSK1616 ? ((x) & MSK0824 ? \ leftbit[((x)>>24) & 0xFF] : 8+leftbit[(x)>>16]) \ : ((x) & MSK0808 ? 16+leftbit[(x)>>8] : 24+leftbit[x])) #define BITMASK(x) (MSK31C >> (x)) #define ALLBITS MSK32 #define SWCHUNK0(w) ((long)((w)>>16)&0xFFFFL) #define SWCHUNK1(w) ((long)(w)&0xFFFFL) #endif #if WORDSIZE==16 #define POPCOUNT(x) (bytecount[(x)>>8 & 0xFF] + bytecount[(x) & 0xFF]) #define FIRSTBIT(x) ((x) & MSK0808 ? leftbit[((x)>>8) & 0xFF] : 8+leftbit[x]) #define BITMASK(x) (MSK15C >> (x)) #define ALLBITS MSK16 #define SWCHUNK0(w) ((long)(w)&0xFFFFL) #endif #ifdef SYS_CRAY #undef POPCOUNT #undef FIRSTBIT #undef BITMASK #define POPCOUNT(x) _popcnt(x) #define FIRSTBIT(x) _leadz(x) #define BITMASK(x) _mask(65+(x)) #endif #ifdef NAUTY_IN_MAGMA #undef POPCOUNT #undef FIRSTBIT #undef BITMASK #define POPCOUNT(x) bs_popcount(x) #define FIRSTBIT(x) bs_firstbit(x) #define BITMASK(x) bs_bitmask(x) #endif #define ALLMASK(n) ((n)?~BITMASK((n)-1):(setword)0) /* First n bits */ /* various constants: */ #undef FALSE #undef TRUE #define FALSE 0 #define TRUE 1 #if SIZEOF_INT>=4 #define NAUTY_INFINITY 0x40000002 #else #define NAUTY_INFINITY 0x7FFF #endif typedef int shortish; /* For backward compatibility: */ #if !HAS_MATH_INF && !defined(INFINITY) #define INFINITY NAUTY_INFINITY #endif #if MAXN > NAUTY_INFINITY-2 #error MAXN must be at most NAUTY_INFINITY-2 #endif /* typedefs for sets, graphs, permutations, etc.: */ typedef int boolean; /* boolean MUST be the same as int */ #define UPROC void /* obsolete */ typedef setword set,graph; typedef int nvector,np2vector; /* obsolete */ typedef shortish permutation; #ifdef NAUTY_IN_MAGMA typedef graph nauty_graph; typedef set nauty_set; #endif typedef struct { double grpsize1; /* size of group is */ int grpsize2; /* grpsize1 * 10^grpsize2 */ #define groupsize1 grpsize1 /* for backwards compatibility */ #define groupsize2 grpsize2 int numorbits; /* number of orbits in group */ int numgenerators; /* number of generators found */ int errstatus; /* if non-zero : an error code */ #define outofspace errstatus; /* for backwards compatibility */ unsigned long numnodes; /* total number of nodes */ unsigned long numbadleaves; /* number of leaves of no use */ int maxlevel; /* maximum depth of search */ unsigned long tctotal; /* total size of all target cells */ unsigned long canupdates; /* number of updates of best label */ unsigned long invapplics; /* number of applications of invarproc */ unsigned long invsuccesses; /* number of successful uses of invarproc() */ int invarsuclevel; /* least level where invarproc worked */ } statsblk; /* codes for errstatus field (see nauty.c for more accurate descriptions): */ #define NTOOBIG 1 /* n > MAXN or n > WORDSIZE*m */ #define MTOOBIG 2 /* m > MAXM */ #define CANONGNIL 3 /* canong = NULL, but getcanon = TRUE */ /* manipulation of real approximation to group size */ #define MULTIPLY(s1,s2,i) if ((s1 *= i) >= 1e10) {s1 /= 1e10; s2 += 10;} struct optionstruct; /* incomplete definition */ typedef struct { boolean (*isautom) /* test for automorphism */ (graph*,permutation*,boolean,int,int); int (*testcanlab) /* test for better labelling */ (graph*,graph*,int*,int*,int,int); void (*updatecan) /* update canonical object */ (graph*,graph*,permutation*,int,int,int); void (*refine) /* refine partition */ (graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); void (*refine1) /* refine partition, MAXM==1 */ (graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); boolean (*cheapautom) /* test for easy automorphism */ (int*,int,boolean,int); int (*targetcell) /* decide which cell to split */ (graph*,int*,int*,int,int,boolean,int,int,int); void (*freedyn)(void); /* free dynamic memory */ void (*check) /* check compilation parameters */ (int,int,int,int); void (*init)(graph*,graph**,graph*,graph**,int*,int*,set*, struct optionstruct*,int*,int,int); void (*cleanup)(graph*,graph**,graph*,graph**,int*,int*, struct optionstruct*,statsblk*,int,int); } dispatchvec; typedef struct optionstruct { int getcanon; /* make canong and canonlab? */ #define LABELONLY 2 /* new value UNIMPLEMENTED */ boolean digraph; /* multiple edges or loops? */ boolean writeautoms; /* write automorphisms? */ boolean writemarkers; /* write stats on pts fixed, etc.? */ boolean defaultptn; /* set lab,ptn,active for single cell? */ boolean cartesian; /* use cartesian rep for writing automs? */ int linelength; /* max chars/line (excl. '\n') for output */ FILE *outfile; /* file for output, if any */ void (*userrefproc) /* replacement for usual refine procedure */ (graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); void (*userautomproc) /* procedure called for each automorphism */ (int,permutation*,int*,int,int,int); void (*userlevelproc) /* procedure called for each level */ (int*,int*,int,int*,statsblk*,int,int,int,int,int,int); void (*usernodeproc) /* procedure called for each node */ (graph*,int*,int*,int,int,int,int,int,int); void (*invarproc) /* procedure to compute vertex-invariant */ (graph*,int*,int*,int,int,int,permutation*,int,boolean,int,int); int tc_level; /* max level for smart target cell choosing */ int mininvarlevel; /* min level for invariant computation */ int maxinvarlevel; /* max level for invariant computation */ int invararg; /* value passed to (*invarproc)() */ dispatchvec *dispatch; /* vector of object-specific routines */ void *extra_options; /* arbitrary extra options */ #ifdef NAUTY_IN_MAGMA boolean print_stats; /* CAYLEY specfic - GYM Sep 1990 */ char *invarprocname; /* Magma - no longer global sjc 1994 */ int lab_h; /* Magma - no longer global sjc 1994 */ int ptn_h; /* Magma - no longer global sjc 1994 */ int orbitset_h; /* Magma - no longer global sjc 1994 */ #endif } optionblk; #ifndef CONSOLWIDTH #define CONSOLWIDTH 78 #endif /* The following are obsolete. Just use NULL. */ #define NILFUNCTION ((void(*)())NULL) /* nil pointer to user-function */ #define NILSET ((set*)NULL) /* nil pointer to set */ #define NILGRAPH ((graph*)NULL) /* nil pointer to graph */ #define DEFAULTOPTIONS_GRAPH(options) optionblk options = \ {0,FALSE,FALSE,FALSE,TRUE,FALSE,CONSOLWIDTH, \ NULL,NULL,NULL,NULL,NULL,NULL,100,0,1,0,&dispatch_graph,NULL} #ifndef DEFAULTOPTIONS #define DEFAULTOPTIONS DEFAULTOPTIONS_GRAPH #endif #ifdef NAUTY_IN_MAGMA #define PUTC(c,f) io_putchar(c) #else #ifdef IS_JAVA extern void javastream(FILE* f,char c); #define PUTC(c,f) javastream(f,c) #else #define PUTC(c,f) putc(c,f) #endif #endif /* We hope that malloc, free, realloc are declared either in or . Otherwise we will define them. We also assume that size_t has been defined by the time we get to define malloc(). */ #ifndef NAUTY_IN_MAGMA #if MALLOC_DEC==2 #include #endif #if MALLOC_DEC==0 extern void *malloc(size_t); extern void *realloc(void*,size_t); extern void free(void*); #endif #endif /* ALLOCS(x,y) should return a pointer (any pointer type) to x*y units of new storage, not necessarily initialised. A "unit" of storage is defined by the sizeof operator. x and y are integer values of type int or larger, but x*y may well be too large for an int. The macro should cast to the correct type for the call. On failure, ALLOCS(x,y) should return a NULL pointer. FREES(p) should free storage previously allocated by ALLOCS, where p is the value that ALLOCS returned. */ #ifdef NAUTY_IN_MAGMA #define ALLOCS(x,y) mem_malloc((size_t)(x)*(size_t)(y)) #define REALLOCS(p,x) mem_realloc(p,(size_t)(x)) #define FREES(p) mem_free(p) #else #define ALLOCS(x,y) malloc((size_t)(x)*(size_t)(y)) #define REALLOCS(p,x) realloc(p,(size_t)(x)) #define FREES(p) free(p) #endif /* The following macros are used by nauty if MAXN=0. They dynamically allocate arrays of size dependent on m or n. For each array there should be two static variables: type *name; size_t name_sz; "name" will hold a pointer to an allocated array. "name_sz" will hold the size of the allocated array in units of sizeof(type). DYNALLSTAT declares both variables and initialises name_sz=0. DYNALLOC1 and DYNALLOC2 test if there is enough space allocated, and if not free the existing space and allocate a bigger space. The allocated space is not initialised. In the case of DYNALLOC1, the space is allocated using ALLOCS(sz,sizeof(type)). In the case of DYNALLOC2, the space is allocated using ALLOCS(sz1,sz2*sizeof(type)). DYNREALLOC is like DYNALLOC1 except that the old contents are copied into the new space. realloc() is assumed. This is not currently used by nauty or dreadnaut. DYNFREE frees any allocated array and sets name_sz back to 0. CONDYNFREE does the same, but only if name_sz exceeds some limit. */ #define DYNALLSTAT(type,name,name_sz) \ static type *name; static size_t name_sz=0 #define DYNALLOC1(type,name,name_sz,sz,msg) \ if ((size_t)(sz) > name_sz) \ { if (name_sz) FREES(name); name_sz = (sz); \ if ((name=(type*)ALLOCS(sz,sizeof(type))) == NULL) {alloc_error(msg);}} #define DYNALLOC2(type,name,name_sz,sz1,sz2,msg) \ if ((size_t)(sz1)*(size_t)(sz2) > name_sz) \ { if (name_sz) FREES(name); name_sz = (size_t)(sz1)*(size_t)(sz2); \ if ((name=(type*)ALLOCS((sz1),(sz2)*sizeof(type))) == NULL) \ {alloc_error(msg);}} #define DYNREALLOC(type,name,name_sz,sz,msg) \ {if ((size_t)(sz) > name_sz) \ { if ((name = (type*)REALLOCS(name,(sz)*sizeof(type))) == NULL) \ {alloc_error(msg);} else name_sz = (sz);}} #define DYNFREE(name,name_sz) if (name_sz) {FREES(name); name_sz = 0;} #define CONDYNFREE(name,name_sz,minsz) \ if (name_sz > (size_t)(minsz)) {FREES(name); name_sz = 0;} /* File to write error messages to (used as first argument to fprintf()). */ #define ERRFILE stderr /* Don't use OLDEXTDEFS, it is only still here for Magma. */ #ifdef OLDEXTDEFS #define EXTDEF_CLASS #ifdef EXTDEFS #define EXTDEF_TYPE 1 #else #define EXTDEF_TYPE 2 #endif #else #define EXTDEF_CLASS static #define EXTDEF_TYPE 2 #endif extern int labelorg; /* Declared in nautil.c */ #ifndef NAUTY_IN_MAGMA /* Things equivalent to bit, bytecount, leftbit are defined in bs.h for Magma. */ #if EXTDEF_TYPE==1 extern setword bit[]; extern int bytecount[]; extern int leftbit[]; #else /* array giving setwords with single 1-bit */ #if WORDSIZE==64 #ifdef SETWORD_LONGLONG EXTDEF_CLASS setword bit[] = {01000000000000000000000LL,0400000000000000000000LL, 0200000000000000000000LL,0100000000000000000000LL, 040000000000000000000LL,020000000000000000000LL, 010000000000000000000LL,04000000000000000000LL, 02000000000000000000LL,01000000000000000000LL, 0400000000000000000LL,0200000000000000000LL, 0100000000000000000LL,040000000000000000LL, 020000000000000000LL,010000000000000000LL, 04000000000000000LL,02000000000000000LL, 01000000000000000LL,0400000000000000LL,0200000000000000LL, 0100000000000000LL,040000000000000LL,020000000000000LL, 010000000000000LL,04000000000000LL,02000000000000LL, 01000000000000LL,0400000000000LL,0200000000000LL, 0100000000000LL,040000000000LL,020000000000LL,010000000000LL, 04000000000LL,02000000000LL,01000000000LL,0400000000LL, 0200000000LL,0100000000LL,040000000LL,020000000LL, 010000000LL,04000000LL,02000000LL,01000000LL,0400000LL, 0200000LL,0100000LL,040000LL,020000LL,010000LL,04000LL, 02000LL,01000LL,0400LL,0200LL,0100LL,040LL,020LL,010LL, 04LL,02LL,01LL}; #else EXTDEF_CLASS setword bit[] = {01000000000000000000000,0400000000000000000000, 0200000000000000000000,0100000000000000000000, 040000000000000000000,020000000000000000000, 010000000000000000000,04000000000000000000, 02000000000000000000,01000000000000000000, 0400000000000000000,0200000000000000000, 0100000000000000000,040000000000000000,020000000000000000, 010000000000000000,04000000000000000,02000000000000000, 01000000000000000,0400000000000000,0200000000000000, 0100000000000000,040000000000000,020000000000000, 010000000000000,04000000000000,02000000000000, 01000000000000,0400000000000,0200000000000,0100000000000, 040000000000,020000000000,010000000000,04000000000, 02000000000,01000000000,0400000000,0200000000,0100000000, 040000000,020000000,010000000,04000000,02000000,01000000, 0400000,0200000,0100000,040000,020000,010000,04000, 02000,01000,0400,0200,0100,040,020,010,04,02,01}; #endif #endif #if WORDSIZE==32 EXTDEF_CLASS setword bit[] = {020000000000,010000000000,04000000000,02000000000, 01000000000,0400000000,0200000000,0100000000,040000000, 020000000,010000000,04000000,02000000,01000000,0400000, 0200000,0100000,040000,020000,010000,04000,02000,01000, 0400,0200,0100,040,020,010,04,02,01}; #endif #if WORDSIZE==16 EXTDEF_CLASS setword bit[] = {0100000,040000,020000,010000,04000,02000,01000,0400,0200, 0100,040,020,010,04,02,01}; #endif /* array giving number of 1-bits in bytes valued 0..255: */ EXTDEF_CLASS int bytecount[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8}; /* array giving position (1..7) of high-order 1-bit in byte: */ EXTDEF_CLASS int leftbit[] = {8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; #endif /* EXTDEFS */ #endif /* not NAUTY_IN_MAGMA */ #define ANSIPROT 1 #define EXTPROC(func,args) extern func args; /* obsolete */ /* The following is for C++ programs that read nauty.h. Compile nauty itself using C, not C++. */ #ifdef __cplusplus extern "C" { #endif extern void alloc_error(char*); extern void breakout(int*,int*,int,int,int,set*,int); extern boolean cheapautom(int*,int,boolean,int); extern void doref(graph*,int*,int*,int,int*,int*,permutation*,set*,int*, void(*)(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int), void(*)(graph*,int*,int*,int,int,int,permutation*,int,boolean,int,int), int,int,int,boolean,int,int); extern void extra_autom(permutation*,int); extern void extra_level(int,int*,int*,int,int,int,int,int,int); extern boolean isautom(graph*,permutation*,boolean,int,int); extern dispatchvec dispatch_graph; extern int itos(int,char*); extern void fmperm(permutation*,set*,set*,int,int); extern void fmptn(int*,int*,int,set*,set*,int,int); extern void longprune(set*,set*,set*,set*,int); extern void nauty(graph*,int*,int*,set*,int*,optionblk*, statsblk*,set*,int,int,int,graph*); extern void maketargetcell(graph*,int*,int*,int,set*,int*,int*,int,boolean, int,int (*)(graph*,int*,int*,int,int,boolean,int,int,int),int,int); extern int nextelement(set*,int,int); extern int orbjoin(int*,permutation*,int); extern void permset(set*,set*,int,permutation*); extern void putstring(FILE*,char*); extern void refine(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); extern void refine1(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); extern void shortprune(set*,set*,int); extern int targetcell(graph*,int*,int*,int,int,boolean,int,int,int); extern int testcanlab(graph*,graph*,int*,int*,int,int); extern void updatecan(graph*,graph*,permutation*,int,int,int); extern void writeperm(FILE*,permutation*,boolean,int,int); extern void nauty_freedyn(void); extern void nauty_check(int,int,int,int); extern void naugraph_check(int,int,int,int); extern void nautil_check(int,int,int,int); extern void nautil_freedyn(void); extern void naugraph_freedyn(void); #ifdef __cplusplus } #endif #endif /* _NAUTY_H_ */ nauty24r2/deledgeg.c0000600000604200001440000001044411274163463013216 0ustar bdmusers/* deledgeg.c version 1.2; B D McKay, March 2009. */ #define USAGE "deledgeg [-lq] [-d#] [infile [outfile]]" #define HELPTEXT \ " For each edge e, output G-e\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -l Canonically label outputs\n\ -d# Specify a lower bound on the minimum degree of the output\n\ -q Suppress auxiliary information\n" /*************************************************************************/ #include "gtools.h" /**************************************************************************/ int main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile,*outfile; boolean badargs,dolabel,quiet,dswitch; int i,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; double t; #if MAXN graph h[MAXN*MAXM]; int deg[MAXN]; #else DYNALLSTAT(graph,h,h_sz); DYNALLSTAT(int,deg,deg_sz); #endif HELP; infilename = outfilename = NULL; badargs = FALSE; dswitch = dolabel = quiet = FALSE; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('l',dolabel) else SWBOOLEAN('q',quiet) else SWINT('d',dswitch,mindeg,">E deledgeg -d") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!quiet) { fprintf(stderr,">A deledgeg"); if (dolabel) fprintf(stderr," -l"); if (dswitch) fprintf(stderr," -d%d",mindeg); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (codetype&HAS_HEADER) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } if (!dswitch) mindeg = 0; if (dolabel) nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); nin = nout = 0; t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; #if !MAXN 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; } if (actmindeg < mindeg) continue; for (v = 0, gv = g; v < n; ++v, gv += m) { if (deg[v] <= mindeg) continue; for (w = v; (w = nextelement(gv,m,w)) >= 0; ) { if (deg[w] <= mindeg) continue; gw = GRAPHROW(g,w,m); DELELEMENT(gv,w); DELELEMENT(gw,v); gq = g; if (dolabel) { #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"deledgeg"); #endif fcanonise(g,m,n,h,NULL,FALSE); /* FIXME (loops) */ gq = h; } if (outcode == SPARSE6) writes6(outfile,gq,m,n); else writeg6(outfile,gq,m,n); ++nout; ADDELEMENT(gv,w); ADDELEMENT(gw,v); } } FREES(g); } t = CPUTIME - t; #if LONG_LONG_COUNTERS if (!quiet) fprintf(stderr, ">Z %lld graphs read from %s, %lld written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,t); #else if (!quiet) fprintf(stderr, ">Z %ld graphs read from %s, %ld written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,t); #endif exit(0); } nauty24r2/checks6.c0000600000604200001440000001106411405400216012765 0ustar bdmusers/* checks6.c; May 2005 */ #define USAGE "checks6 [-p#:#w] [infile [outfile]]" #define HELPTEXT \ " Check a file of graphs, optionally write corrected version\n\ \n\ -p# -p#:# \n\ Specify range of input lines (first is 1)\n\ \n\ -w Write corrected graphs (default is not to write)\n\ A header is written if there is one in the input.\n" /***********************************************************************/ #include "gtools.h" /***********************************************************************/ static boolean seemsbad(char *s) /* Check graph string for apparent problem, if so, correct it */ { int i,j,k,m,n; char *p,x,pq; set *gj; long ii; int r,rr,topbit,nb,lastj; graph g[16]; if (s[0] != ':') return FALSE; /* not sparse6 */ n = graphsize(s); if (n != 2 && n != 4 && n != 8 && n != 16) return FALSE; m = 1; stringtograph(s,g,m); if (g[n-1] != bit[n-1]) return FALSE; if (g[n-2] == 0) return FALSE; g[n-1] = 0; p = s+2; for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} topbit = 1 << (nb-1); k = 6; x = 0; lastj = 0; for (j = 0; j < n; ++j) { gj = GRAPHROW(g,j,m); for (i = 0; i <= j; ++i) { if (ISELEMENT(gj,i)) { if (j == lastj) { x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } else { x = (x << 1) | 1; if (--k == 0) { p++; k = 6; x = 0; } if (j > lastj+1) { for (r = 0, rr = j; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } lastj = j; } for (r = 0, rr = i; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } } } } if (k != 6) { if (k >= nb+1 && lastj == n-2 && n == (1< 2) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE, pswitch ? pval1 : 1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (wswitch && (codetype&HAS_HEADER)) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } nerr = nin = 0; if (!pswitch || pval2 == NOLIMIT) maxin = NOLIMIT; else if (pval1 < 1) maxin = pval2; else maxin = pval2 - pval1 + 1; while (nin < maxin || maxin == NOLIMIT) { if ((s = gtools_getline(infile)) == NULL) break; ++nin; if (seemsbad(s)) ++nerr; if (wswitch) writeline(outfile,s); } fprintf(stderr,">Z %ld graphs read",nin); if (nerr > 0) fprintf(stderr,"; %ld probable errors",nerr); else fprintf(stderr,"; NO PROBLEMS"); if (wswitch) fprintf(stderr,"; %ld graphs written",nin); fprintf(stderr,"\n"); exit(0); } nauty24r2/naugraph.c0000600000604200001440000005474511405400302013255 0ustar bdmusers/***************************************************************************** * * * Graph-specific auxiliary source file for version 2.4 of nauty. * * * * Copyright (1984-2010) Brendan McKay. All rights reserved. * * Subject to waivers and disclaimers in nauty.h. * * * * CHANGE HISTORY * * 16-Nov-00 : initial creation out of nautil.c * * 22-Apr-01 : added aproto line for Magma * * EXTDEFS is no longer required * * removed dynamic allocation from refine1() * * 21-Nov-01 : use NAUTYREQUIRED in naugraph_check() * * 23-Nov-06 : add targetcell(); make bestcell() local * * 10-Dec-06 : remove BIGNAUTY * * * *****************************************************************************/ #define ONE_WORD_SETS #include "nauty.h" /* macros for hash-codes: */ #define MASH(l,i) ((((l) ^ 065435) + (i)) & 077777) /* : expression whose long value depends only on long l and int/long i. Anything goes, preferably non-commutative. */ #define CLEANUP(l) ((int)((l) % 077777)) /* : expression whose value depends on long l and is less than 077777 when converted to int then short. Anything goes. */ #if MAXM==1 #define M 1 #else #define M m #endif /* aproto: header new_nauty_protos.h */ dispatchvec dispatch_graph = {isautom,testcanlab,updatecan,refine,refine1,cheapautom,targetcell, naugraph_freedyn,naugraph_check,NULL,NULL}; #if !MAXN DYNALLSTAT(set,workset,workset_sz); DYNALLSTAT(permutation,workperm,workperm_sz); DYNALLSTAT(int,bucket,bucket_sz); #else static set workset[MAXM]; /* used for scratch work */ static permutation workperm[MAXN]; static int bucket[MAXN+2]; #endif /***************************************************************************** * * * isautom(g,perm,digraph,m,n) = TRUE iff perm is an automorphism of g * * (i.e., g^perm = g). Symmetry is assumed unless digraph = TRUE. * * * *****************************************************************************/ boolean isautom(graph *g, permutation *perm, boolean digraph, int m, int n) { set *pg; int pos; set *pgp; int posp,i; for (pg = g, i = 0; i < n; pg += M, ++i) { pgp = GRAPHROW(g,perm[i],M); pos = (digraph ? -1 : i); while ((pos = nextelement(pg,M,pos)) >= 0) { posp = perm[pos]; if (!ISELEMENT(pgp,posp)) return FALSE; } } return TRUE; } /***************************************************************************** * * * testcanlab(g,canong,lab,samerows,m,n) compares g^lab to canong, * * using an ordering which is immaterial since it's only used here. The * * value returned is -1,0,1 if g^lab <,=,> canong. *samerows is set to * * the number of rows (0..n) of canong which are the same as those of g^lab. * * * * GLOBALS ACCESSED: workset,permset(),workperm * * * *****************************************************************************/ int testcanlab(graph *g, graph *canong, int *lab, int *samerows, int m, int n) { int i,j; set *ph; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"testcanlab"); DYNALLOC1(set,workset,workset_sz,m,"testcanlab"); #endif for (i = 0; i < n; ++i) workperm[lab[i]] = i; for (i = 0, ph = canong; i < n; ++i, ph += M) { permset(GRAPHROW(g,lab[i],M),workset,M,workperm); for (j = 0; j < M; ++j) if (workset[j] < ph[j]) { *samerows = i; return -1; } else if (workset[j] > ph[j]) { *samerows = i; return 1; } } *samerows = n; return 0; } /***************************************************************************** * * * updatecan(g,canong,lab,samerows,m,n) sets canong = g^lab, assuming * * the first samerows of canong are ok already. * * * * GLOBALS ACCESSED: permset(),workperm * * * *****************************************************************************/ void updatecan(graph *g, graph *canong, permutation *lab, int samerows, int m, int n) { int i; set *ph; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"updatecan"); #endif for (i = 0; i < n; ++i) workperm[lab[i]] = i; for (i = samerows, ph = GRAPHROW(canong,samerows,M); i < n; ++i, ph += M) permset(GRAPHROW(g,lab[i],M),ph,M,workperm); } /***************************************************************************** * * * refine(g,lab,ptn,level,numcells,count,active,code,m,n) performs a * * refinement operation on the partition at the specified level of the * * partition nest (lab,ptn). *numcells is assumed to contain the number of * * cells on input, and is updated. The initial set of active cells (alpha * * in the paper) is specified in the set active. Precisely, x is in active * * iff the cell starting at index x in lab is active. * * The resulting partition is equitable if active is correct (see the paper * * and the Guide). * * *code is set to a value which depends on the fine detail of the * * algorithm, but which is independent of the labelling of the graph. * * count is used for work space. * * * * GLOBALS ACCESSED: workset,bit,nextelement(),bucket,workperm * * * *****************************************************************************/ void refine(graph *g, int *lab, int *ptn, int level, int *numcells, permutation *count, set *active, int *code, int m, int n) { #if MAXM==1 refine1(g,lab,ptn,level,numcells,count,active,code,m,n); } #else int i,c1,c2,labc1; setword x; set *set1,*set2; int split1,split2,cell1,cell2; int cnt,bmin,bmax; long longcode; set *gptr; int maxcell,maxpos,hint; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"refine"); DYNALLOC1(set,workset,workset_sz,m,"refine"); DYNALLOC1(int,bucket,bucket_sz,n+2,"refine"); #endif longcode = *numcells; split1 = -1; hint = 0; while (*numcells < n && ((split1 = hint, ISELEMENT(active,split1)) || (split1 = nextelement(active,M,split1)) >= 0 || (split1 = nextelement(active,M,-1)) >= 0)) { DELELEMENT(active,split1); for (split2 = split1; ptn[split2] > level; ++split2) {} longcode = MASH(longcode,split1+split2); if (split1 == split2) /* trivial splitting cell */ { gptr = GRAPHROW(g,lab[split1],M); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} if (cell1 == cell2) continue; c1 = cell1; c2 = cell2; while (c1 <= c2) { labc1 = lab[c1]; if (ISELEMENT(gptr,labc1)) ++c1; else { lab[c1] = lab[c2]; lab[c2] = labc1; --c2; } } if (c2 >= cell1 && c1 <= cell2) { ptn[c2] = level; longcode = MASH(longcode,c2); ++*numcells; if (ISELEMENT(active,cell1) || c2-cell1 >= cell2-c1) { ADDELEMENT(active,c1); if (c1 == cell2) hint = c1; } else { ADDELEMENT(active,cell1); if (c2 == cell1) hint = cell1; } } } } else /* nontrivial splitting cell */ { EMPTYSET(workset,m); for (i = split1; i <= split2; ++i) ADDELEMENT(workset,lab[i]); longcode = MASH(longcode,split2-split1+1); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} if (cell1 == cell2) continue; i = cell1; set1 = workset; set2 = GRAPHROW(g,lab[i],m); cnt = 0; for (c1 = m; --c1 >= 0;) if ((x = (*set1++) & (*set2++)) != 0) cnt += POPCOUNT(x); count[i] = bmin = bmax = cnt; bucket[cnt] = 1; while (++i <= cell2) { set1 = workset; set2 = GRAPHROW(g,lab[i],m); cnt = 0; for (c1 = m; --c1 >= 0;) if ((x = (*set1++) & (*set2++)) != 0) cnt += POPCOUNT(x); while (bmin > cnt) bucket[--bmin] = 0; while (bmax < cnt) bucket[++bmax] = 0; ++bucket[cnt]; count[i] = cnt; } if (bmin == bmax) { longcode = MASH(longcode,bmin+cell1); continue; } c1 = cell1; maxcell = -1; for (i = bmin; i <= bmax; ++i) if (bucket[i]) { c2 = c1 + bucket[i]; bucket[i] = c1; longcode = MASH(longcode,i+c1); if (c2-c1 > maxcell) { maxcell = c2-c1; maxpos = c1; } if (c1 != cell1) { ADDELEMENT(active,c1); if (c2-c1 == 1) hint = c1; ++*numcells; } if (c2 <= cell2) ptn[c2-1] = level; c1 = c2; } for (i = cell1; i <= cell2; ++i) workperm[bucket[count[i]]++] = lab[i]; for (i = cell1; i <= cell2; ++i) lab[i] = workperm[i]; if (!ISELEMENT(active,cell1)) { ADDELEMENT(active,cell1); DELELEMENT(active,maxpos); } } } } longcode = MASH(longcode,*numcells); *code = CLEANUP(longcode); } #endif /* else case of MAXM==1 */ /***************************************************************************** * * * refine1(g,lab,ptn,level,numcells,count,active,code,m,n) is the same as * * refine(g,lab,ptn,level,numcells,count,active,code,m,n), except that * * m==1 is assumed for greater efficiency. The results are identical in all * * respects. See refine (above) for the specs. * * * *****************************************************************************/ void refine1(graph *g, int *lab, int *ptn, int level, int *numcells, permutation *count, set *active, int *code, int m, int n) { int i,c1,c2,labc1; setword x; int split1,split2,cell1,cell2; int cnt,bmin,bmax; long longcode; set *gptr,workset0; int maxcell,maxpos,hint; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"refine1"); DYNALLOC1(int,bucket,bucket_sz,n+2,"refine1"); #endif longcode = *numcells; split1 = -1; hint = 0; while (*numcells < n && ((split1 = hint, ISELEMENT1(active,split1)) || (split1 = nextelement(active,1,split1)) >= 0 || (split1 = nextelement(active,1,-1)) >= 0)) { DELELEMENT1(active,split1); for (split2 = split1; ptn[split2] > level; ++split2) {} longcode = MASH(longcode,split1+split2); if (split1 == split2) /* trivial splitting cell */ { gptr = GRAPHROW(g,lab[split1],1); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} if (cell1 == cell2) continue; c1 = cell1; c2 = cell2; while (c1 <= c2) { labc1 = lab[c1]; if (ISELEMENT1(gptr,labc1)) ++c1; else { lab[c1] = lab[c2]; lab[c2] = labc1; --c2; } } if (c2 >= cell1 && c1 <= cell2) { ptn[c2] = level; longcode = MASH(longcode,c2); ++*numcells; if (ISELEMENT1(active,cell1) || c2-cell1 >= cell2-c1) { ADDELEMENT1(active,c1); if (c1 == cell2) hint = c1; } else { ADDELEMENT1(active,cell1); if (c2 == cell1) hint = cell1; } } } } else /* nontrivial splitting cell */ { workset0 = 0; for (i = split1; i <= split2; ++i) ADDELEMENT1(&workset0,lab[i]); longcode = MASH(longcode,split2-split1+1); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > level; ++cell2) {} if (cell1 == cell2) continue; i = cell1; if ((x = workset0 & g[lab[i]]) != 0) cnt = POPCOUNT(x); else cnt = 0; count[i] = bmin = bmax = cnt; bucket[cnt] = 1; while (++i <= cell2) { if ((x = workset0 & g[lab[i]]) != 0) cnt = POPCOUNT(x); else cnt = 0; while (bmin > cnt) bucket[--bmin] = 0; while (bmax < cnt) bucket[++bmax] = 0; ++bucket[cnt]; count[i] = cnt; } if (bmin == bmax) { longcode = MASH(longcode,bmin+cell1); continue; } c1 = cell1; maxcell = -1; for (i = bmin; i <= bmax; ++i) if (bucket[i]) { c2 = c1 + bucket[i]; bucket[i] = c1; longcode = MASH(longcode,i+c1); if (c2-c1 > maxcell) { maxcell = c2-c1; maxpos = c1; } if (c1 != cell1) { ADDELEMENT1(active,c1); if (c2-c1 == 1) hint = c1; ++*numcells; } if (c2 <= cell2) ptn[c2-1] = level; c1 = c2; } for (i = cell1; i <= cell2; ++i) workperm[bucket[count[i]]++] = lab[i]; for (i = cell1; i <= cell2; ++i) lab[i] = workperm[i]; if (!ISELEMENT1(active,cell1)) { ADDELEMENT1(active,cell1); DELELEMENT1(active,maxpos); } } } } longcode = MASH(longcode,*numcells); *code = CLEANUP(longcode); } /***************************************************************************** * * * cheapautom(ptn,level,digraph,n) returns TRUE if the partition at the * * specified level in the partition nest (lab,ptn) {lab is not needed here} * * satisfies a simple sufficient condition for its cells to be the orbits of * * some subgroup of the automorphism group. Otherwise it returns FALSE. * * It always returns FALSE if digraph!=FALSE. * * * * nauty assumes that this function will always return TRUE for any * * partition finer than one for which it returns TRUE. * * * *****************************************************************************/ boolean cheapautom(int *ptn, int level, boolean digraph, int n) { int i,k,nnt; if (digraph) return FALSE; k = n; nnt = 0; for (i = 0; i < n; ++i) { --k; if (ptn[i] > level) { ++nnt; while (ptn[++i] > level) {} } } return (k <= nnt + 1 || k <= 4); } /***************************************************************************** * * * bestcell(g,lab,ptn,level,tc_level,m,n) returns the index in lab of the * * start of the "best non-singleton cell" for fixing. If there is no * * non-singleton cell it returns n. * * This implementation finds the first cell which is non-trivially joined * * to the greatest number of other cells. * * * * GLOBALS ACCESSED: bit,workperm,workset,bucket * * * *****************************************************************************/ static int bestcell(graph *g, int *lab, int *ptn, int level, int tc_level, int m, int n) { int i; set *gp; setword setword1,setword2; int v1,v2,nnt; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"bestcell"); DYNALLOC1(set,workset,workset_sz,m,"bestcell"); DYNALLOC1(int,bucket,bucket_sz,n+2,"bestcell"); #endif /* find non-singleton cells: put starts in workperm[0..nnt-1] */ i = nnt = 0; while (i < n) { if (ptn[i] > level) { workperm[nnt++] = i; while (ptn[i] > level) ++i; } ++i; } if (nnt == 0) return n; /* set bucket[i] to # non-trivial neighbours of n.s. cell i */ for (i = nnt; --i >= 0;) bucket[i] = 0; for (v2 = 1; v2 < nnt; ++v2) { EMPTYSET(workset,m); i = workperm[v2] - 1; do { ++i; ADDELEMENT(workset,lab[i]); } while (ptn[i] > level); for (v1 = 0; v1 < v2; ++v1) { gp = GRAPHROW(g,lab[workperm[v1]],m); #if MAXM==1 setword1 = *workset & *gp; setword2 = *workset & ~*gp; #else setword1 = setword2 = 0; for (i = m; --i >= 0;) { setword1 |= workset[i] & gp[i]; setword2 |= workset[i] & ~gp[i]; } #endif if (setword1 != 0 && setword2 != 0) { ++bucket[v1]; ++bucket[v2]; } } } /* find first greatest bucket value */ v1 = 0; v2 = bucket[0]; for (i = 1; i < nnt; ++i) if (bucket[i] > v2) { v1 = i; v2 = bucket[i]; } return (int)workperm[v1]; } /***************************************************************************** * * * targetcell(g,lab,ptn,level,tc_level,digraph,hint,m,n) returns the index * * in lab of the next cell to split. * * hint is a suggestion for the answer, which is obeyed if it is valid. * * Otherwise we use bestcell() up to tc_level and the first non-trivial * * cell after that. * * * *****************************************************************************/ int targetcell(graph *g, int *lab, int *ptn, int level, int tc_level, boolean digraph, int hint, int m, int n) { int i; if (hint >= 0 && ptn[hint] > level && (hint == 0 || ptn[hint-1] <= level)) return hint; else if (level <= tc_level) return bestcell(g,lab,ptn,level,tc_level,m,n); else { for (i = 0; i < n && ptn[i] <= level; ++i) {} return (i == n ? 0 : i); } } /***************************************************************************** * * * naugraph_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void naugraph_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in naugraph.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in naugraph.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in naugraph.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: naugraph.c version mismatch\n"); exit(1); } } /***************************************************************************** * * * naugraph_freedyn() - free the dynamic memory in this module * * * *****************************************************************************/ void naugraph_freedyn(void) { #if !MAXN DYNFREE(workset,workset_sz); DYNFREE(workperm,workperm_sz); DYNFREE(bucket,bucket_sz); #endif } nauty24r2/testa.dre0000600000604200001440000000050311274163463013121 0ustar bdmusers*=0 n=100 s7 %%%%% c ! 3262 vertices jx a=ccfaa80 o=f935ec3 b=6f5ed03 jx a=c846139 o=555fdb2 b=155828f jx a=bb5e92d o=918c61 b=6f70f94 jx a=e8f9f8a o=437a860 b=53c138c jx a=c05721 o=936879b b=33d85a6 n=10000 s3 _ cx a=1 o=a72fb0f b=1ec7f77 n=20000 s3 _ cx a=1 o=2e19ad7 b=a5c28ff n=25000 s4 cx a=1 o=76d150c b=54e0d8c q nauty24r2/nausparse.h0000600000604200001440000000510611274163463013463 0ustar bdmusers/* nausparse.h : header file for sparse digraphs, nauty 2.4 */ /* This version allows only simple graphs with loops but * contains the data structures for weights on the edges * even though they aren't implemented yet. */ #ifndef _NAUSPARSE_H_ /* only process this file once */ #define _NAUSPARSE_H_ #include "nauty.h" #ifndef SG_WEIGHT #define SG_WEIGHT int #endif typedef struct { int nv,nde; int *v,*d,*e; SG_WEIGHT *w; /* Not implemented, should be NULL. */ size_t vlen,dlen,elen,wlen; } sparsegraph; /* tip: loops only contribute 1 to nde */ #define SG_VDE(sgp,vv,dd,ee) do { vv = ((sparsegraph*)(sgp))->v; \ dd = ((sparsegraph*)(sgp))->d; ee = ((sparsegraph*)(sgp))->e; } while(0) #define SG_INIT(sg) do { (sg).v = (sg).d = (sg).e = (sg).w = NULL; \ (sg).vlen = (sg).dlen = (sg).elen = (sg).wlen = 0; } while(0) #define SG_ALLOC(sg,nlen,ndelen,msg) do { \ DYNALLOC1(int,(sg).v,(sg).vlen,nlen,msg); \ DYNALLOC1(int,(sg).d,(sg).dlen,nlen,msg); \ DYNALLOC1(int,(sg).e,(sg).elen,ndelen,msg); } while (0) #define SG_FREE(sg) do { \ DYNFREE((sg).v,(sg).vlen); \ DYNFREE((sg).d,(sg).dlen); \ DYNFREE((sg).e,(sg).elen); } while (0) #define SG_DECL(sg) sparsegraph sg = {0,0,NULL,NULL,NULL,NULL,0,0,0,0} #define DEFAULTOPTIONS_SPARSEGRAPH(options) optionblk options = \ {0,FALSE,FALSE,FALSE,TRUE,FALSE,CONSOLWIDTH, \ NULL,NULL,NULL,NULL,NULL,NULL,100,0,1,0,&dispatch_sparse,NULL} #ifdef __cplusplus extern "C" { #endif extern dispatchvec dispatch_sparse; extern int targetcell_sg(graph*,int*,int*,int,int,boolean,int,int,int); extern boolean cheapautom_sg(int*,int,boolean,int); extern boolean isautom_sg(graph*,permutation*,boolean,int,int); extern void refine_sg(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int); extern int testcanlab_sg(graph*,graph*,int*,int*,int,int); extern void updatecan_sg(graph*,graph*,permutation*,int,int,int); extern void init_sg(graph*,graph**,graph*,graph**,int*,int*,set*, struct optionstruct*,int*,int,int); extern void nausparse_freedyn(void); extern void nausparse_check(int,int,int,int); extern sparsegraph *nauty_to_sg(graph*,sparsegraph*,int,int); extern graph* sg_to_nauty(sparsegraph*,graph*,int,int*); extern void sortlists_sg(sparsegraph*); extern boolean aresame_sg(sparsegraph*,sparsegraph*); extern void put_sg(FILE*,sparsegraph*,boolean,int); extern void adjacencies_sg(graph*,int*,int*,int,int,int, permutation*,int,boolean,int,int); extern void distances_sg(graph*,int*,int*,int,int,int, permutation*,int,boolean,int,int); #ifdef __cplusplus } #endif #endif nauty24r2/biplabg.c0000600000604200001440000000724311274163463013061 0ustar bdmusers/* biplabg.c version 1.0; B D McKay, Nov 19, 2003. */ #define USAGE "biplabg [-q] [infile [outfile]]" #define HELPTEXT \ " Label bipartite graphs so that the colour classes are contiguous.\n\ The first vertex of each component is assigned the first colour.\n\ Vertices in each colour class have the same relative order as before.\n\ Non-bipartite graphs are rejected.\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -q Suppress auxiliary information.\n" /*************************************************************************/ #include "gtools.h" /**************************************************************************/ static boolean biplabel(graph *g, int m, int n, graph *h) /* h := bipartite labelling of g; else return FALSE */ { int i,j; #if MAXN int colour[MAXN]; permutation lab[MAXN]; #else DYNALLSTAT(int,colour,colour_sz); DYNALLSTAT(permutation,lab,lab_sz); DYNALLOC1(int,colour,colour_sz,n,"biplabg"); DYNALLOC1(permutation,lab,lab_sz,n,"biplabg"); #endif if (!twocolouring(g,colour,m,n)) return FALSE; j = 0; for (i = 0; i < n; ++i) if (colour[i] == 0) lab[j++] = i; for (i = 0; i < n; ++i) if (colour[i] == 1) lab[j++] = i; updatecan(g,h,lab,0,m,n); return TRUE; } /**************************************************************************/ int main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile,*outfile; boolean badargs,quiet; int j,m,n,argnum; int codetype,outcode; graph *g; long nin,nout; char *arg,sw; double t; #if MAXN graph h[MAXN*MAXM]; #else DYNALLSTAT(graph,h,h_sz); #endif HELP; infilename = outfilename = NULL; quiet = FALSE; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('q',quiet) else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!quiet) { fprintf(stderr,">A biplabg"); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (codetype&HAS_HEADER) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } nautil_check(WORDSIZE,1,1,NAUTYVERSIONID); nin = nout = 0; t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"biplabg"); #endif if (biplabel(g,m,n,h)) { ++nout; if (outcode == SPARSE6) writes6(outfile,h,m,n); else writeg6(outfile,h,m,n); } FREES(g); } t = CPUTIME - t; if (!quiet) fprintf(stderr, ">Z %ld graphs read from %s; %ld written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,t); exit(0); } nauty24r2/gtools.c0000600000604200001440000013137311405400216012754 0ustar bdmusers/* gtools.c : Common routines for gtools programs. */ /* Version 2.4, Nov 2006. */ /* Todo: size check if MAXN>0; option to free memory */ #include "gtools.h" #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif size_t ogf_linelen; boolean is_pipe; #if !FTELL_DEC extern long ftell(FILE*); extern int fseek(FILE*,long,int); #endif #if !POPEN_DEC extern FILE *popen(const char*,const char*); #endif /* Version 1.1: Fixed sparse6 input for powers of 2. May 9, 1998 Version 1.2: Added "cmd: ..." option for opengraphfile(). Fixed readg() bug (could not be invisible). Oct 5, 1998 Version 1.3: Added "is_pipe". June 20, 2002 Version 1.4: Stuff for autoconf. August 30, 2002 Version 1.5: Unlocked stdio for efficiency. October 31, 2004 Also fwrite() in place of fputs() for writeline(). Version 1.6: i/o for sparsegraph; use of s6len; improve allocations Version 1.7: Add stringcounts() Add very long size code (see formats.txt) Version 1.8: Add gtools_check() Version 1.9: Add writepc_sg(), readpc_sg() and readpcle_sg() Add planar_code options to opengraphfile() Version 2.4: Add writeec_sg(), readec_sg() Add edge_code options to opengraphfile() */ #define B(i) (1 << ((i)-1)) #define M(i) ((1 << (i))-1) /***************************************************************************** * * * sortints(x,n) - sort x[0..n-1] according to numerical values * * * *****************************************************************************/ static void sortints(int *x, int n) { int i,j,h; int xi; j = n / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < n; ++i) { xi = x[i]; for (j = i; x[j-h] > xi; ) { x[j] = x[j-h]; if ((j -= h) < h) break; } x[j] = xi; } h /= 3; } while (h > 0); } /********************************************************************* opengraphfile(filename,codetype,assumefixed,position) opens and positions a file for reading graphs. filename = the name of the file to open (NULL means stdin, assumed already open) If filename starts with "cmd:", the remainder is taken to be a command to open a subshell for, using a pipe. codetype = returns a code for the format. This is a combination of SPARSE6, GRAPH6, PLANARCODE, PLANARCODELE, PLANARCODEBE, EDGECODE, UNKNOWN_TYPE and HAS_HEADER. If a header is present, that overrides the data. If there is no header, the first graph is examined. assumefixed = nonzero if files other than stdin or pipes should be assumed to be seekable and have equal record sizes. Ignored if there is a sparse6 header or the first graph has sparse6 format. position = the number of the record to position to (the first is number 1; 0 and -NOLIMIT also mean to position at start). planar_code files can only be positioned at the start. If the file starts with ">", there must be a header. Otherwise opengraphfile() fails. The value returned is a file pointer or NULL. If assumedfixed is not zero and position > 1, the global variable ogf_linelen is set to the length (including \n) of the length of the first record. UPDATE The global variable is_pipe is set to whether the input file is a pipe. **********************************************************************/ FILE* opengraphfile(char *filename, int *codetype, int assumefixed, long position) { FILE *f; int c,bl,firstc; long i,l,pos,pos1,pos2; boolean bad_header; is_pipe = FALSE; if (filename == NULL) { f = stdin; assumefixed = FALSE; } else { if (filename[0] == 'c' && filename[1] == 'm' && filename[2] == 'd' && filename[3] == ':') { #if !HAVE_POPEN gt_abort (">E The \"cmd:\" option is not available in this version"); #else filename += 4; while (*filename == ' ') ++filename; f = popen(filename,"r"); #endif assumefixed = FALSE; is_pipe = TRUE; } else f = fopen(filename,"r"); if (f == NULL) { fprintf(stderr,">E opengraphfile: can't open %s\n",filename); return NULL; } } FLOCKFILE(f); firstc = c = GETC(f); if (c == EOF) { *codetype = GRAPH6; FUNLOCKFILE(f); return f; } if (c != '>') { *codetype = firstc == ':' ? SPARSE6 : GRAPH6; ungetc(c,f); } else { bad_header = FALSE; if ((c = GETC(f)) == EOF || c != '>') bad_header = TRUE; if (!bad_header && ((c = GETC(f)) == EOF || (c != 'g' && c != 's' && c != 'p'))) bad_header = TRUE; if (!bad_header && c == 'g') { if ((c = GETC(f)) == EOF || c != 'r' || (c = GETC(f)) == EOF || c != 'a' || (c = GETC(f)) == EOF || c != 'p' || (c = GETC(f)) == EOF || c != 'h' || (c = GETC(f)) == EOF || c != '6' || (c = GETC(f)) == EOF || c != '<' || (c = GETC(f)) == EOF || c != '<') bad_header = TRUE; else *codetype = GRAPH6 | HAS_HEADER; } else if (!bad_header && c == 'e') { if ((c = GETC(f)) == EOF || c != 'd' || (c = GETC(f)) == EOF || c != 'g' || (c = GETC(f)) == EOF || c != 'e' || (c = GETC(f)) == EOF || c != '_' || (c = GETC(f)) == EOF || c != 'c' || (c = GETC(f)) == EOF || c != 'o' || (c = GETC(f)) == EOF || c != 'd' || (c = GETC(f)) == EOF || c != 'e' || (c = GETC(f)) == EOF || c != '<' || (c = GETC(f)) == EOF || c != '<') bad_header = TRUE; else *codetype = EDGECODE | HAS_HEADER; } else if (!bad_header && c == 's') { if ((c = GETC(f)) == EOF || c != 'p' || (c = GETC(f)) == EOF || c != 'a' || (c = GETC(f)) == EOF || c != 'r' || (c = GETC(f)) == EOF || c != 's' || (c = GETC(f)) == EOF || c != 'e' || (c = GETC(f)) == EOF || c != '6' || (c = GETC(f)) == EOF || c != '<' || (c = GETC(f)) == EOF || c != '<') bad_header = TRUE; else *codetype = SPARSE6 | HAS_HEADER; } else if (!bad_header && c == 'p') { if ((c = GETC(f)) == EOF || c != 'l' || (c = GETC(f)) == EOF || c != 'a' || (c = GETC(f)) == EOF || c != 'n' || (c = GETC(f)) == EOF || c != 'a' || (c = GETC(f)) == EOF || c != 'r' || (c = GETC(f)) == EOF || c != '_' || (c = GETC(f)) == EOF || c != 'c' || (c = GETC(f)) == EOF || c != 'o' || (c = GETC(f)) == EOF || c != 'd' || (c = GETC(f)) == EOF || c != 'e') bad_header = TRUE; else { if ((c = GETC(f)) == EOF) bad_header = TRUE; else if (c == ' ') { if ((bl = GETC(f)) == EOF || (bl != 'l' && bl != 'b') || (c = GETC(f)) == EOF || c != 'e' || (c = GETC(f)) == EOF || c != '<' || (c = GETC(f)) == EOF || c != '<') bad_header = TRUE; else if (bl == 'l') *codetype = PLANARCODELE | HAS_HEADER; else *codetype = PLANARCODEBE | HAS_HEADER; } else if (c == '<') { if ((c = GETC(f)) == EOF || c != '<') bad_header = TRUE; else *codetype = PLANARCODE | HAS_HEADER; } else bad_header = TRUE; } } if (bad_header) { fprintf(stderr,">E opengraphfile: illegal header in %s\n", filename == NULL ? "stdin" : filename); *codetype = UNKNOWN_TYPE | HAS_HEADER; FUNLOCKFILE(f); return NULL; } } if (position <= 1) return f; if (*codetype&PLANARCODE) { fprintf(stderr, ">E opengraphfile: planar_code files can only be opened at the start\n"); *codetype = UNKNOWN_TYPE | HAS_HEADER; FUNLOCKFILE(f); fclose(f); return NULL; } if (*codetype&EDGECODE) { fprintf(stderr, ">E opengraphfile: edge_code files can only be opened at the start\n"); *codetype = UNKNOWN_TYPE | HAS_HEADER; FUNLOCKFILE(f); fclose(f); return NULL; } if (!assumefixed || (*codetype&SPARSE6) || firstc == ':') { l = 1; while ((c = GETC(f)) != EOF) { if (c == '\n') { ++l; if (l == position) break; } } if (l == position) return f; fprintf(stderr, ">E opengraphfile: can't find line %ld in %s\n",position, filename == NULL ? "stdin" : filename); return NULL; } else { pos1 = ftell(f); if (pos1 < 0) { fprintf(stderr,">E opengraphfile: error on first ftell\n"); return NULL; } for (i = 1; (c = GETC(f)) != EOF && c != '\n'; ++i) {} ogf_linelen = i; if (c == EOF) { fprintf(stderr, ">E opengraphfile: required record no present\n"); FUNLOCKFILE(f); return NULL; } pos2 = ftell(f); if (pos2 < 0) { fprintf(stderr,">E opengraphfile: error on second ftell\n"); return NULL; } pos = pos1 + (position-1)*(pos2-pos1); if (fseek(f,pos,SEEK_SET) < 0) { fprintf(stderr,">E opengraphfile: seek failed\n"); return NULL; } } FUNLOCKFILE(f); return f; } /*********************************************************************/ void writeline(FILE *f, char *s) /* write a line with error checking */ /* \n is not appended automatically */ { size_t slen; slen = strlen(s); if (fwrite(s,1,slen,f) != slen || ferror(f)) gt_abort(">E writeline : error on writing\n"); } /*********************************************************************/ char* gtools_getline(FILE *f) /* read a line with error checking */ /* includes \n (if present) and \0. Immediate EOF causes NULL return. */ { DYNALLSTAT(char,s,s_sz); int c; long i; DYNALLOC1(char,s,s_sz,5000,"gtools_getline"); FLOCKFILE(f); i = 0; while ((c = GETC(f)) != EOF && c != '\n') { if (i == s_sz-3) DYNREALLOC(char,s,s_sz,3*(s_sz/2)+10000,"gtools_getline"); s[i++] = c; } FUNLOCKFILE(f); if (i == 0 && c == EOF) return NULL; if (c == '\n') s[i++] = '\n'; s[i] = '\0'; return s; } /****************************************************************************/ char* getecline(FILE *f) /* read an edge_code line */ /* No trailing \n or \0 is added. Immediate EOF causes NULL return. */ { size_t headsize,bodysize; int sizesize,edgesize; int c1,c,i; DYNALLSTAT(unsigned char,s,s_sz); FLOCKFILE(f); if ((c1 = GETC(f)) == EOF) return NULL; if (c1 > 0) { bodysize = c1; edgesize = 1; headsize = 1; } else { if ((c = GETC(f)) == EOF) gt_abort("Incomplete edge_code line"); else { sizesize = c >> 4; edgesize = c & 0xF; bodysize = 0; for (i = 0; i < sizesize; ++i) { if ((c = GETC(f)) == EOF) gt_abort("Incomplete edge_code line"); else bodysize = (bodysize << 8) + c; } headsize = 2 + sizesize; } } DYNALLOC1(unsigned char,s,s_sz,headsize+bodysize,"getecline"); s[0] = c1; if (c1 == 0) { s[1] = (sizesize << 4) + edgesize; for (i = 0; i < sizesize; ++i) s[headsize-1-i] = (bodysize >> 8*i) & 0xFF; } if (bodysize > 0 && fread(s+headsize,bodysize,1,f) != bodysize) gt_abort("Incomplete edge_code line"); FUNLOCKFILE(f); return (char*)s; } int graphsize(char *s) /* Get size of graph out of graph6 or sparse6 string. */ { char *p; int n; if (s[0] == ':') p = s+1; else p = s; n = *p++ - BIAS6; if (n > SMALLN) { n = *p++ - BIAS6; if (n > SMALLN) { n = *p++ - BIAS6; n = (n << 6) | (*p++ - BIAS6); n = (n << 6) | (*p++ - BIAS6); n = (n << 6) | (*p++ - BIAS6); n = (n << 6) | (*p++ - BIAS6); n = (n << 6) | (*p++ - BIAS6); } else { n = (n << 6) | (*p++ - BIAS6); n = (n << 6) | (*p++ - BIAS6); } } return n; } /****************************************************************************/ static void encodegraphsize(int n, char **pp) /* Encode the size n in a string starting at **p, and reset **p to point to the character after the size */ { char *p; p = *pp; if (n <= SMALLN) *p++ = BIAS6 + n; else if (n <= SMALLISHN) { *p++ = MAXBYTE; *p++ = BIAS6 + (n >> 12); *p++ = BIAS6 + ((n >> 6) & C6MASK); *p++ = BIAS6 + (n & C6MASK); } else { *p++ = MAXBYTE; *p++ = MAXBYTE; *p++ = BIAS6 + (n >> 30); *p++ = BIAS6 + ((n >> 24) & C6MASK); *p++ = BIAS6 + ((n >> 18) & C6MASK); *p++ = BIAS6 + ((n >> 12) & C6MASK); *p++ = BIAS6 + ((n >> 6) & C6MASK); *p++ = BIAS6 + (n & C6MASK); } *pp = p; } /****************************************************************************/ void stringcounts(char *s, int *pn, size_t *pe) /* Determine number of edges of graph6 or sparse6 string */ { char *p; int i,j,k,x,nb,v,n,need; size_t count; boolean done; n = graphsize(s); *pn = n; p = s + (s[0] == ':') + SIZELEN(n); if (s[0] == ':') /* sparse6 */ { count = 0; for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} k = 0; v = 0; done = FALSE; while (!done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (x & B(k)) ++v; --k; need = nb; j = 0; while (need > 0 && !done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (need >= k) { j = (j << k) | (x & M(k)); need -= k; k = 0; } else { k -= need; j = (j << need) | ((x >> k) & M(need)); need = 0; } } if (done) continue; if (j > v) v = j; else if (v < n) ++count; } } else /* graph6 */ { count = 0; for (; *p != '\n' && *p != '\0'; ++p) count += bytecount[*p - BIAS6]; } *pe = count; } /****************************************************************************/ void stringtograph(char *s, graph *g, int m) /* Convert string (graph6 or sparse6 format) to graph. */ /* Assumes g is big enough to hold it. */ { char *p; int n,i,j,k,v,x,nb,need; size_t ii; set *gi,*gj; boolean done; n = graphsize(s); p = s + (s[0] == ':') + SIZELEN(n); if (TIMESWORDSIZE(m) < n) gt_abort(">E stringtograph: impossible m value\n"); for (ii = m*(size_t)n; --ii > 0;) g[ii] = 0; g[0] = 0; if (s[0] != ':') /* graph6 format */ { k = 1; for (j = 1; j < n; ++j) { gj = GRAPHROW(g,j,m); for (i = 0; i < j; ++i) { if (--k == 0) { k = 6; x = *(p++) - BIAS6; } if (x & TOPBIT6) { gi = GRAPHROW(g,i,m); ADDELEMENT(gi,j); ADDELEMENT(gj,i); } x <<= 1; } } } else /* sparse6 format */ { for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} k = 0; v = 0; done = FALSE; while (!done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (x & B(k)) ++v; --k; need = nb; j = 0; while (need > 0 && !done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (need >= k) { j = (j << k) | (x & M(k)); need -= k; k = 0; } else { k -= need; j = (j << need) | ((x >> k) & M(need)); need = 0; } } if (done) continue; if (j > v) v = j; else if (v < n) { ADDELEMENT(GRAPHROW(g,v,m),j); ADDELEMENT(GRAPHROW(g,j,m),v); } } } } /***********************************************************************/ graph* /* read graph into nauty format */ readg(FILE *f, graph *g, int reqm, int *pm, int *pn) /* graph6 and sparse6 formats are supported f = an open file g = place to put the answer (NULL for dynamic allocation) reqm = the requested value of m (0 => compute from n) *pm = the actual value of m *pn = the value of n */ { char *s,*p; int m,n; if ((readg_line = gtools_getline(f)) == NULL) return NULL; s = readg_line; if (s[0] == ':') { readg_code = SPARSE6; p = s + 1; } else { readg_code = GRAPH6; p = s; } while (*p >= BIAS6 && *p <= MAXBYTE) ++p; if (*p == '\0') gt_abort(">E readg: missing newline\n"); else if (*p != '\n') gt_abort(">E readg: illegal character\n"); n = graphsize(s); if (readg_code == GRAPH6 && p - s != G6LEN(n)) gt_abort(">E readg: truncated graph6 line\n"); if (reqm > 0 && TIMESWORDSIZE(reqm) < n) gt_abort(">E readg: reqm too small\n"); else if (reqm > 0) m = reqm; else m = (n + WORDSIZE - 1) / WORDSIZE; if (g == NULL) { if ((g = (graph*)ALLOCS(n,m*sizeof(graph))) == NULL) gt_abort(">E readg: malloc failed\n"); } *pn = n; *pm = m; stringtograph(s,g,m); return g; } /****************************************************************************/ void stringtosparsegraph(char *s, sparsegraph *sg, int *nloops) /* Convert string (graph6 or sparse6 format) to sparse graph. * Assumes sg exists and is initialised * Also returns the number of loops */ { char *p,*q; int n,nde,i,j,k,vv,x,nb,need; int *v,*d,*e; int loops; boolean done; n = graphsize(s); q = s + (s[0] == ':') + SIZELEN(n); sg->nv = n; DYNALLOC1(int,sg->v,sg->vlen,n,"stringtosparsegraph"); DYNALLOC1(int,sg->d,sg->dlen,n,"stringtosparsegraph"); v = sg->v; d = sg->d; for (i = 0; i < n; ++i) d[i] = 0; if (s[0] != ':') /* graph6 format */ { p = q; k = 1; for (j = 1; j < n; ++j) { for (i = 0; i < j; ++i) { if (--k == 0) { k = 6; x = *(p++) - BIAS6; } if (x & TOPBIT6) { d[i]++; d[j]++; } x <<= 1; } } v[0] = 0; for (i = 1; i < n; ++i) v[i] = v[i-1]+d[i-1]; nde = v[n-1]+d[n-1]; for (i = 0; i < n; ++i) d[i] = 0; sg->nde = nde; DYNALLOC1(int,sg->e,sg->elen,nde,"stringtosparsegraph"); e = sg->e; p = q; k = 1; for (j = 1; j < n; ++j) { for (i = 0; i < j; ++i) { if (--k == 0) { k = 6; x = *(p++) - BIAS6; } if (x & TOPBIT6) { e[v[i]+d[i]++] = j; e[v[j]+d[j]++] = i; } x <<= 1; } } *nloops = 0; } else /* sparse6 format */ { for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} p = q; k = 0; vv = 0; done = FALSE; loops = 0; while (!done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (x & B(k)) ++vv; --k; need = nb; j = 0; while (need > 0 && !done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (need >= k) { j = (j << k) | (x & M(k)); need -= k; k = 0; } else { k -= need; j = (j << need) | ((x >> k) & M(need)); need = 0; } } if (done) continue; if (j > vv) vv = j; else if (vv < n) { d[vv]++; if (vv != j) d[j]++; else ++loops; } } v[0] = 0; for (i = 1; i < n; ++i) v[i] = v[i-1]+d[i-1]; nde = v[n-1]+d[n-1]; for (i = 0; i < n; ++i) d[i] = 0; sg->nde = nde; DYNALLOC1(int,sg->e,sg->elen,nde,"stringtosparsegraph"); e = sg->e; p = q; k = 0; vv = 0; done = FALSE; while (!done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (x & B(k)) ++vv; --k; need = nb; j = 0; while (need > 0 && !done) { if (k == 0) { x = *(p++); if (x == '\n' || x == '\0') { done = TRUE; continue; } else { x -= BIAS6; k = 6; } } if (need >= k) { j = (j << k) | (x & M(k)); need -= k; k = 0; } else { k -= need; j = (j << need) | ((x >> k) & M(need)); need = 0; } } if (done) continue; if (j > vv) vv = j; else if (vv < n) { e[v[vv]+d[vv]++] = j; if (vv != j) e[v[j]+d[j]++] = vv; } } *nloops = loops; } } /***********************************************************************/ sparsegraph* /* read graph into sparsegraph format */ read_sg_loops(FILE *f, sparsegraph *sg, int *nloops) /* graph6 and sparse6 formats are supported * f = an open file * sg = place to put the answer (NULL for dynamic allocation) * - must be initialised if not NULL * nloops := number of loops (each loop in a sparse6 string * gives one loop in the sparse representation) */ { char *s,*p; int n,loops; if ((readg_line = gtools_getline(f)) == NULL) return NULL; s = readg_line; if (s[0] == ':') { readg_code = SPARSE6; p = s + 1; } else { readg_code = GRAPH6; p = s; } while (*p >= BIAS6 && *p <= MAXBYTE) ++p; if (*p == '\0') gt_abort(">E read_sg: missing newline\n"); else if (*p != '\n') gt_abort(">E read_sg: illegal character\n"); n = graphsize(s); if (readg_code == GRAPH6 && p - s != G6LEN(n)) gt_abort(">E read_sg: truncated graph6 line\n"); if (sg == NULL) { if ((sg = (sparsegraph*)ALLOCS(1,sizeof(sparsegraph))) == NULL) gt_abort(">E read_sg: malloc failed\n"); SG_INIT(*sg); } stringtosparsegraph(s,sg,&loops); *nloops = loops; return sg; } /***********************************************************************/ sparsegraph* /* read graph into sparsegraph format */ read_sg(FILE *f, sparsegraph *sg) /* graph6 and sparse6 formats are supported * *f = an open file * *sg = place to put the answer (NULL for dynamic allocation) * - must be initialised if not NULL */ { int loops; return read_sg_loops(f,sg,&loops); } /****************************************************************************/ DYNALLSTAT(char,gcode,gcode_sz); /* Used by ntog6, ntos6 and sgtos6 */ size_t s6len; int readg_code; char *readg_line; /****************************************************************************/ char* ntog6(graph *g, int m, int n) /* convert nauty graph to graph6 string, including \n and \0 */ { int i,j,k; char *p,x; set *gj; size_t ii; ii = G6LEN(n)+3; DYNALLOC1(char,gcode,gcode_sz,ii,"ntog6"); p = gcode; encodegraphsize(n,&p); k = 6; x = 0; for (j = 1; j < n; ++j) { gj = GRAPHROW(g,j,m); for (i = 0; i < j; ++i) { x <<= 1; if (ISELEMENT(gj,i)) x |= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } } if (k != 6) *p++ = BIAS6 + (x << k); *p++ = '\n'; *p = '\0'; return gcode; } /****************************************************************************/ char* ntos6(graph *g, int m, int n) /* convert nauty graph to sparse6 string, including \n and \0 */ { int i,j,k; char *p,x; set *gj; size_t ii; int r,rr,topbit,nb,lastj; char *plim; DYNALLOC1(char,gcode,gcode_sz,5000,"ntos6"); plim = gcode + gcode_sz - 20; gcode[0] = ':'; p = gcode+1; encodegraphsize(n,&p); for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} topbit = 1 << (nb-1); k = 6; x = 0; lastj = 0; for (j = 0; j < n; ++j) { gj = GRAPHROW(g,j,m); for (i = 0; i <= j; ++i) { if (ISELEMENT(gj,i)) { if (p >= plim) { ii = p - gcode; DYNREALLOC(char,gcode,gcode_sz, 3*(gcode_sz/2)+10000,"ntos6"); p = gcode + ii; plim = gcode + gcode_sz - 20; } if (j == lastj) { x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } else { x = (x << 1) | 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } if (j > lastj+1) { for (r = 0, rr = j; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } lastj = j; } for (r = 0, rr = i; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } } } } if (k != 6) { if (k >= nb+1 && lastj == n-2 && n == (1<nv; for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} ii = (nb+1)*(n/6+sg->nde/3); DYNALLOC1(char,gcode,gcode_sz,ii+1000,"ntos6"); plim = gcode + gcode_sz - 20; gcode[0] = ':'; p = gcode; *p++ = ':'; encodegraphsize(n,&p); topbit = 1 << (nb-1); k = 6; x = 0; lastj = 0; for (j = 0; j < n; ++j) { vj = v[j]; dj = d[j]; for (l = 0; l < dj; ++l) { i = e[vj+l]; if (i <= j) { if (p >= plim) { ii = p - gcode; DYNREALLOC(char,gcode,gcode_sz, 5*(gcode_sz/4)+1000,"sgtos6"); p = gcode + ii; plim = gcode + gcode_sz - 20; } if (j == lastj) { x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } else { x = (x << 1) | 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } if (j > lastj+1) { for (r = 0, rr = j; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } lastj = j; } for (r = 0, rr = i; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { *p++ = BIAS6 + x; k = 6; x = 0; } } } } } if (k != 6) { if (k >= nb+1 && lastj == n-2 && n == (1<E writes6 : error on writing\n"); } /**************************************************************************/ void writes6_sg(FILE *f, sparsegraph *g) /* write undirected sparse graph to file in sparse6 format */ { char *s; s = sgtos6(g); if (fwrite(s,1,s6len,f) != s6len || ferror(f)) gt_abort(">E writes6 : error on writing\n"); } /**************************************************************************/ DYNALLSTAT(unsigned char,buff,buff_sz); void writepc_sg(FILE *f, sparsegraph *sg) /* write a sparse graph in planar_code format *f = an open file *sg = the graph to write */ { int bytes; size_t i,j,len,k; unsigned int w; int n,*v,*d,*e,vi,di; #define BEPUT1(x) buff[j++]=(x); #define BEPUT2(x) w=(x); buff[j++]=(w>>8)&0xFF; buff[j++]=w&0xff; #define BEPUT4(x) w=(x); buff[j++]=(w>>24)&0xFF; buff[j++]=(w>>16)&0xff; \ buff[j++]=(w>>8)&0xFF; buff[j++]=w&0xff; n = sg->nv; SG_VDE(sg,v,d,e); if (n <= 255) bytes = 1; else if (n <= 65535) bytes = 2; else bytes = 4; len = bytes * (1 + n + (size_t)(sg->nde)); if (bytes == 2) len += 1; else if (bytes == 4) len += 3; DYNALLOC1(unsigned char,buff,buff_sz,len,"writepc_sg"); if (bytes == 1) { j = 0; BEPUT1(n); for (i = 0; i < n; ++i) { vi = v[i]; di = d[i]; for (k = 0; k < di; ++k) BEPUT1(e[vi+k]+1); BEPUT1(0); } } else if (bytes == 2) { j = 0; BEPUT1(n); BEPUT2(n); for (i = 0; i < n; ++i) { vi = v[i]; di = d[i]; for (k = 0; k < di; ++k) BEPUT2(e[vi+k]+1); BEPUT2(0); } } else /* bytes==4 */ { j = 0; BEPUT1(n); BEPUT2(n); BEPUT4(n); for (i = 0; i < n; ++i) { vi = v[i]; di = d[i]; for (k = 0; k < di; ++k) BEPUT4(e[vi+k]+1); BEPUT4(0); } } if (fwrite((void*)buff,1,j,f) != j) gt_abort(">E writepc_sg : error on writing\n"); } /**************************************************************************/ sparsegraph* readpc_sg(FILE *f,sparsegraph *sg) /* read a planar_code graph into sparse graph format *f = an open file *sg = place to put the answer (NULL for dynamic allocation) - must be initialised if not NULL */ { #define BEGET1(x) { x = GETC(f); } #define BEGET2(x) { w1=GETC(f); w2=GETC(f); if (w2==EOF) x = EOF; else \ x = (w1<<8) | w2; } #define BEGET4(x) { w1=GETC(f); w2=GETC(f); w3=GETC(f); w4=GETC(f); \ if (w4==EOF) x = EOF; \ else x = (w1<<24) | (w2<<16) | (w3<<8) | w4; } int w1,w2,w3,w4; int bytes,n; int i,j,*v,*d,*e,vi,di; BEGET1(n); if (n == EOF || n < 0) return NULL; else if (n > 0) bytes = 1; else { BEGET2(n); if (n == EOF || n < 0) gt_abort(">E readpc_sg : error 1 on reading\n"); else if (n > 0) bytes = 2; else { BEGET4(n); if (n == EOF || n < 0) gt_abort(">E readpc_sg : error 2 on reading\n"); else if (n > 0) bytes = 4; else gt_abort(">E readpc_sg : error 3 on reading\n"); } } if (sg == NULL) { if ((sg = (sparsegraph*)ALLOCS(1,sizeof(sparsegraph))) == NULL) gt_abort(">E readpc_sg: malloc failed\n"); SG_INIT(*sg); } SG_ALLOC(*sg,n,2*n,"readpc_sg"); SG_VDE(sg,v,d,e); vi = 0; for (i = 0; i < n; ++i) { v[i] = vi; di = 0; do { if (bytes == 1) BEGET1(j) else if (bytes == 2) BEGET2(j) else BEGET4(j); if (j == EOF) gt_abort(">E readpc_sg : error 4 on reading\n"); if (j > 0) { if (vi == sg->elen) { DYNREALLOC(int,sg->e,sg->elen,2*sg->elen,"readpc_sg"); e = sg->e; } e[vi++] = j-1; ++di; } else if (j == 0) d[i] = di; else gt_abort(">E readpc_sg : error 5 on reading\n"); } while (j != 0); } sg->nv = n; sg->nde = vi; return sg; } /**************************************************************************/ sparsegraph* readpcle_sg(FILE *f,sparsegraph *sg) /* read a planar_code graph into sparse graph format *f = an open file *sg = place to put the answer (NULL for dynamic allocation) - must be initialised if not NULL */ { #define LEGET1(x) { x = GETC(f); } #define LEGET2(x) { w2=GETC(f); w1=GETC(f); if (w1==EOF) x = EOF; else \ x = (w1<<8) | w2; } #define LEGET4(x) { w4=GETC(f); w3=GETC(f); w2=GETC(f); w1=GETC(f); \ if (w1==EOF) x = EOF; \ else x = (w1<<24) | (w2<<16) | (w3<<8) | w4; } int w1,w2,w3,w4; int bytes,n; int i,j,*v,*d,*e,vi,di; LEGET1(n); if (n == EOF || n < 0) return NULL; else if (n > 0) bytes = 1; else { LEGET2(n); if (n == EOF || n < 0) gt_abort(">E readpcle_sg : error 1 on reading\n"); else if (n > 0) bytes = 2; else { LEGET4(n); if (n == EOF || n < 0) gt_abort(">E readpcle_sg : error 2 on reading\n"); else if (n > 0) bytes = 4; else gt_abort(">E readpcle_sg : error 3 on reading\n"); } } if (sg == NULL) { if ((sg = (sparsegraph*)ALLOCS(1,sizeof(sparsegraph))) == NULL) gt_abort(">E readpcle_sg: malloc failed\n"); SG_INIT(*sg); } SG_ALLOC(*sg,n,2*n,"readpcle_sg"); SG_VDE(sg,v,d,e); vi = 0; for (i = 0; i < n; ++i) { v[i] = vi; di = 0; do { if (bytes == 1) LEGET1(j) else if (bytes == 2) LEGET2(j) else LEGET4(j); if (j == EOF) gt_abort(">E readpcle_sg : error 4 on reading\n"); if (j > 0) { if (vi == sg->elen) { DYNREALLOC(int,sg->e,sg->elen,2*sg->elen,"readpcle_sg"); e = sg->e; } e[vi++] = j-1; ++di; } else if (j == 0) d[i] = di; else gt_abort(">E readpcle_sg : error 5 on reading\n"); } while (j != 0); } sg->nv = n; sg->nde = vi; return sg; } /**************************************************************************/ void writelast(FILE *f) /* write last graph read by readg() assuming no intervening getline() */ { writeline(f,readg_line); } /**************************************************************************/ int longvalue(char **ps, long *l) { boolean neg,pos; long sofar,last; char *s; s = *ps; pos = neg = FALSE; if (*s == '-') { neg = TRUE; ++s; } else if (*s == '+') { pos = TRUE; ++s; } if (*s < '0' || *s > '9') { *ps = s; return (pos || neg) ? ARG_ILLEGAL : ARG_MISSING; } sofar = 0; for (; *s >= '0' && *s <= '9'; ++s) { last = sofar; sofar = sofar * 10 + (*s - '0'); if (sofar < last || sofar > MAXARG) { *ps = s; return ARG_TOOBIG; } } *ps = s; *l = neg ? -sofar : sofar; return ARG_OK; } /*************************************************************************/ void arg_long(char **ps, long *val, char *id) { int code; code = longvalue(ps,val); if (code == ARG_MISSING || code == ARG_ILLEGAL) { fprintf(stderr,">E %s: missing argument value\n",id); gt_abort(NULL); } else if (code == ARG_TOOBIG) { fprintf(stderr,">E %s: argument value too large\n",id); gt_abort(NULL); } } /*************************************************************************/ void arg_int(char **ps, int *val, char *id) { int code; long longval; code = longvalue(ps,&longval); *val = longval; if (code == ARG_MISSING || code == ARG_ILLEGAL) { fprintf(stderr,">E %s: missing argument value\n",id); gt_abort(NULL); } else if (code == ARG_TOOBIG || *val != longval) { fprintf(stderr,">E %s: argument value too large\n",id); gt_abort(NULL); } } /************************************************************************/ boolean strhaschar(char *s, int c) /* Check if s contains c. Saves the bother of figuring out whether strchr() is available, or index() or whatever. */ { int i; for (i = 0; s[i] != '\0'; ++i) if (s[i] == c) return TRUE; return FALSE; } /************************************************************************/ void arg_range(char **ps, char *sep, long *val1, long *val2, char *id) { int code; char *s; s = *ps; code = longvalue(&s,val1); if (code != ARG_MISSING) { if (code == ARG_ILLEGAL) { fprintf(stderr,">E %s: bad range\n",id); gt_abort(NULL); } else if (code == ARG_TOOBIG) { fprintf(stderr,">E %s: value too big\n",id); gt_abort(NULL); } } else if (*s == '\0' || !strhaschar(sep,*s)) { fprintf(stderr,">E %s: missing value\n",id); gt_abort(NULL); } else *val1 = -NOLIMIT; if (*s != '\0' && strhaschar(sep,*s)) { ++s; code = longvalue(&s,val2); if (code == ARG_MISSING) *val2 = NOLIMIT; else if (code == ARG_TOOBIG) { fprintf(stderr,">E %s: value too big\n",id); gt_abort(NULL); } else if (code == ARG_ILLEGAL) { fprintf(stderr,">E %s: illegal range\n",id); gt_abort(NULL); } } else *val2 = *val1; *ps = s; } /***********************************************************************/ void writerange(FILE *f, int c, long lo, long hi) /* Write a range. */ { if (c != '\0') fprintf(f,"%c",c); if (lo != -NOLIMIT) fprintf(f,"%ld",lo); if (lo != hi) { fprintf(stderr,":"); if (hi != NOLIMIT) fprintf(f,"%ld",hi); } } /************************************************************************/ void gt_abort(char *msg) /* Write message and halt. */ { if (msg) fprintf(stderr,msg); ABORT(">E gtools"); } /************************************************************************/ char* stringcopy(char *s) /* duplicate string */ { char *scopy; size_t i,len; for (len = 0; s[len] != '\0'; ++len) {} if ((scopy = (char*)ALLOCS(len+1,1)) == NULL) gt_abort(">E stringcopy: malloc failed\n"); for (i = 0; i <= len; ++i) scopy[i] = s[i]; return scopy; } /***************************************************************************** * * * gtools_check() checks that this file is compiled compatibly with the * * given parameters. If not, call exit(1). * * * *****************************************************************************/ void gtools_check(int wordsize, int m, int n, int version) { if (wordsize != WORDSIZE) { fprintf(ERRFILE,"Error: WORDSIZE mismatch in gtools.c\n"); exit(1); } #if MAXN if (m > MAXM) { fprintf(ERRFILE,"Error: MAXM inadequate in gtools.c\n"); exit(1); } if (n > MAXN) { fprintf(ERRFILE,"Error: MAXN inadequate in gtools.c\n"); exit(1); } #endif if (version < NAUTYREQUIRED) { fprintf(ERRFILE,"Error: gtools.c version mismatch\n"); exit(1); } } nauty24r2/config.sub0000700000604200001440000007501011274163463013273 0ustar bdmusers#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. timestamp='2004-06-24' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32r | m32rle | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | msp430-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16c) basic_machine=cr16c-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: nauty24r2/showg.c0000600000604200001440000007052111274163463012607 0ustar bdmusers/* showg.c version 1.6; B D McKay, September 2009. Formerly called readg.c. This is a stand-alone edition of listg.c that does not need nauty or any other files. Use listg in preference if you have installed it. */ #define USAGE "showg [-p#:#l#o#Ftq] [-a|-A|-c|-d|-e] [infile [outfile]]" #define HELPTEXT \ " Write graphs in human-readable format.\n\ \n\ infile is the input file in graph6 or sparse6 format\n\ outfile is the output file\n\ Defaults are standard input and standard output.\n\ \n\ -p#, -p#:#, -p#-# : only display one graph or a sequence of\n\ graphs. The first graph is number 1. A second number\n\ which is empty or zero means infinity.\n\ \n\ -a : write the adjacency matrix\n\ -A : same as -a with a space between entries\n\ -d : write output to satisfy dreadnaut\n\ -c : write compact dreadnaut form with minimal line-breaks\n\ -e : write a list of edges, preceded by the order and the\n\ number of edges\n\ \n\ -o# : specify number of first vertex (default is 0)\n\ -t : write upper triangle only (affects -a, -A, -d and default)\n\ -F : write a form-feed after each graph except the last\n\ -l# : specify screen width limit (default 78, 0 means no limit)\n\ This is not currently implemented with -a or -A.\n\ -q : suppress auxiliary output\n\ \n\ -a, -A, -c, -d and -e are incompatible.\n" /* Version 1.1: Fixed sparse6 input for powers of 2. May 9, 1998. Version 1.3: Declared errno according to ISO C. August 22, 1998. Version 1.4: Change name of getline() so that broken compilers which define the GNU function without being asked don't cause a conflict. June 16, 2006. Version 1.5: Use function prototypes. Avoid errno. Sep 19, 2007. Version 1.6: Very minor tweaks. Hope you all have string.h. Sep 6, 2009. */ /*************************************************************************/ #include #include /* gtools.h : General header for gtools programs. */ #ifndef MAXN #define MAXN 0 #endif #define G6LEN(n) (((n)*((n)-1)/2+5)/6+(n<=SMALLN?1:4)) /* Exact length of graph6 code except for \n\0 */ /* Remove errno: too hard to get portable without configuration * #if defined(__unix) || defined(__unix__) || defined(unix) || \ defined(__ppc__) #include #else int errno = 0; #endif #define ABORT(msg) {if (errno != 0) perror(msg); exit(1);} */ extern long ftell(FILE*); #define BIAS6 63 #define MAXBYTE 126 #define SMALLN 62 #define TOPBIT6 32 #define C6MASK 63 #define GRAPH6_HEADER ">>graph6<<" #define SPARSE6_HEADER ">>sparse6<<" #define GRAPH6 1 #define SPARSE6 2 #define UNKNOWN_TYPE 256 #define HAS_HEADER 512 #define ARG_OK 0 #define ARG_MISSING 1 #define ARG_TOOBIG 2 #define ARG_ILLEGAL 3 #define MAXARG 2000000000L #define NOLIMIT (MAXARG+1L) #define SWBOOLEAN(c,bool) if (sw==c) bool=TRUE; #define SWINT(c,bool,val,id) if (sw==c) \ {bool=TRUE;arg_int(&arg,&val,id);} #define SWRANGE(c,bool,val1,val2,id) if (sw==c) \ {bool=TRUE;arg_range(&arg,&val1,&val2,id);} #define FREES free #define ALLOCS calloc #define DYNALLSTAT(type,name,name_sz) static type *name; static size_t name_sz=0 #define DYNALLOC1(type,name,name_sz,sz,msg) \ if ((size_t)(sz) > name_sz) \ { if (name_sz) FREES(name); name_sz = (sz); \ if ((name=(type*)ALLOCS(sz,sizeof(type))) == NULL) alloc_error(msg);} #define DYNALLOC2(type,name,name_sz,sz1,sz2,msg) \ if ((size_t)(sz1)*(size_t)(sz2) > name_sz) \ { if (name_sz) FREES(name); name_sz = (size_t)(sz1)*(size_t)(sz2); \ if ((name=(type*)ALLOCS((sz1),(sz2)*sizeof(type))) == NULL) alloc_error(msg);} #define DYNFREE(name,name_sz) if (name_sz) {FREES(name); name_sz = 0;} #define DYNREALLOC(type,name,name_sz,sz,msg) \ {if ((size_t)(sz) > name_sz) \ { if ((name = (type*)realloc(name,(sz)*sizeof(type))) == NULL) \ alloc_error(msg); else name_sz = (sz);}} #define alloc_error gt_abort #ifdef __STDC__ #include #include #else #include extern char *calloc(); extern char *malloc(); extern char *realloc(); #endif #ifdef __alpha typedef unsigned int setword; #else typedef unsigned long setword; #endif typedef setword set; typedef setword graph; typedef int boolean; static setword bit[32]= {020000000000,010000000000,04000000000,02000000000, 01000000000,0400000000,0200000000,0100000000,040000000, 020000000,010000000,04000000,02000000,01000000,0400000, 0200000,0100000,040000,020000,010000,04000,02000,01000, 0400,0200,0100,040,020,010,04,02,01}; static int leftbit[] = {8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static int labelorg = 0; #define WORDSIZE 32 #define FIRSTBIT(x) ((x) & 037777600000 ? ((x) & 037700000000 ? \ leftbit[((x)>>24) & 0377] : 8+leftbit[(x)>>16]) \ : ((x) & 0177400 ? 16+leftbit[(x)>>8] : 24+leftbit[x])) #define BITMASK(x) (017777777777 >> (x)) /* setword whose rightmost WORDSIZE-x-1 (numbered) bits are 1 and the rest 0 (0 <= x < WORDSIZE) */ #define TIMESWORDSIZE(w) ((w)<<5) #define SETWD(pos) ((pos)>>5) #define SETBT(pos) ((pos)&037) #define ISELEMENT(setadd,pos) (((setadd)[SETWD(pos)] & bit[SETBT(pos)]) != 0) #define ADDELEMENT(setadd,pos) ((setadd)[SETWD(pos)] |= bit[SETBT(pos)]) #define GRAPHROW(g,v,m) ((set*)(g) + (long)(v) * (long)(m)) #define FALSE 0 #define TRUE 1 /************************************************************************/ #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif #ifndef SEEK_CUR #define SEEK_CUR SEEK_CURRENT #endif static long ogf_linelen; /************************************************************************/ static void gt_abort(char *msg) /* Write message and halt. */ { if (msg) fprintf(stderr,msg); exit(1); } /***************************************************************************** * * * itos(i,s) converts the int i to a nul-terminated decimal character * * string s. The value returned is the number of characters excluding * * the nul. * * * * GLOBALS ACCESSED: NONE * * * *****************************************************************************/ static int itos(int i, char *s) { int digit,j,k; char c; int ans; if (i < 0) { k = 0; i = -i; j = 1; s[0] = '-'; } else { k = -1; j = 0; } do { digit = i % 10; i = i / 10; s[++k] = digit + '0'; } while (i); s[k+1] = '\0'; ans = k + 1; for (;j < k; ++j, --k) { c = s[j]; s[j] = s[k]; s[k] = c; } return(ans); } /***************************************************************************** * * * nextelement(set1,m,pos) = the position of the first element in set set1 * * which occupies a position greater than pos. If no such element exists, * * the value is -1. pos can have any value less than n, including negative * * values. * * * * GLOBALS ACCESSED: none * * * *****************************************************************************/ static int nextelement(set *set1, int m, int pos) { setword setwd; int w; if (pos < 0) { w = 0; setwd = set1[0]; } else { w = SETWD(pos); setwd = set1[w] & BITMASK(SETBT(pos)); } for (;;) { if (setwd != 0) return(TIMESWORDSIZE(w) + FIRSTBIT(setwd)); if (++w == m) return -1; setwd = set1[w]; } } /********************************************************************* opengraphfile(filename,codetype,assumefixed,position) opens and positions a file for reading graphs. filename = the name of the file to open (NULL means stdin, assumed already open) codetype = returns a code for the format. This is a combination of SPARSE6, GRAPH6, UNKNOWN_TYPE and HAS_HEADER. If a header is present, that overrides the data. If there is no header, the first graph is examined. assumefixed = nonzero if files other than stdin should be assumed to be seekable and have equal record sizes. Ignored if there is a sparse6 header or the first graph has sparse6 format. position = the number of the record to position to (the first is number 1; 0 and -NOLIMIT also mean to position at start) If the file starts with ">", there must be a header, either GRAPH6_HEAD or SPARSE6_HEAD. Otherwise opengraphfile() fails. The value returned is a file pointer or NULL. If assumedfixed is not zero and position > 1, the global variable ogf_linelen is set to the length (including \n) of the length of the first record. **********************************************************************/ static FILE* opengraphfile(char *filename, int *codetype, int assumefixed, long position) { FILE *f; int c,firstc; long i,l,pos,pos1,pos2; boolean bad_header; if (filename == NULL) f = stdin; else { f = fopen(filename,"r"); if (f == NULL) { fprintf(stderr,">E opengraphfile: can't open %s\n",filename); return NULL; } } firstc = c = getc(f); if (c == EOF) { *codetype = GRAPH6; return f; } if (c != '>') { *codetype = firstc == ':' ? SPARSE6 : GRAPH6; ungetc(c,f); } else { bad_header = FALSE; if ((c = getc(f)) == EOF || c != '>') bad_header = TRUE; if (!bad_header && ((c = getc(f)) == EOF || (c != 'g' && c != 's'))) bad_header = TRUE; if (!bad_header && c == 'g') { if ((c = getc(f)) == EOF || c != 'r' || (c = getc(f)) == EOF || c != 'a' || (c = getc(f)) == EOF || c != 'p' || (c = getc(f)) == EOF || c != 'h' || (c = getc(f)) == EOF || c != '6' || (c = getc(f)) == EOF || c != '<' || (c = getc(f)) == EOF || c != '<') bad_header = TRUE; else *codetype = GRAPH6 | HAS_HEADER; } else if (!bad_header && c == 's') { if ((c = getc(f)) == EOF || c != 'p' || (c = getc(f)) == EOF || c != 'a' || (c = getc(f)) == EOF || c != 'r' || (c = getc(f)) == EOF || c != 's' || (c = getc(f)) == EOF || c != 'e' || (c = getc(f)) == EOF || c != '6' || (c = getc(f)) == EOF || c != '<' || (c = getc(f)) == EOF || c != '<') bad_header = TRUE; else *codetype = SPARSE6 | HAS_HEADER; } if (bad_header) { fprintf(stderr,">E opengraphfile: illegal header in %s\n", filename == NULL ? "stdin" : filename); *codetype = UNKNOWN_TYPE | HAS_HEADER; return NULL; } } if (position <= 1) return f; if (filename == NULL || !assumefixed || (*codetype&SPARSE6) || firstc == ':') { l = 1; while ((c = getc(f)) != EOF) { if (c == '\n') { ++l; if (l == position) break; } } if (l == position) return f; fprintf(stderr, ">E opengraphfile: can't find line %ld in %s\n",position, filename == NULL ? "stdin" : filename); return NULL; } else { pos1 = ftell(f); if (pos1 < 0) { fprintf(stderr,">E opengraphfile: error on first ftell\n"); return NULL; } for (i = 1; (c = getc(f)) != EOF && c != '\n'; ++i) {} ogf_linelen = i; if (c == EOF) { fprintf(stderr, ">E opengraphfile: required record no present\n"); return NULL; } pos2 = ftell(f); if (pos2 < 0) { fprintf(stderr,">E opengraphfile: error on second ftell\n"); return NULL; } pos = pos1 + (position-1)*(pos2-pos1); if (fseek(f,pos,SEEK_SET) < 0) { fprintf(stderr,">E opengraphfile: seek failed\n"); return NULL; } } return f; } /*********************************************************************/ static char* showg_getline(FILE *f) /* read a line with error checking */ /* includes \n (if present) and \0. Immediate EOF causes NULL return. */ { DYNALLSTAT(char,s,s_sz); int c; long i; DYNALLOC1(char,s,s_sz,500,"showg_getline"); i = 0; while ((c = getc(f)) != EOF && c != '\n') { if (i == s_sz-2) DYNREALLOC(char,s,s_sz,s_sz+1000,"showg_getline"); s[i++] = c; } if (i == 0 && c == EOF) return NULL; if (c == '\n') s[i++] = '\n'; s[i] = '\0'; return s; } /****************************************************************************/ static int graphsize(char *s) /* Get size of graph out of graph6 or sparse6 string. */ { char *p; int n; if (s[0] == ':') p = s+1; else p = s; n = *p++ - BIAS6; if (n > SMALLN) { n = *p++ - BIAS6; n = (n << 6) | (*p++ - BIAS6); n = (n << 6) | (*p++ - BIAS6); } return n; } /****************************************************************************/ static void stringtograph(char *s, graph *g, int m) /* Convert string (graph6 or sparse6 format) to graph. */ /* Assumes g is big enough to hold it. */ { char *p; int n,i,j,k,v,x,nb; long ii; set *gi,*gj; n = graphsize(s); p = s + 1 + (s[0] == ':'); if (n > SMALLN) p += 3; if (TIMESWORDSIZE(m) < n) gt_abort(">E stringtograph: impossible m value\n"); for (ii = (long)m*n; --ii >= 0;) g[ii] = 0; if (s[0] != ':') /* graph6 format */ { k = 1; for (j = 1; j < n; ++j) { gj = GRAPHROW(g,j,m); for (i = 0; i < j; ++i) { if (--k == 0) { k = 6; x = *(p++) - BIAS6; } if (x & TOPBIT6) { gi = GRAPHROW(g,i,m); ADDELEMENT(gi,j); ADDELEMENT(gj,i); } x <<= 1; } } } else /* sparse6 format */ { for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} k = 1; v = 0; for (;;) { if (--k == 0) { k = 6; if (*p == '\n' || *p == '\0') break; else x = *p - BIAS6; ++p; } else x <<= 1; if (x & TOPBIT6) ++v; j = 0; for (i = 0; i < nb; ++i) { if (--k == 0) { k = 6; if (*p == '\n' || *p == '\0') break; else x = *p - BIAS6; ++p; } else x <<= 1; if (x & TOPBIT6) j = (j << 1) | 1; else j <<= 1; } if (i < nb) break; if (j > v) v = j; else if (v < n) { ADDELEMENT(GRAPHROW(g,v,m),j); ADDELEMENT(GRAPHROW(g,j,m),v); } } } } /***********************************************************************/ static graph* /* read graph into nauty format */ readg(FILE *f, graph *g, int reqm, int *pm, int *pn) /* graph6 and sparse6 formats are supported */ /* f = an open file */ /* g = place to put the answer (NULL for dynamic allocation) */ /* reqm = the requested value of m (0 => compute from n) */ /* pm = the actual value of m */ /* pn = the value of n */ { char *s,*p,*readg_line; int m,n,readg_code; if ((readg_line = showg_getline(f)) == NULL) return NULL; s = readg_line; if (s[0] == ':') { readg_code = SPARSE6; p = s + 1; } else { readg_code = GRAPH6; p = s; } while (*p >= BIAS6 && *p <= MAXBYTE) ++p; if (*p == '\0') gt_abort(">E showg: missing newline\n"); else if (*p != '\n') gt_abort(">E showg: illegal character\n"); n = graphsize(s); if (readg_code == GRAPH6 && p - s != G6LEN(n)) { fprintf(stderr,"p-s=%d G6LEN(%d)=%d\n",(int)(p-s),n,G6LEN(n)); gt_abort(">E showg: truncated graph6 line\n"); } if (reqm > 0 && TIMESWORDSIZE(reqm) > n) gt_abort(">E showg: reqm too small\n"); else if (reqm > 0) m = reqm; else m = (n + WORDSIZE - 1) / WORDSIZE; if (g == NULL) { if ((g = (graph*)ALLOCS(n,m*sizeof(graph))) == NULL) gt_abort(">E showg: malloc failed\n"); } *pn = n; *pm = m; stringtograph(s,g,m); return g; } /**************************************************************************/ static int longvalue(char **ps, long *l) { boolean neg,pos; long sofar,last; char *s; s = *ps; pos = neg = FALSE; if (*s == '-') { neg = TRUE; ++s; } else if (*s == '+') { pos = TRUE; ++s; } if (*s < '0' || *s > '9') { *ps = s; return (pos || neg) ? ARG_ILLEGAL : ARG_MISSING; } sofar = 0; for (; *s >= '0' && *s <= '9'; ++s) { last = sofar; sofar = sofar * 10 + (*s - '0'); if (sofar < last || sofar > MAXARG) { *ps = s; return ARG_TOOBIG; } } *ps = s; *l = neg ? -sofar : sofar; return ARG_OK; } /*************************************************************************/ static void arg_int(char **ps, int *val, char *id) { int code; long longval; code = longvalue(ps,&longval); *val = longval; if (code == ARG_MISSING || code == ARG_ILLEGAL) { fprintf(stderr,">E %s: missing argument value\n",id); gt_abort(NULL); } else if (code == ARG_TOOBIG || *val != longval) { fprintf(stderr,">E %s: argument value too large\n",id); gt_abort(NULL); } } /************************************************************************/ static void arg_range(char **ps, long *val1, long *val2, char *id) { int code; char *s; s = *ps; code = longvalue(&s,val1); if (code != ARG_MISSING) { if (code == ARG_ILLEGAL) { fprintf(stderr,">E %s: bad range\n",id); gt_abort(NULL); } else if (code == ARG_TOOBIG) { fprintf(stderr,">E %s: value too big\n",id); gt_abort(NULL); } } else if (*s != ':' && *s != '-') { fprintf(stderr,">E %s: missing value\n",id); gt_abort(NULL); } else *val1 = -NOLIMIT; if (*s == ':' || *s == '-') { ++s; code = longvalue(&s,val2); if (code == ARG_MISSING) *val2 = NOLIMIT; else if (code == ARG_TOOBIG) { fprintf(stderr,">E %s: value too big\n",id); gt_abort(NULL); } else if (code == ARG_ILLEGAL) { fprintf(stderr,">E %s: illegal range\n",id); gt_abort(NULL); } } else *val2 = *val1; *ps = s; } /************************************************************************/ #define LABELORG 0 /* number of first vertex (any integer >= 0) */ #define LINELEN 78 /* max characters per line (0 = no limit) */ static FILE *infile,*outfile; static long nin; extern int labelorg; /***************************************************************************** * * * putsetx(f,set1,curlenp,linelength,m,compress,start) writes the set * * set1 to file f using at most linelength characters per line (excluding * * '\n'). Set elements less than or equal to start are ignored. * * *curlenp is the number of characters on the line so far; it is updated. * * A range j1,j1+1,...,j2 for j2-j1>=2 is written as "j1:j2" if compress * * is nonzero (eg. TRUE); otherwise each element is written separately. * * No final '\n' is written. labelorg is used. * * * * FUNCTIONS CALLED: nextelement(),itos() * * * *****************************************************************************/ static void putsetx(FILE *f, set *set1, int *curlenp, int linelength, int m, boolean compress, int start) { int slen,j1,j2; char s[40]; boolean first; first = TRUE; j1 = start; while ((j1 = nextelement(set1,m,j1)) >= 0) { j2 = j1; if (compress) { while (nextelement(set1,m,j2) == j2 + 1) ++j2; if (j2 == j1+1) j2 = j1; } slen = itos(j1 + labelorg,s); if (j2 >= j1 + 2) { s[slen] = ':'; slen += 1 + itos(j2 + labelorg,&s[slen+1]); } if (*curlenp + slen + 1 >= linelength) { fprintf(f,"\n "); *curlenp = 1; } if (first) { fprintf(f,"%s",s); *curlenp += slen; first = FALSE; } else { fprintf(f," %s",s); *curlenp += slen + 1; } j1 = j2; } } /***************************************************************************** * * * STOLEN FROM naututil.c * * putgraphx(f,g,linelength,m,n) writes a list of the edges of g to f * * using at most linelength characters per line (excluding '\n'). * * If triang, only write the upper triangle. * * labelorg is used. * * * *****************************************************************************/ static void putgraphx(FILE *f, graph *g, int linelength, boolean triang, int m, int n) { int i,curlen; set *pg; for (i = 0, pg = g; i < n; ++i, pg += m) { fprintf(f,"%3d : ",i + labelorg); curlen = 7; putsetx(f,pg,&curlen,linelength,m,FALSE,triang ? i-1 : -1); fprintf(f,";\n"); } } /***************************************************************************/ static void putedges(FILE *f, graph *g, int linelength, int m, int n) /* write list of edges */ { int i,j,curlen,ne; char s[20]; set *pg; ne = 0; for (i = 0, pg = g; i < n; ++i, pg += m) { for (j = i-1; (j = nextelement(pg,m,j)) >= 0;) ++ne; } fprintf(f,"%d %d\n",n,ne); curlen = 0; for (i = 0, pg = g; i < n; ++i, pg += m) { for (j = i-1; (j = nextelement(pg,m,j)) >= 0;) { if (curlen > linelength - 10 && linelength > 0) { fprintf(f,"\n"); curlen = 0; } if (curlen > 0) { fprintf(f," "); curlen += 2; } curlen += itos(i+labelorg,s); fprintf(f,s); fprintf(f," "); curlen += 1 + itos(j+labelorg,s); fprintf(f,s); } } fprintf(f,"\n"); } /***************************************************************************/ static void putcgraph(FILE *f, graph *g, int linelength, int m, int n) /* write compressed form */ { int i,curlen; int semicolons; char s[20]; set *pg; curlen = itos(n,s)+2; fprintf(f,";n%sg",s); semicolons = 0; for (i = 0, pg = g; i < n; ++i, pg += m) { if (nextelement(pg,m,i-1) >= 0) { while (semicolons > 0) { if (curlen >= linelength-1 && linelength > 0) { fprintf(f,"\n "); curlen = 1; } fprintf(f,";"); ++curlen; --semicolons; } putsetx(f,pg,&curlen,linelength,m,FALSE,i-1); semicolons = 1; } else ++semicolons; } fprintf(f,".\n"); } /**************************************************************************/ static void putam(FILE *f, graph *g, int linelength, boolean space, boolean triang, int m, int n) /* write adjacency matrix */ { set *gi; int i,j; boolean first; for (i = 0, gi = (set*)g; i < n - (triang!=0); ++i, gi += m) { first = TRUE; for (j = triang ? i+1 : 0; j < n; ++j) { if (!first && space) putc(' ',f); else first = FALSE; if (ISELEMENT(gi,j)) putc('1',f); else putc('0',f); } putc('\n',f); } } /**************************************************************************/ /**************************************************************************/ int main(int argc, char *argv[]) { graph *g; int m,n,codetype; int argnum,j; char *arg,sw; boolean badargs; long maxin,pval1,pval2; boolean fswitch,pswitch,cswitch,dswitch; boolean aswitch,lswitch,oswitch,Fswitch; boolean Aswitch,eswitch,tswitch,qswitch; int linelength; char *infilename,*outfilename; if (argc > 1 && (strcmp(argv[1],"-help") == 0 || (strcmp(argv[1],"--help") == 0))) { printf("Usage: %s\n\n%s",USAGE,HELPTEXT); exit(0); } if (sizeof(setword) < 4) { fprintf(stderr,">E showg: setword too small\n"); fprintf(stderr," Please report this to bdm@cs.anu.edu.au\n"); exit(1); } fswitch = pswitch = cswitch = dswitch = FALSE; aswitch = lswitch = oswitch = Fswitch = FALSE; Aswitch = eswitch = tswitch = qswitch = FALSE; infilename = outfilename = NULL; linelength = LINELEN; labelorg = 0; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('a',aswitch) else SWBOOLEAN('A',Aswitch) else SWBOOLEAN('c',cswitch) else SWBOOLEAN('d',dswitch) else SWBOOLEAN('e',eswitch) else SWBOOLEAN('f',fswitch) else SWBOOLEAN('F',Fswitch) else SWBOOLEAN('t',tswitch) else SWBOOLEAN('q',qswitch) else SWRANGE('p',pswitch,pval1,pval2,"showg -p") else SWINT('l',lswitch,linelength,"showg -l") else SWINT('o',oswitch,labelorg,"listo -o") else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (labelorg < 0) gt_abort(">E showg: negative origin forbidden.\n"); if ((aswitch!=0) + (Aswitch!=0) + (eswitch!=0) + (dswitch!=0) + (cswitch!=0) > 1) gt_abort(">E showg: -aAecd are incompatible\n"); if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); fprintf(stderr,"Use showg -help to see a list of the options.\n"); exit(1); } if (!pswitch || pval1 < 1) pval1 = 1; if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,fswitch, pswitch ? pval1 : 1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } nin = 0; if (!pswitch || pval2 == NOLIMIT) maxin = NOLIMIT; else if (pval1 < 1) maxin = pval2; else maxin = pval2 - pval1 + 1; while (nin < maxin || maxin == NOLIMIT) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; ++nin; if (Fswitch && nin > 1) fprintf(outfile,"\f"); if (cswitch) putcgraph(outfile,g,linelength,m,n); else if (dswitch) { if (qswitch) fprintf(outfile,"%d\n",n); else { fprintf(outfile,"\n!Graph %ld.\n",pval1+nin-1); fprintf(outfile,"n=%d $=%d g\n",n,labelorg); } putgraphx(outfile,g,linelength,tswitch,m,n); if (!qswitch) fprintf(outfile,"$$\n"); } else { if (qswitch) { if (!eswitch) fprintf(outfile,"%d\n",n); } else fprintf(outfile,"\nGraph %ld, order %d.\n", pval1+nin-1,n); if (aswitch|Aswitch) putam(outfile,g,linelength,Aswitch,tswitch,m,n); else if (eswitch) putedges(outfile,g,linelength,m,n); else putgraphx(outfile,g,linelength,tswitch,m,n); } FREES(g); } exit(0); } nauty24r2/planarity.h0000600000604200001440000005144311274163463013472 0ustar bdmusers/* data structures and stuff for the planarity algorithm Paulette Lieby, Brendan McKay October 2001 */ #ifndef _PLANARITY_H_ #define _PLANARITY_H_ /* The following line must be uncommented for compiling into Magma. */ /* #define PLANAR_IN_MAGMA */ #ifdef PLANAR_IN_MAGMA #include "defs.h" #include "system.h" /* includes "system_math.h" and more */ #else /* not PLANAR_IN_MAGMA */ #include #include #include #include #undef FALSE #undef TRUE #define FALSE 0 #define TRUE 1 #define NP NULL #define ASSERT(x) assert(x) #define DIE() exit(0) #define mem_malloc malloc #define mem_realloc realloc #define mem_free free #include "naututil.h" CPUDEFS #define time_current_user() CPUTIME #endif /* not PLANAR_IN_MAGMA */ #include "nauty.h" /* max number of edges (and directed edges) for the embed_graph data structure: 1 more than for a (possibly) planar graph to allow search for obstructions 1. if the graph is planar the embedding cannot possibly contain more than 3*n - 6 edges (including the short cut edges) 2. if the graph is non planar, when retrieving and marking the obstruction, we introduce EXACTLY one edge crossing */ #define MAXE(n) ((n) > 1 ? 3*(n) - 5 : 0) #define MAXDE(n) (6*(n) - 10) #define NIL -1 #define CUTV -2 /* obviously used in diff. circ. than NILSIGN */ #define NILSIGN -2 #define CCLOCKW 1 #define CLOCKW -1 #define TE 1 #define BE 2 #define SCE 3 /* various "marks" for various purposes, ONLY for the t_ver_edge str note: do NOT use a mark in {0,..,n} since those values are used either while initialising or in the walkup procedure */ #define MARK_EMBED(n) ((n)+1) #define MARK_EXT_FACE(n) ((n)+2) #define MARK_EXT_FACE_L(n) ((n)+3) #define MARK_EXT_FACE_R(n) ((n)+4) #define MARK_X_Y_PATH(n) ((n)+5) #define MARK_MINORS(n) ((n)+6) #define MIN_EMBED_MARK 0 /* ONLY for the t_embed_sparse_rep str */ typedef enum { MINOR_A, MINOR_B, MINOR_C, MINOR_D, MINOR_E, MINOR_E1, MINOR_E2, MINOR_E3, MINOR_E4, MINOR_E5, NBR_MINORS } minor; /* a basic doubly linked circular list storing vertices/edges from the "big" 2*n + 2(3*n-5) array of vertices/edges only used internally in the planarity tester: especially where ordering of the vertices is important */ typedef struct dlcl { int info; /* info is: - position in "big" array */ int in_adjl; /* if relevant, the pos in the adjl. list of this edge */ int twin_in_adjl; /* if relevant, the pos in the adjl. list of the twin of this edge */ int mult; /* if relevant, #occurences if this edge (when graph is not simple */ struct dlcl * right; struct dlcl * left; } t_dlcl; /* a common structure for both (virtual) vertex & edge */ typedef struct ver_edge { /* vertex data */ int label; int DFS_parent; int least_ancestor; int lowpoint; t_dlcl * separated_DFS_child_list; t_dlcl * rep_in_parent_list; t_dlcl * pertinent_bicomp_list; int adjacent_to; int visited; /* edge data */ int neighbour; int in_adjl; int twin_in_adjl; int mult; int type; int sign; /* link the lot in a doubly linked circular list */ /* links indicate positions in the array of vertices/edges */ int link[2]; } t_ver_edge; /* data structure for the merge queue */ typedef struct merge_queue { int start, end; int *b; } t_merge_queue; /* data structure for the sparse graph representation: the array of vertices */ typedef struct ver_sparse_rep { int first_edge; /* can be index into an adj. list or an embedding */ } t_ver_sparse_rep; /* data structure for the sparse graph representation: a record in the adjacency list */ typedef struct adjl_sparse_rep { int end_vertex; int next; /* next in list as an index in the adj. list */ } t_adjl_sparse_rep; /* data structure for the sparse graph representation: a record in the embedding */ typedef struct embed_sparse_rep { int in_adjl;/* index of edge in adj. list */ int next; /* next edge in embedding */ int prev; /* previous edge in embedding */ int inv; /* inverse edge */ int mark; /* a spot for marking */ } t_embed_sparse_rep; /* data structure for the sparse graph representation: a record an individual edge */ typedef struct edge_sparse_rep { int ends[2]; } t_edge_sparse_rep; /* data structure for the sparse graph representation: a record for a component */ typedef struct comp_sparse_rep { int nbr_v; /* nbr of vertices */ int *v; /* the actual vertices */ } t_comp_sparse_rep; typedef struct graph_sparse_rep { t_ver_sparse_rep *V; int n; t_adjl_sparse_rep *A; int size_A; int pos_A; int nbr_e; /* ALWAYS # directed edges */ } t_graph_sparse_rep; /* * embed_graph_protos.h */ /* aproto: file embed_graph/sparseg_adjl_pred.c */ extern boolean sparseg_adjl_dir_edge_exists (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int); extern boolean sparseg_adjl_u_adj_v (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int); extern boolean sparseg_adjl_sub (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, t_ver_sparse_rep *, int, t_adjl_sparse_rep *); extern boolean sparseg_adjl_eq (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, t_ver_sparse_rep *, int, t_adjl_sparse_rep *); /* aproto: endfile */ /* aproto: file embed_graph/VES_misc.c */ extern boolean embedg_VES_is_vertex (int, int); extern boolean embedg_VES_is_virtual_vertex (int, int); extern boolean embedg_VES_is_edge (int, int); extern boolean embedg_VES_is_tree_edge (t_ver_edge *, int, int); extern boolean embedg_VES_is_back_edge (t_ver_edge *, int, int); extern boolean embedg_VES_is_short_cut_edge (t_ver_edge *, int, int); extern void embedg_VES_print_vertex (int, int); extern void embedg_VES_print_virtual_vertex (t_ver_edge *, int, int); extern void embedg_VES_print_any_vertex (t_ver_edge *, int, int); extern void embedg_VES_print_any_rec (t_ver_edge *, int, int); extern void embedg_VES_print_edge (t_ver_edge *, int, int); extern void embedg_VES_print_flipped_edges (t_ver_edge *, int, int); extern int embedg_VES_get_edge_from_ver (t_ver_edge *, int, int); extern int embedg_VES_get_ver_from_edge (t_ver_edge *, int, int); extern int embedg_VES_get_twin_edge (t_ver_edge *, int, int); extern int embedg_VES_get_ver_from_virtual (t_ver_edge *, int, int); extern int embedg_VES_get_ver (t_ver_edge *, int, int); extern int embedg_VES_get_next_in_dlcl (t_ver_edge *, int, int, int); extern void embedg_VES_walk_bicomp (t_ver_edge *, int, int, int); extern void embedg_VES_print_adj_list (t_ver_edge *, int, int, boolean); extern boolean embedg_VES_is_adj_list_consistent (t_ver_edge *, int, int); extern boolean embedg_VES_are_adj_lists_consistent (t_ver_edge *, int); extern void embedg_VES_remove_edge (t_ver_edge *, int, int); extern void embedg_VES_set_orientation (t_ver_edge *, int, int *); /* aproto: endfile */ /* aproto: file embed_graph/embed_edge.c */ extern void embedg_VES_embed_edge (t_ver_edge *, int, int *, int, int, int, int, int); extern void embedg_VES_add_edge (t_ver_edge *, int, int *, int, int, boolean, int); /* aproto: endfile */ /* aproto: file embed_graph/embedg_misc.c */ extern void embedg_VES_delete (t_ver_edge *, int); extern void embedg_VES_print (t_ver_edge *, int); extern void embedg_VES_print_bigcomps (t_ver_edge *, int); /* aproto: endfile */ /* aproto: file embed_graph/ext_face_walk.c */ extern void embedg_VES_get_succ_on_ext_face (t_ver_edge *, int, int, int, boolean, int, int *, int *); extern void embedg_VES_get_succ_active_on_ext_face (t_ver_edge *, int, int, int, int, boolean, int, int *, int *); extern void embedg_VES_get_succ_ext_active_on_ext_face (t_ver_edge *, int, int, int, int, boolean, int, int *, int *); extern void embedg_VES_get_succ_pertinent_on_ext_face (t_ver_edge *, int, int, int, int, boolean, int, int *, int *); /* aproto: endfile */ /* aproto: file embed_graph/isolator.c */ extern int embedg_iso_get_c_of_v (t_ver_edge *, int, int, int); extern boolean embedg_iso_is_minor_A (t_ver_edge *, int, int *, int, int, int *); extern void embedg_iso_get_x_y_w (t_ver_edge *, int, int, int, int, int, int, int, int *, int *, int *); extern boolean embedg_iso_is_minor_B (t_ver_edge *, int, int *, int, int, int *, int *, int *); extern void embedg_iso_get_highest_x_y_path (t_ver_edge *, int, int, int, int, int, int, int, int, int, int **, int **, int *, int *, boolean *, boolean *, boolean *); /* aproto: endfile */ /* aproto: file embed_graph/mark_kur.c */ extern boolean embedg_VES_is_ext_face_marked (t_ver_edge *, int, int, int); extern void embedg_mark_minor_A (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int); extern void embedg_mark_minor_B (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int, int, int); extern void embedg_mark_minor_C (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int, int, int, int *, int *, int, boolean, boolean); extern void embedg_mark_minor_D (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int, int, int, int *, int *, int, int); extern minor embedg_mark_minor_E (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, int, int, int, int *, int *, int); /* aproto: endfile */ /* aproto: file embed_graph/merge_bicomps.c */ extern void embedg_VES_merge_simple_bicomps (t_ver_edge *, int, int, int, int, int); extern void embedg_VES_merge_pertinent_bicomps (t_ver_edge *, int, int, int, int, int); /* aproto: endfile */ /* aproto: file embed_graph/merge_queue_misc.c */ extern t_merge_queue embedg_merge_queue_new (int); extern void embedg_merge_queue_delete (t_merge_queue); extern boolean embedg_merge_queue_empty (t_merge_queue); extern void embedg_merge_queue_print (t_merge_queue); extern void embedg_merge_queue_append (t_merge_queue *, t_ver_edge *, int, int, int, int, int); extern void embedg_merge_queue_append_vertex (t_merge_queue *, t_ver_edge *, int, int, int); extern void embedg_merge_queue_append_virtual_vertex (t_merge_queue *, t_ver_edge *, int, int, int); extern void embedg_merge_queue_get (t_merge_queue *, int *, int *, int *, int *); extern void embedg_merge_queue_prune (t_merge_queue *, int *, int *, int *, int *); /* aproto: endfile */ /* aproto: file embed_graph/obstruction.c */ extern void embedg_obstruction (t_ver_sparse_rep *, t_adjl_sparse_rep *, t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int, t_ver_sparse_rep **, t_adjl_sparse_rep **, int *); extern minor embedg_mark_obstruction (t_dlcl **, t_dlcl **, t_ver_edge *, int, int *, int, int); /* aproto: endfile */ /* aproto: file embed_graph/post_dfs_preproc.c */ extern t_dlcl *sparseg_order_wrt_lowpoint (int, int *, int *, t_dlcl *); extern int *sparseg_find_least_ancestor (int, t_dlcl **); extern int *sparseg_find_dfs_parent (int, t_dlcl **); /* aproto: endfile */ /* aproto: file embed_graph/proper_face_walk.c */ extern boolean embedg_VES_get_succ_on_proper_face_with_avoidance (t_ver_edge *, int, int, int, int, boolean, int, int *, int *, int *); extern void embedg_VES_get_succ_on_proper_face (t_ver_edge *, int, int, int, int, int, int *, int *, int *); extern void embedg_VES_walk_proper_face (t_ver_edge *, int, int, int, boolean, int); /* aproto: endfile */ /* aproto: file embed_graph/vertex_activity.c */ extern boolean embedg_VES_is_ver_pertinent (t_ver_edge *, int, int, int); extern boolean embedg_VES_is_ver_ext_active (t_ver_edge *, int, int, int); extern boolean embedg_VES_is_ver_int_active (t_ver_edge *, int, int, int); extern boolean embedg_VES_is_ver_inactive (t_ver_edge *, int, int, int); /* aproto: endfile */ /* aproto: file embed_graph/walkdown.c */ extern t_merge_queue embedg_walkdown (t_ver_edge *, int, int *, int); /* aproto: endfile */ /* aproto: file embed_graph/sparseg_dlcl_misc.c */ extern void sparseg_dlcl_delete (t_dlcl **, int); extern void sparseg_dlcl_print (t_dlcl **, int); extern boolean sparseg_dlcl_is_adjacent (t_dlcl **, int, int, int, t_dlcl **); extern void sparseg_dlcl_append_to_neigh_list (t_dlcl **, int, int, int, int); extern void sparseg_dlcl_to_sparseg (t_dlcl **, int, int, t_ver_sparse_rep **, t_adjl_sparse_rep **); extern boolean sparseg_dlcl_sub (t_dlcl **, int, t_dlcl **, int); /* aproto: endfile */ /* aproto: file embed_graph/walkup.c */ extern void embedg_walkup (t_ver_edge *, int, int, t_dlcl *); /* aproto: endfile */ /* aproto: file embed_graph/dfs_preprocessing.c */ extern void sparseg_adjl_dfs_preprocessing (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int *, int **, int **, int **, t_dlcl ***, t_dlcl ***, int **, int **, t_dlcl ***); /* aproto: endfile */ /* aproto: file embed_graph/planar_by_edge_addition.c */ extern boolean sparseg_adjl_is_planar (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int *, t_dlcl ***, t_dlcl ***, t_dlcl ***, t_ver_edge **, int *, int *, int *); /* aproto: endfile */ /* aproto: file embed_graph/recover.c */ extern void embedg_recover_embedding (t_ver_sparse_rep *, t_adjl_sparse_rep *, t_ver_edge *, int, int, t_dlcl **, t_ver_sparse_rep **, t_embed_sparse_rep **); extern void embedg_recov_embed_walk_proper_face (int, int, t_adjl_sparse_rep *, t_embed_sparse_rep *, boolean, int); extern boolean embedg_check_recov_embedding (int, int, int, t_ver_sparse_rep *, t_adjl_sparse_rep *, t_embed_sparse_rep *); extern t_dlcl **embedg_recover_obstruction (t_ver_edge *, int, minor, int *); extern boolean embedg_check_recov_obs (t_dlcl **, int, minor); /* aproto: endfile */ /* aproto: file embed_graph/planar_alg_init.c */ extern t_ver_edge *embedg_planar_alg_init (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int *, int *, t_dlcl ***, t_dlcl ***, t_dlcl ***); /* aproto: endfile */ /* aproto: file embed_graph/dlcl_misc.c */ extern t_dlcl *embedg_dlcl_rec_new (int); extern void embedg_dlcl_rec_print (t_dlcl *); extern void embedg_dlcl_print (t_dlcl *); extern t_dlcl *embedg_dlcl_rec_append (t_dlcl *, t_dlcl *); extern t_dlcl *embedg_dlcl_rec_prepend (t_dlcl *, t_dlcl *); extern t_dlcl *embedg_dlcl_cat (t_dlcl *, t_dlcl *); extern t_dlcl *embedg_dlcl_find (t_dlcl *, int); extern t_dlcl *embedg_dlcl_find_with_NIL_twin_in_adjl (t_dlcl *, int); extern t_dlcl *embedg_dlcl_delete_first (t_dlcl *); extern t_dlcl *embedg_dlcl_delete_rec (t_dlcl *, t_dlcl *); extern boolean embedg_dlcl_is_empty (t_dlcl *); extern t_dlcl *embedg_dlcl_list_next (t_dlcl *); extern t_dlcl *embedg_dlcl_list_prev (t_dlcl *); extern t_dlcl *embedg_dlcl_list_last (t_dlcl *); extern void embedg_dlcl_delete (t_dlcl *); extern t_dlcl *embedg_dlcl_copy (t_dlcl *); extern int embedg_dlcl_length (t_dlcl *); /* aproto: endfile */ /* aproto: file embed_graph/sparseg_adjl.c */ extern boolean sparseg_adjl_plan_and_iso (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int *, t_ver_sparse_rep **, t_adjl_sparse_rep **, t_embed_sparse_rep **, int *); extern int *sparseg_adjl_footprint (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int); extern void sparseg_adjl_print (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, boolean); extern void sparseg_adjl_embed_print (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, t_embed_sparse_rep *, boolean); extern graph *sparseg_adjl_to_nauty_graph (t_ver_sparse_rep *, int, t_adjl_sparse_rep *); extern t_edge_sparse_rep *sparseg_adjl_edges (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, boolean); /* aproto: endfile */ /* aproto: file embed_graph/embedding.c */ extern void embedg_embedding (t_ver_sparse_rep *, t_adjl_sparse_rep *, t_ver_edge *, int, int, int, int, t_dlcl **, t_ver_sparse_rep **, t_embed_sparse_rep **); extern void embedg_remove_SCE (t_ver_edge *, int, int); extern int *embedg_vertices_orientation (t_ver_edge *, int); extern int embedg_merge_remaining_virtual (t_ver_edge *, int); extern int embedg_nbr_faces (t_ver_edge *, int, int, int *, int *); extern boolean embedg_is_embed_valid (t_ver_edge *, int, int, int, int *, int *); /* aproto: endfile */ /* aproto: file embed_graph/sparseg_adjl_modify.c */ extern boolean sparseg_adjl_add_edge (t_ver_sparse_rep *, int, t_adjl_sparse_rep **, int *, int *, int, int, boolean); extern boolean sparseg_adjl_add_edge_no_extend (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int *, int, int, boolean); extern boolean sparseg_adjl_add_dir_edge (t_ver_sparse_rep *, int, t_adjl_sparse_rep **, int *, int *, int, int, boolean); extern boolean sparseg_adjl_add_dir_edge_no_extend (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int *, int, int, boolean); extern boolean sparseg_adjl_remove_edge_no_red (t_ver_sparse_rep *, t_adjl_sparse_rep *, int, int); extern boolean sparseg_adjl_remove_dir_edge_no_red (t_ver_sparse_rep *, t_adjl_sparse_rep *, int, int); extern int sparseg_adjl_remove_all_dir_edge_no_red (t_ver_sparse_rep *, t_adjl_sparse_rep *, int, int); extern void sparseg_adjl_add_vertices (t_ver_sparse_rep **, int, int); extern void sparseg_adjl_add_vertices_no_extend (t_ver_sparse_rep *, int, int); extern void sparseg_adjl_remove_vertex (t_ver_sparse_rep **, int, t_adjl_sparse_rep *, int, int, int *); extern void sparseg_adjl_remove_vertex_no_red (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int *); extern void sparseg_adjl_relabel_vertex (t_adjl_sparse_rep *, int, int); /* aproto: endfile */ /* aproto: file embed_graph/sparseg_adjl_misc.c */ extern void sparseg_adjl_assign_V (t_ver_sparse_rep *, t_ver_sparse_rep *, int); extern t_ver_sparse_rep *sparseg_adjl_dup_V (t_ver_sparse_rep *, int); extern void sparseg_adjl_assign_A (t_adjl_sparse_rep *, t_adjl_sparse_rep *, int); extern t_adjl_sparse_rep *sparseg_adjl_dup_A (t_adjl_sparse_rep *, int); extern void sparseg_embed_assign_E (t_embed_sparse_rep *, t_embed_sparse_rep *, int); extern t_embed_sparse_rep *sparseg_embed_dup_E (t_embed_sparse_rep *, int); extern void sparseg_adjl_underlying_undir (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, t_ver_sparse_rep **, t_adjl_sparse_rep **, int *, int *); extern void sparseg_adjl_edge_union (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, t_ver_sparse_rep *, t_adjl_sparse_rep *, boolean, t_ver_sparse_rep **, t_adjl_sparse_rep **, int *, int *); extern void sparseg_adjl_add_edges (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int *, t_ver_sparse_rep *, t_adjl_sparse_rep *, boolean, int *); /* aproto: endfile */ /* aproto: file embed_graph/degree.c */ extern int *sparseg_adjl_degree_seq (t_ver_sparse_rep *, int, t_adjl_sparse_rep *); /* aproto: endfile */ /* aproto: file embed_graph/neighbours.c */ extern void sparseg_adjl_vertex_out_neighbours (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int **, int *); extern void sparseg_adjl_vertex_in_neighbours (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int **, int *); /* aproto: endfile */ /* aproto: file embed_graph/misc.c */ extern void sparseg_comp_delete (t_comp_sparse_rep *, int); extern void sparseg_comp_print (t_comp_sparse_rep *, int); /* aproto: endfile */ /* aproto: file embed_graph/dfs_things.c */ extern void sparseg_adjl_dfs_things (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, boolean, int *, t_ver_sparse_rep **, t_adjl_sparse_rep **, int *, int **, int **, int **, int **, int **, int *, int **, int *, t_comp_sparse_rep **); extern void sparseg_adjl_dfs_add_vertex_to_comp (t_comp_sparse_rep **, int *, int); extern void sparseg_adjl_dfs_create_new_comp (t_comp_sparse_rep **, int *); extern void sparseg_adjl_from_comps_to_sparseg_adjl (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, t_comp_sparse_rep *, int, t_graph_sparse_rep **); extern void sparseg_adjl_from_start_comp_to_sparseg_adjl (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int *, t_graph_sparse_rep **); /* aproto: endfile */ /* aproto: file embed_graph/dfs_for_digraph.c */ extern void sparseg_adjl_dfs_digraph (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, int, int, t_ver_sparse_rep **, t_adjl_sparse_rep **, int *, int **, int **, int **, int **, int **, int *, t_comp_sparse_rep **); /* aproto: endfile */ /* aproto: file embed_graph/bfs.c */ extern void sparseg_adjl_bfs (t_ver_sparse_rep *, int, t_adjl_sparse_rep *, boolean, int, t_ver_sparse_rep **, t_adjl_sparse_rep **, int *); /* aproto: endfile */ /* aproto: file embed_graph/faces.c */ extern void sparseg_adjl_walk_proper_face (int, t_adjl_sparse_rep *, t_embed_sparse_rep *, int, boolean, int, int *, t_edge_sparse_rep *); extern void sparseg_adjl_get_face_edges (int, t_adjl_sparse_rep *, int, t_embed_sparse_rep *, int, t_edge_sparse_rep **, int *, boolean, int); /* aproto: endfile */ #endif /* _PLANARITY_H_ */ nauty24r2/newedgeg.c0000600000604200001440000001226411274163463013245 0ustar bdmusers/* newedgeg.c version 1.1; B D McKay, Dec 2005. */ #define USAGE "newedgeg [-lq] [infile [outfile]]" #define HELPTEXT \ " For each pair of non-adjacent edges, output the graph obtained\n\ by subdividing the edges and joining the new vertices.\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -l Canonically label outputs\n\ -q Suppress auxiliary information\n" /*************************************************************************/ #include "gtools.h" #include "gutils.h" static FILE *outfile; static long nout; static int outcode; /*************************************************************************/ static void newedge(graph *g1, int m1, int n1, int v1, int v2, int w1, int w2, graph *g2, int m2) /* Make g2 by subdividing edges v1-v2 and w1-w2 in g1 and adding an edge between them. Must have m2 >= m1. */ { int i,j; setword *s1,*s2; s1 = g1; s2 = g2; for (i = 0; i < n1; ++i) { for (j = 0; j < m1; ++j) *(s2++) = *(s1++); for (; j < m2; ++j) *(s2++) = 0; } s2 = GRAPHROW(g2,v1,m2); DELELEMENT(s2,v2); ADDELEMENT(s2,n1); s2 = GRAPHROW(g2,v2,m2); DELELEMENT(s2,v1); ADDELEMENT(s2,n1); s2 = GRAPHROW(g2,w1,m2); DELELEMENT(s2,w2); ADDELEMENT(s2,n1+1); s2 = GRAPHROW(g2,w2,m2); DELELEMENT(s2,w1); ADDELEMENT(s2,n1+1); s2 = GRAPHROW(g2,n1,m2); EMPTYSET(s2,m2); ADDELEMENT(s2,v1); ADDELEMENT(s2,v2); ADDELEMENT(s2,n1+1); s2 = GRAPHROW(g2,n1+1,m2); EMPTYSET(s2,m2); ADDELEMENT(s2,w1); ADDELEMENT(s2,w2); ADDELEMENT(s2,n1); } /*************************************************************************/ static void na_newedge(graph *g1, int m1, int n1, boolean dolabel) /* Make all graphs by non-adjacent edge addition. */ { int n2,m2; int v1,v2,w1,w2; set *sv1,*sw1; graph *gq; #if MAXN graph h[MAXN*MAXM]; grapg g2[MAXN*MAXM]; #else DYNALLSTAT(graph,h,h_sz); DYNALLSTAT(graph,g2,g2_sz); #endif n2 = n1 + 2; m2 = (n2 + WORDSIZE - 1) / WORDSIZE; if (m2 < m1) m2 = m1; #if !MAXN DYNALLOC2(graph,g2,g2_sz,m2,n2,"newedgeg"); if (dolabel) DYNALLOC2(graph,h,h_sz,m2,n2,"newedgeg"); #endif for (v1 = 0, sv1 = g1; v1 < n1-3; ++v1, sv1 += m1) for (w1 = v1+1, sw1 = sv1 + m1; w1 < n1-1; ++w1, sw1 += m1) { for (v2 = v1; (v2 = nextelement(sv1,m1,v2)) >= 0; ) for (w2 = w1; (w2 = nextelement(sw1,m1,w2)) >= 0; ) { if (v2 == w1 || v2 == w2) continue; newedge(g1,m1,n1,v1,v2,w1,w2,g2,m2); gq = g2; if (dolabel) { fcanonise(g2,m2,n2,h,NULL,FALSE); /* FIXME (loops) */ gq = h; } if (outcode == SPARSE6) writes6(outfile,gq,m2,n2); else writeg6(outfile,gq,m2,n2); ++nout; } } } /*************************************************************************/ int main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile; boolean badargs,dolabel,quiet; int j,m,n,argnum; int codetype; graph *g; long nin; char *arg,sw; double t; HELP; infilename = outfilename = NULL; badargs = FALSE; dolabel = quiet = FALSE; argnum = 0; badargs = FALSE; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('l',dolabel) else SWBOOLEAN('q',quiet) else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!quiet) { fprintf(stderr,">A newedgeg"); if (dolabel) fprintf(stderr," -l"); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); fflush(stderr); } if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (!outfilename || outfilename[0] == '-') { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"Can't open output file %s\n",outfilename); gt_abort(NULL); } if (codetype&SPARSE6) outcode = SPARSE6; else outcode = GRAPH6; if (codetype&HAS_HEADER) { if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); } if (dolabel) nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); nin = nout = 0; t = CPUTIME; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; #if MAXN if (n > MAXN-2) { fprintf(stderr,">E newedgeg: input too large\n"); exit(1); } #endif ++nin; na_newedge(g,m,n,dolabel); FREES(g); } t = CPUTIME - t; if (!quiet) fprintf(stderr, ">Z %ld graphs read from %s, %ld written to %s; %3.2f sec.\n", nin,infilename,nout,outfilename,t); exit(0); } nauty24r2/shortg.c0000600000604200001440000004624111405400302012746 0ustar bdmusers/* shortg.c version 2.0; B D McKay, Jun 2010 */ #define USAGE \ "shortg [-qvkdu] [-i# -I#:# -K#] [-fxxx] [-Tdir] [infile [outfile]]" #define HELPTEXT \ " Remove isomorphs from a file of graphs.\n\ \n\ If outfile is omitted, it is taken to be the same as infile\n\ If both infile and outfile are omitted, input will be taken\n\ from stdin and written to stdout\n\ \n\ The output file has a header if and only if the input file does.\n\ \n\ -s force output to sparse6 format\n\ -g force output to graph6 format\n\ If neither -s or -g are given, the output format is\n\ determined by the header or, if there is none, by the\n\ format of the first input graph.\n\ -k output graphs have the same labelling and format as the inputs.\n\ Otherwise, output graphs have canonical labelling.\n\ -s and -g are ineffective if -k is given. If none of -sgk are\n\ given, the output format is determined by the header or, if there\n\ is none, by the format of the first input graph.\n\ \n\ -v write to stderr a list of which input graphs correspond to which\n\ output graphs. The input and output graphs are both numbered\n\ beginning at 1. A line like\n\ 23 : 30 154 78\n\ means that inputs 30, 154 and 78 were isomorphic, and produced\n\ output 23.\n\ \n\ -d include in the output only those inputs which are isomorphic\n\ to another input. If -k is specified, all such inputs are\n\ included in their original labelling. Without -k, only one\n\ member of each nontrivial isomorphism class is written,\n\ with canonical labelling.\n\ \n\ -fxxx Specify a partition of the point set. xxx is any\n\ string of ASCII characters except nul. This string is\n\ considered extended to infinity on the right with the\n\ character 'z'. One character is associated with each point,\n\ in the order given. The labelling used obeys these rules:\n\ (1) the new order of the points is such that the associated\n\ characters are in ASCII ascending order\n\ (2) if two graphs are labelled using the same string xxx,\n\ the output graphs are identical iff there is an\n\ associated-character-preserving isomorphism between them.\n\ -i# select an invariant (1 = twopaths, 2 = adjtriang(K), 3 = triples,\n\ 4 = quadruples, 5 = celltrips, 6 = cellquads, 7 = cellquins,\n\ 8 = distances(K), 9 = indsets(K), 10 = cliques(K), 11 = cellcliq(K),\n\ 12 = cellind(K), 13 = adjacencies, 14 = cellfano, 15 = cellfano2)\n\ -I#:# select mininvarlevel and maxinvarlevel (default 1:1)\n\ -K# select invararg (default 3)\n\ \n\ -u Write no output, just report how many graphs it would have output.\n\ In this case, outfile is not permitted.\n\ -Tdir Specify that directory \"dir\" will be used for temporary disk\n\ space by the sort subprocess. The default is usually /tmp.\n\ -q Suppress auxiliary output\n" /*************************************************************************/ #include "gtools.h" #include "nautinv.h" #if (HAVE_PIPE==0) || (HAVE_WAIT==0) #error Forget it, either pipe() or wait() are not available #endif #if HAVE_SIGNAL_H #include #endif #if HAVE_SYS_WAIT_H #include #else #if !HAVE_PID_T typedef int pid_t; #endif #endif #if !PIPE_DEC int pipe(int*); #endif #if !FDOPEN_DEC FILE *fdopen(int, const char*); #endif #if SORT_NEWKEY == 0 #define SORTCOMMAND SORTPROG,SORTPROG,"-u","+0","-1" #define VSORTCOMMAND1 SORTPROG,SORTPROG #define VSORTCOMMAND2 SORTPROG,SORTPROG,"+0","-1","+2" #define SORTCOMMANDT SORTPROG,SORTPROG,"-T",tempdir,"-u","+0","-1" #define VSORTCOMMANDT1 SORTPROG,SORTPROG,"-T",tempdir #define VSORTCOMMANDT2 SORTPROG,SORTPROG,"-T",tempdir,"+0","-1","+2" #else #define SORTCOMMAND SORTPROG,SORTPROG,"-u","-k","1,1" #define VSORTCOMMAND1 SORTPROG,SORTPROG #define VSORTCOMMAND2 SORTPROG,SORTPROG,"-k","1,1","-k","3" #define SORTCOMMANDT SORTPROG,SORTPROG,"-T",tempdir,"-u","-k","1,1" #define VSORTCOMMANDT1 SORTPROG,SORTPROG,"-T",tempdir #define VSORTCOMMANDT2 SORTPROG,SORTPROG,"-T",tempdir,"-k","1,1","-k","3" #endif static struct invarrec { void (*entrypoint)(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int); char *name; } invarproc[] = {{NULL, "none"}, {twopaths, "twopaths"}, {adjtriang, "adjtriang"}, {triples, "triples"}, {quadruples, "quadruples"}, {celltrips, "celltrips"}, {cellquads, "cellquads"}, {cellquins, "cellquins"}, {distances, "distances"}, {indsets, "indsets"}, {cliques, "cliques"}, {cellcliq, "cellcliq"}, {cellind, "cellind"}, {adjacencies, "adjacencies"}, {cellfano, "cellfano"}, {cellfano2, "cellfano2"}}; #define NUMINVARS ((int)(sizeof(invarproc)/sizeof(struct invarrec))) /**************************************************************************/ static pid_t beginsort(FILE **sortin, FILE **sortout, char *tempdir, boolean vdswitch, boolean keep) /* begin sort process, open streams for i/o to it, and return its pid */ { int pid; int inpipe[2],outpipe[2]; if (pipe(inpipe) < 0 || pipe(outpipe) < 0) gt_abort(">E shortg: can't create pipes to sort process\n"); if ((pid = fork()) < 0) gt_abort(">E shortg: can't fork\n"); if (pid > 0) /* parent */ { close(inpipe[0]); close(outpipe[1]); if ((*sortin = fdopen(inpipe[1],"w")) == NULL) gt_abort(">E shortg: can't open stream to sort process\n"); if ((*sortout = fdopen(outpipe[0],"r")) == NULL) gt_abort(">E shortg: can't open stream from sort process\n"); } else /* child */ { SET_C_COLLATION; close(inpipe[1]); close(outpipe[0]); if (dup2(inpipe[0],0) < 0 || dup2(outpipe[1],1) < 0) gt_abort(">E shortg: dup2 failed\n"); if (tempdir == NULL) { if (vdswitch) if (keep) execlp(VSORTCOMMAND2,NULL); else execlp(VSORTCOMMAND1,NULL); else execlp(SORTCOMMAND,NULL); } else { if (vdswitch) if (keep) execlp(VSORTCOMMANDT2,NULL); else execlp(VSORTCOMMANDT1,NULL); else execlp(SORTCOMMANDT,NULL); } gt_abort(">E shortg: can't start sort process\n"); } return pid; } /**************************************************************************/ static void tosort(FILE *f, char *cdstr, char *dstr, nauty_counter index) /* write one graph to sort process cdstr = canonical string dstr = optional original string index = optional index number */ { int i; char buff[30]; for (i = 0; cdstr[i] != '\n'; ++i) {} cdstr[i] = '\0'; writeline(f,cdstr); if (dstr != NULL) { writeline(f," "); for (i = 0; dstr[i] != '\n'; ++i) {} dstr[i] = '\0'; writeline(f,dstr); } if (index > 0) { #if LONG_LONG_COUNTERS sprintf(buff,"\t%09llu\n",index); #else sprintf(buff,"\t%09lu\n",index); #endif writeline(f,buff); } else writeline(f,"\n"); } /**************************************************************************/ static boolean fromsort(FILE *f, char **cdstr, char **dstr, nauty_counter *index) /* read one graph from sort process */ { int j; char *s; if ((s = gtools_getline(f)) == NULL) return FALSE; *cdstr = s; for (j = 0; s[j] != ' ' && s[j] != '\t' && s[j] != '\n'; ++j) {} if (s[j] == ' ') { s[j] = '\0'; *dstr = &s[j+1]; for (++j; s[j] != '\t' && s[j] != '\n'; ++j) {} } else *dstr = NULL; if (s[j] == '\t') { #if LONG_LONG_COUNTERS if (sscanf(&s[j+1],"%llu",index) != 1) #else if (sscanf(&s[j+1],"%lu",index) != 1) #endif gt_abort(">E shortg: index field corrupted\n"); } else *index = 0; s[j] = '\0'; return TRUE; } /**************************************************************************/ int main(int argc, char *argv[]) { char *infilename,*outfilename; FILE *infile,*outfile; FILE *sortin,*sortout; int status,loops; char *dstr,*cdstr,*prevdstr,*prevcdstr; char sw,*fmt; boolean badargs,quiet,vswitch,dswitch,keep,format,uswitch; boolean iswitch,Iswitch,Kswitch,Tswitch; boolean sswitch,gswitch; nauty_counter numread,prevnumread,numwritten,classsize; int m,n,i,argnum,line; int outcode,codetype; int inv,mininvarlevel,maxinvarlevel,invararg; long minil,maxil; pid_t sortpid; graph *g; char *arg,*tempdir; #if MAXN graph h[MAXN*MAXM]; #else DYNALLSTAT(graph,h,h_sz); #endif HELP; nauty_check(WORDSIZE,1,1,NAUTYVERSIONID); infilename = outfilename = NULL; dswitch = format = quiet = vswitch = keep = uswitch = FALSE; sswitch = gswitch = Tswitch = FALSE; iswitch = Iswitch = Kswitch = FALSE; inv = 0; /* parse argument list */ argnum = 0; badargs = FALSE; for (i = 1; !badargs && i < argc; ++i) { arg = argv[i]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('q',quiet) else SWBOOLEAN('v',vswitch) else SWBOOLEAN('k',keep) else SWBOOLEAN('d',dswitch) else SWBOOLEAN('u',uswitch) else SWBOOLEAN('s',sswitch) else SWBOOLEAN('g',gswitch) else SWINT('i',iswitch,inv,"shortg -i") else SWINT('K',Kswitch,invararg,"shortg -K") else SWRANGE('I',":-",Iswitch,minil,maxil,"shortg -I") else if (sw == 'f') { format = TRUE; fmt = arg; break; } else if (sw == 'T') { Tswitch = TRUE; tempdir = arg; break; } else badargs = TRUE; } } else { ++argnum; if (argnum == 1) infilename = arg; else if (argnum == 2) outfilename = arg; else badargs = TRUE; } } if (strcmp(SORTPROG,"no_sort_found") == 0) gt_abort(">E shortg: no sort program known\n"); if (uswitch && outfilename != NULL) gt_abort(">E shortg: -u and outfile are incompatible\n"); if (sswitch && gswitch) gt_abort(">E shortg: -s and -g are incompatible\n"); if (Tswitch && *tempdir == '\0') gt_abort(">E shortg: -T needs a non-empty argument\n"); if (argnum == 1 && !uswitch) outfilename = infilename; if (iswitch && (inv > 15)) gt_abort(">E shortg: -i value must be 0..15\n"); if (iswitch && inv == 0) iswitch = FALSE; if (iswitch) { if (Iswitch) { mininvarlevel = minil; maxinvarlevel = maxil; } else mininvarlevel = maxinvarlevel = 1; if (!Kswitch) invararg = 3; } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if (!quiet) { fprintf(stderr,">A shortg"); if (uswitch || keep || vswitch || format || Tswitch || sswitch || gswitch || iswitch) fprintf(stderr," -"); if (sswitch) fprintf(stderr,"s"); if (gswitch) fprintf(stderr,"g"); if (keep) fprintf(stderr,"k"); if (vswitch) fprintf(stderr,"v"); if (dswitch) fprintf(stderr,"d"); if (uswitch) fprintf(stderr,"u"); if (iswitch) fprintf(stderr,"i=%s[%d:%d,%d]",invarproc[inv].name, mininvarlevel,maxinvarlevel,invararg); if (format) fprintf(stderr,"f%s",fmt); if (format && Tswitch) fprintf(stderr," -"); if (Tswitch) fprintf(stderr,"T%s",tempdir); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename); fprintf(stderr,"\n"); } /* open input file */ if (infilename && infilename[0] == '-') infilename = NULL; infile = opengraphfile(infilename,&codetype,FALSE,1); if (!infile) exit(1); if (!infilename) infilename = "stdin"; if (sswitch || !gswitch && (codetype&SPARSE6)) outcode = SPARSE6; else outcode = GRAPH6; #ifdef SIG_IGN signal(SIGPIPE,SIG_IGN); /* process pipe errors ourselves */ #endif /* begin sort in a subprocess */ sortpid = beginsort(&sortin,&sortout,(Tswitch?tempdir:NULL), dswitch||vswitch,keep); /* feed input graphs, possibly relabelled, to sort process */ numread = 0; while (TRUE) { if ((g = readg(infile,NULL,0,&m,&n)) == NULL) break; dstr = readg_line; ++numread; loops = loopcount(g,m,n); #if !MAXN DYNALLOC2(graph,h,h_sz,n,m,"shortg"); #endif fcanonise_inv(g,m,n,h,format?fmt:NULL, invarproc[inv].entrypoint,mininvarlevel,maxinvarlevel, invararg, loops>0); if (outcode == SPARSE6) cdstr = ntos6(h,m,n); else cdstr = ntog6(h,m,n); tosort(sortin,cdstr,keep ? dstr : NULL,vswitch ? numread : 0); FREES(g); } fclose(sortin); fclose(infile); /* open output file */ if (uswitch) outfilename = ""; else if (outfilename == NULL || outfilename[0] == '-' || is_pipe) { outfile = stdout; outfilename = "stdout"; } else { if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr, ">E shortg: can't open %s for writing\n",outfilename); gt_abort(NULL); } } if (!uswitch && (codetype&HAS_HEADER)) if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER); if (!quiet) #if LONG_LONG_COUNTERS fprintf(stderr, ">Z %6llu graphs read from %s\n",numread,infilename); #else fprintf(stderr, ">Z %6lu graphs read from %s\n",numread,infilename); #endif /* collect output from sort process and write to output file */ prevcdstr = prevdstr = NULL; numwritten = 0; if (dswitch) { classsize = 0; while (fromsort(sortout,&cdstr,&dstr,&numread)) { if (classsize == 0 || strcmp(cdstr,prevcdstr) != 0) classsize = 1; else { ++classsize; if (classsize == 2) { ++numwritten; if (!uswitch) { writeline(outfile,keep ? prevdstr : prevcdstr); writeline(outfile,"\n"); } if (keep) { ++numwritten; if (!uswitch) { writeline(outfile,keep ? dstr : cdstr); writeline(outfile,"\n"); } } if (vswitch) { fprintf(stderr,"\n"); #if LONG_LONG_COUNTERS fprintf(stderr,"%3llu : %3llu %3llu", numwritten,prevnumread,numread); #else fprintf(stderr,"%3lu : %3lu %3lu", numwritten,prevnumread,numread); #endif line = 1; } } else { if (keep) { ++numwritten; if (!uswitch) { writeline(outfile,keep ? dstr : cdstr); writeline(outfile,"\n"); } } if (vswitch) { if (line == 15) { line = 0; fprintf(stderr,"\n "); } #if LONG_LONG_COUNTERS fprintf(stderr," %3llu",numread); #else fprintf(stderr," %3lu",numread); #endif ++line; } } } if (prevcdstr) FREES(prevcdstr); prevcdstr = stringcopy(cdstr); if (prevdstr) FREES(prevdstr); if (keep) prevdstr = stringcopy(dstr); prevnumread = numread; } if (vswitch) fprintf(stderr,"\n\n"); } else if (vswitch) { while (fromsort(sortout,&cdstr,&dstr,&numread)) { if (numwritten == 0 || strcmp(cdstr,prevcdstr) != 0) { ++numwritten; if (!uswitch) { writeline(outfile,keep ? dstr : cdstr); writeline(outfile,"\n"); } fprintf(stderr,"\n"); #if LONG_LONG_COUNTERS fprintf(stderr,"%3llu : %3llu",numwritten,numread); #else fprintf(stderr,"%3lu : %3lu",numwritten,numread); #endif line = 1; } else { if (line == 15) { line = 0; fprintf(stderr,"\n "); } #if LONG_LONG_COUNTERS fprintf(stderr," %3llu",numread); #else fprintf(stderr," %3lu",numread); #endif ++line; } if (prevcdstr) FREES(prevcdstr); prevcdstr = stringcopy(cdstr); } fprintf(stderr,"\n\n"); } else { while (fromsort(sortout,&cdstr,&dstr,&numread)) { ++numwritten; if (!uswitch) { writeline(outfile,keep ? dstr : cdstr); writeline(outfile,"\n"); } } } fclose(sortout); if (!uswitch) fclose(outfile); if (!quiet) { #if LONG_LONG_COUNTERS if (uswitch) fprintf(stderr,">Z %6llu graphs produced\n",numwritten); else fprintf(stderr, ">Z %6llu graphs written to %s\n",numwritten,outfilename); #else if (uswitch) fprintf(stderr,">Z %6lu graphs produced\n",numwritten); else fprintf(stderr, ">Z %6lu graphs written to %s\n",numwritten,outfilename); #endif } /* check that the subprocess exitted properly */ while (wait(&status) != sortpid) {} #if (defined(WIFSIGNALED) || defined(WTERMSIG)) && defined(WEXITSTATUS) #ifdef WIFSIGNALED if (WIFSIGNALED(status) && WTERMSIG(status) != 0) #else if (WTERMSIG(status) != 0) #endif { fprintf(stderr,">E shortg: sort process killed (signal %d)\n", WTERMSIG(status)); gt_abort(NULL); } else if (WEXITSTATUS(status) != 0) { fprintf(stderr, ">E shortg: sort process exited abnormally (code %d)\n", WEXITSTATUS(status)); gt_abort(NULL); } #endif exit(0); } nauty24r2/testW.dre0000600000604200001440000000217611274163463013117 0ustar bdmusers! tests from 17 to 32 vertices n=16 $=0 g 0 : 5 10 14; 1 : 3 5 8; 2 : 7 12 15; 3 : 1 11 13; 4 : 6 11 12; 5 : 0 1 10; 6 : 4 9 10; 7 : 2 8 15; 8 : 1 7 14; 9 : 6 12 15; 10 : 0 5 6; 11 : 3 4 13; 12 : 2 4 9; 13 : 3 11 14; 14 : 0 8 13; 15 : 2 7 9; $$ -cx a=6ca17f8 o=69f5b55 jcx a=3b3deed b=409c76b o=fba1919 _ jcx a=3aba43e b=430b1df o=d2788e5 n=15 $=0 g 0 : 3 7 8 12 13 14; 1 : 3 7 8 12 13 14; 2 : 3 6 9 10 12 14; 3 : 0 1 2 4 9 11; 4 : 3 6 7 8 11 14; 5 : 6 7 10 12 13 14; 6 : 2 4 5 9 11 12; 7 : 0 1 4 5 11 13; 8 : 0 1 4 9 12 13; 9 : 2 3 6 8 10 11; 10 : 2 5 9 11 13 14; 11 : 3 4 6 7 9 10; 12 : 0 1 2 5 6 8; 13 : 0 1 5 7 8 10; 14 : 0 1 2 4 5 10; $$ % -cx a=ab420ca o=475cf98 jcx a=1732f18 b=66e763d o=c8d50ad _ jcx a=dbf8606 b=891a41c o=cabae0d n=13 s2 % -cx a=7d62358 o=2f9 jcx a=dbfddfc b=c34c8bd o=e03723 _ jcx a=219d1cf b=f4192a7 o=ca7b824 n=20 s2 -cx a=1 o=beab8e3 jcx a=1 b=d254bd4 o=beab8e3 _ jcx a=1 b=e1c6053 o=beab8e3 n=31 s3 -cx a=1 o=2a37d0d jcx a=1 b=ec02599 o=2a37d0d _ jcx a=1 b=f2e47bd o=2a37d0d n=32 s7 -cx a=1 o=8df43b2 jcx a=1 b=b4df49f o=8df43b2 _ jcx a=1 b=ca04f3c o=8df43b2 q nauty24r2/testB.dre0000600000604200001440000000043011274163463013061 0ustar bdmusers"WARNING: This test will need about 512MB free memory to complete in a reasonable time. To turn it off, change the definition of BIGTEST to 0 near the start of makefile.\n" n=40000 s9 cx a=1 b=df16e41 o=88b646b n=25000 s10 % c f=[0 25001] x a=e9178ea b=4a21f8c o=274dc8c q nauty24r2/makefile0000600000604200001440000000134111427224764013010 0ustar bdmusers# initial stub makefile for nauty # Use configure to create the real makefile SHELL = /bin/sh all : nauty gtools ; nauty : dreadnaut dreadnautB ; gtools : copyg listg labelg dretog amtog geng complg shortg showg NRswitchg \ addedgeg deledgeg countg pickg genrang newedgeg catg genbg directg ; dreadnaut : message ; dreadnautB : message ; copyg : message ; listg : message ; labelg : message ; dretog : message ; amtog : message ; geng : message ; complg : message ; shortg : message ; showg : message ; NRswitchg : message ; addedgeg : message ; deledgeg : message ; countg : message ; pickg : message ; genrang : message ; newedgeg : message ; catg : message ; genbg : message ; directg : message ; message : cat config.txt nauty24r2/gread.me0000600000604200001440000001237411274163463012723 0ustar bdmusersThis is gtools version 1.0 (beta release). ----------------------------------------- Brendan McKay Computer Science Dept Australian National University Canberra, ACT 0200 Australia bdm@cs.anu.edu.au gtools is a growing suite of programs for handling graphs in bulk. The formats supported are graph6 and sparse6; see below for the definitions. gtools is not supported on all the platforms which can compile nauty. Generally we have assumed 'int' has at least 32 bits, and system calls are UNIX or ANSI oriented. The shortg program needs a UNIX-like 'sort' program. Each program has an option -help (also known as --help) which describes what the program does and what the options are. Brief list: geng - generate graphs IMPORTANT NOTE: Contrary to earlier versions, the option for bounding the maximum degree is now -D and not -d. The new version uses -d to bound the minimum degree. labelg - canonically label graphs shortg - reduce graphs by isomorphism type complg - take the complements of graphs NRswitchg - perform various switching operations on graphs dretog - convert dreadnaut input to graph6 or sparse6 amtog - convert adjacency matrix input to graph6 or sparse6 listg - display/convert graphs to various formats readg - a stand-alone version of listg deledgeg - delete each edge from a graph copyg - convert between graph formats pickg - select graphs according to their properties countg - count graphs according to their properties Many more programs will be added over time. To compile gtools, you first need to compile nauty. This version of gtools requires nauty 2.0 beta 7 or later. Make links from the gtools directory to the files nauty.h, naututil.h, nauty.o, nautil.o, nauty1.o, naututil.o, rng.h and rng.o which are in the nauty directory. Then do "make" and it will be done. Alternatively, you can make nauty and gtools in the same directory., ------------------------------------------------------------------------- Definition of graph6 and sparse6 graph formats. All numbers in this description are in decimal unless obviously in binary. graph6 and sparse6 are text formats, and a file containing them is a text file. Apart from the header, there is one object per line. Apart from the header and the end-of-line characters, all bytes have a value in the range 63-126 (which are all printable ASCII characters). BIT VECTORS: A bit vector x of length k can be represented as follows. Example: 1000101100011100 (1) Pad on the right with 0 to make the length a multiple of 6. Example: 100010110001110000 (2) Split into groups of 6 bits each. Example: 100010 110001 110000 (3) Add 63 to each group, considering them as bigendian binary numbers. Example: 97 112 111 These values are then stored one per byte. So, the number of bytes required is ceiling(k/6). Let R(x) denote this representation of x as a string of bytes. SMALL NONNEGATIVE INTEGERS: Let n be an integer in the range 0-262143 (262143 = 2^18-1). If 0 <= n <= 62, define N(n) to be the single byte n+63. If n >= 63, define N(n) to be the four bytes 126 R(x), where x is the bigendian 18-bit binary form of n. Examples: N(30) = 93 N(12345) = N(000011 000000 111001) = 126 69 63 120 ========= graph6 format: Suppose G has n vertices. Write the upper triangle of the adjacency matrix of G as a bit vector x of length n(n-1)/2, using the ordering (0,1),(0,2),(1,2),(0,3),(1,3),(2,3),...,(n-1,n). Then the graph is represented as N(n) R(x). Example: Suppose n=5 and G has edges 0-2, 0-4, 1-3 and 3-4. x = 0 10 010 1001 Then N(n) = 68 and R(x) = R(010010 100100) = 81 99. So, the graph is 68 81 99. Note that graph6 format cannot represent loops or parallel edges. ========= sparse6 format: The encoded graph consists of: (1) The character ':'. (This is present to distinguish the code from graph6 format.) (2) The number of vertices. (3) A list of edges. (4) end-of-line Loops and multiple edges are supported, but not directed edges. Number of vertices n: Represented as N(n) like in graph6 format. List of edges: Let k be the number of bits needed to represent n-1 in binary. The remaining bytes encode a sequence R(z) where z = b[0] x[0] b[1] x[1] b[2] x[2] ... b[m] x[m] 111... Each b[i] occupies 1 bit, and each x[i] occupies k bits, and the number of 1's at the end is the least needed to make the total length a multiple of 6. The vertices of the graph are 0..n-1. The edges encoded by this sequence are determined thus: v = 0 for i from 0 to m do if b[i] = 1 then v = v+1 endif; if x[i] > v then v = x[i] else output {x[i],v} endif endfor Example: :Fa@x^ ':' indicates sparse6 format. Subtract 63 from the other bytes and write them in binary, six bits each. 000111 100010 000001 111001 011111 The first byte is not 63, so it is n. n=7 n-1 needs 3 bits (k=3). Write the other bits in groups of 1 and k: 1 000 1 000 0 001 1 110 0 101 1 111 This is the b/x sequence 1,0 1,0 0,1 1,6 0,5 1,7. The 1,7 at the end is just padding. The remaining pairs give the edges 0-1 1-2 5-6. nauty24r2/gentourng.c0000600000604200001440000012373511274163463013476 0ustar bdmusers/* gentourng.c version 1.0; B D McKay, Nov 29, 2008. */ #define USAGE \ "gentourng [-cd#D#] [-ugs] [-lq] n [res/mod] [file]" #define HELPTEXT \ " Generate all tournaments of a specified class.\n\ \n\ n : the number of vertices\n\ res/mod : only generate subset res out of subsets 0..mod-1\n\ \n\ -c : only write strongly-connected tournaments\n\ -d# : a lower bound for the minimum out-degree\n\ -D# : a upper bound for the maximum out-degree\n\ -l : canonically label output graphs\n\ \n\ -u : do not output any graphs, just generate and count them\n\ -g : use graph6 output (lower triangle)\n\ -s : use sparse6 output (lower triangle)\n\ -h : write a header (only with -g or -s)\n\ Default output is upper triangle row-by-row in ascii\n\ \n\ -q : suppress auxiliary output\n\ \n\ See program text for much more information.\n" /* Parameters: n = the number of vertices (1..min(32,WORDSIZE)) mod, res = a way to restrict the output to a subset. All the graphs in G(n,mine..maxe) are divided into disjoint classes C(0,mod),C(1,mod),...,C(mod-1,mod), of very approximately equal size. Only the class C(res,mod) is written. file = a name for the output file (stdout if missing or "-") All switches can be concatenated or separate. However, the value of -d must be attached to the "d", and similarly for "x". -c : only write connected graphs -d : specify an upper bound for the maximum out-degree. The value of the upper bound must be adjacent to the "d". Example: -d6 -l : canonically label output graphs -u : do not output any graphs, just generate and count them -g : use graph6 output -s : use sparse6 output For -g and -s, the lower triangle of the adjacency matrix is written as if it is an undirected graph. Nauty tools like labelg do not know this format. To read it you can read it as an undirected graph then complement the upper triangle. -h : for graph6 or sparse6 format, write a header too -q : suppress auxiliary output (except from -v) Output formats. The output format is determined by the mutually exclusive switches -u, -g and -s. The default is ascii format. -u suppresses output of graphs completely. -s and -g specify sparse6 and graph6 format, defined elsewhere. In this case a header is also written if -h is present. OUTPROC feature. By defining the C preprocessor variable OUTPROC at compile time (for Unix the syntax is -DOUTPROC=procname on the cc command), gentourng can be made to call a procedure of your manufacture with each output graph instead of writing anything. Your procedure needs to have type void and the argument list (FILE *f, graph *g, int n). f is a stream open for writing, g is the graph in nauty format, and n is the number of vertices. Your procedure can be in a separate file so long as it is linked with gentourng. The global variables nooutput, and canonise (all type boolean) can be used to test for the presence of the flags -u, -n, -y and -l, respectively. If -l is present, the group size and similar details can be found in the global variable nauty_stats. PRUNE feature. By defining the C preprocessor variable PRUNE at compile time, gentourng can be made to call int PRUNE(graph *g,int n,int maxn) for each intermediate (and final) graph, and reject it if the value returned is nonzero. The arguments are: g = the graph in nauty format (m=1) n = the number of vertices in g maxn = the number of vertices for output (the value you gave on the command line to gentourng) gentourng constructs the graph starting with vertex 0, then adding vertices 1,2,3,... in that order. Each graph in the sequence is an induced subgraph of all later graphs in the sequence. A call is made for all orders from 1 to maxn. In testing for a uniform property (such as a forbidden subgraph or forbidden induced subgraph) it might save time to notice that a call to PRUNE for n implies that the call for n-1 already passed. For very fast tests, it might be worthwhile using PREPRUNE as well or instead. It has the same meaning but is applied earlier and more often. SUMMARY If the C preprocessor variable SUMMARY is defined at compile time, the procedure SUMMARY(bigint nout, double cpu) is called just before the program exits. The purpose is to allow reporting of statistics collected by PRUNE or OUTPROC. The values nout and cpu are the output count and cpu time reported on the >Z line. Output should be written to stderr. INSTRUMENT feature. If the C preprocessor variable INSTRUMENT is defined at compile time, extra code is inserted to collect statistics during execution, and more information is written to stderr at termination. CALLING FROM A PROGRAM It is possible to call gentourng from another program instead of using it as a stand-alone program. The main requirement is to change the name of the main program to be other than "main". This is done by defining the preprocessor variable GENG_MAIN. You might also like to define OUTPROC to be the name of a procedure to receive the graphs. To call the program you need to define an argument list argv[] consistent with the usual one; don't forget that argv[0] is the command name and not the first argument. The value of argc is the number of strings in argv[]; that is, one more than the number of arguments. See the sample program callgeng.c. Counts: all strong regular n tournaments tournaments tournaments 1 1 1 1 2 1 0 1 3 2 1 1 4 4 1 1 5 12 6 1 6 56 35 5 7 456 353 3 8 6880 6008 85 9 191536 178133 15 10 9733056 9355949 13333 11 903753248 884464590 1223 12 154108311168 152310149735 19434757 13 48542114686912 48234782263293 1495297 14 28401423719122304 28304491788158056 15 31021002160355166848 30964247546702883729 18400989629 ************************************************************************** Author: B. D. McKay, Nov 2008. Copyright B. McKay (2008). All rights reserved. This software is subject to the conditions and waivers detailed in the file nauty.h. **************************************************************************/ #define NAUTY_PGM 3 /* 1 = geng, 2 = genbg, 3 = gentourng */ #ifndef MAXN #define MAXN 32 /* not more than max(32,WORDSIZE) */ #endif #if MAXN > 32 #error "Can't have MAXN greater than 32" #endif #define ONE_WORD_SETS #include "gtools.h" /* which includes nauty.h and stdio.h */ typedef unsigned int xword; static void (*outproc)(FILE*,graph*,int); static FILE *outfile; /* file for output graphs */ static int connec; /* 1 for -c, 0 for not */ boolean graph6; /* presence of -g */ boolean sparse6; /* presence of -s */ boolean nooutput; /* presence of -u */ boolean canonise; /* presence of -l */ boolean quiet; /* presence of -q */ boolean header; /* presence of -h */ statsblk nauty_stats; static int mindeg,maxdeg,maxn,mod,res; static boolean regular; #define PRUNEMULT 20 /* bigger -> more even split at greater cost */ static int min_splitlevel,odometer,splitlevel,multiplicity; static graph gcan[MAXN]; #if MAXN <= 16 static xword xbit[] = {0x0001,0x0002,0x0004,0x0008, 0x0010,0x0020,0x0040,0x0080, 0x0100,0x0200,0x0400,0x0800, 0x1000,0x2000,0x4000,0x8000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : 15-leftbit[((x)>>8)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] + bytecount[(x)&0xFF]) #elif MAXN <= 24 static xword xbit[] = {0x000001,0x000002,0x000004,0x000008, 0x000010,0x000020,0x000040,0x000080, 0x000100,0x000200,0x000400,0x000800, 0x001000,0x002000,0x004000,0x008000, 0x010000,0x020000,0x040000,0x080000, 0x100000,0x200000,0x400000,0x800000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : \ (x)&0xFF00 ? 15-leftbit[((x)>>8)&0xFF] : 23-leftbit[((x)>>16)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] \ + bytecount[((x)>>16)&0xFF] + bytecount[(x)&0xFF]) #else static xword xbit[] = {0x00000001,0x00000002,0x00000004,0x00000008, 0x00000010,0x00000020,0x00000040,0x00000080, 0x00000100,0x00000200,0x00000400,0x00000800, 0x00001000,0x00002000,0x00004000,0x00008000, 0x00010000,0x00020000,0x00040000,0x00080000, 0x00100000,0x00200000,0x00400000,0x00800000, 0x01000000,0x02000000,0x04000000,0x08000000, 0x10000000,0x20000000,0x40000000,0x80000000}; #define XNEXTBIT(x) \ ((x)&0xFF ? 7-leftbit[(x)&0xFF] : \ (x)&0xFF00 ? 15-leftbit[((x)>>8)&0xFF] : \ (x)&0xFF0000 ? 23-leftbit[((x)>>16)&0xFF] : \ 31-leftbit[((x)>>24)&0xFF]) #define XPOPCOUNT(x) (bytecount[((x)>>8)&0xFF] \ + bytecount[((x)>>16)&0xFF] + \ + bytecount[((x)>>24)&0xFF] + bytecount[(x)&0xFF]) #endif typedef struct { xword lo,hi; /* work purposes for orbit calculation */ xword xstart[MAXN+1]; /* index into xset[] for each cardinality */ xword *xset; /* array of all x-sets in card order */ xword *xcard; /* cardinalities of all x-sets */ xword *xinv; /* map from x-set to index in xset */ xword *xorb; /* min orbit representative */ } leveldata; /* The program is so fast that the count of output graphs can quickly overflow a 32-bit integer. Therefore, we use two long values for each count, with a ratio of 10^9 between them. The macro ADDBIG adds a small number to one of these big numbers. BIGTODOUBLE converts a big number to a double (approximately). SUMBIGS adds a second big number into a first big number. SUBBIGS subtracts one big number from a second. PRINTBIG prints a big number in decimal. ZEROBIG sets the value of a big number to 0. ISZEROBIG tests if the value is 0. SETBIG sets a big number to a value at most 10^9-1. ISEQBIG tests if two big numbers are equal. ISASBIG tests if a big number is at least as a value at most 10^9-1. */ typedef struct { long hi,lo; } bigint; #define ZEROBIG(big) big.hi = big.lo = 0L #define ISZEROBIG(big) (big.lo == 0 && big.hi == 0) #define SETBIG(big,value) {big.hi = 0L; big.lo = (value);} #define ADDBIG(big,extra) if ((big.lo += (extra)) >= 1000000000L) \ { ++big.hi; big.lo -= 1000000000L;} #define PRINTBIG(file,big) if (big.hi == 0) \ fprintf(file,"%ld",big.lo); else fprintf(file,"%ld%09ld",big.hi,big.lo) #define BIGTODOUBLE(big) (big.hi * 1000000000.0 + big.lo) #define SUMBIGS(big1,big2) {if ((big1.lo += big2.lo) >= 1000000000L) \ {big1.lo -= 1000000000L; big1.hi += big2.hi + 1L;} \ else big1.hi += big2.hi;} #define SUBBIGS(big1,big2) {if ((big1.lo -= big2.lo) < 0L) \ {big1.lo += 1000000000L; big1.hi -= big2.hi + 1L;} \ else big1.hi -= big2.hi;} /* Note: SUBBIGS must not allow the value to go negative. SUMBIGS and SUBBIGS both permit big1 and big2 to be the same bigint. */ #define ISEQBIG(big1,big2) (big1.lo == big2.lo && big1.hi == big2.hi) #define ISASBIG(big,value) (big.hi > 0 || big.lo >= (value)) static leveldata data[MAXN]; /* data[n] is data for n -> n+1 */ static bigint nodes[MAXN]; /* nodes at each level */ static bigint nout; #ifdef INSTRUMENT static unsigned long rigidnodes[MAXN],fertilenodes[MAXN]; static unsigned long a1calls,a1nauty,a1succs; static unsigned long a2calls,a2nauty,a2uniq,a2succs; #endif #ifdef PLUGIN #include PLUGIN #endif #ifdef OUTPROC extern void OUTPROC(FILE*,graph*,int); #endif #ifdef PRUNE extern int PRUNE(graph*,int,int); #endif #ifdef PREPRUNE extern int PREPRUNE(graph*,int,int); #endif #ifdef SUMMARY extern void SUMMARY(bigint,double); #endif /************************************************************************/ void write_ascii(FILE *f, graph *g, int n) /* write tournament g (n vertices) to file f in ascii format */ { char s[MAXN*(MAXN-1)/2+2]; int i,j; size_t k; k = 0; for (i = 0; i < n-1; ++i) for (j = i+1; j < n; ++j) if ((g[i] & bit[j])) s[k++] = '1'; else s[k++] = '0'; s[k++] = '\n'; s[k] = '\0'; if (fwrite(s,1,k,f) != k || ferror(f)) gt_abort(">E write_ascii : error on writing\n"); } /************************************************************************/ void writeg6x(FILE *f, graph *g, int n) /* write graph g (n vertices) to file f in graph6 format */ { writeg6(f,g,1,n); } /************************************************************************/ void writes6x(FILE *f, graph *g, int n) /* write graph g (n vertices) to file f in sparse6 format */ { writes6(f,g,1,n); } /***********************************************************************/ static void nullwrite(FILE *f, graph *g, int n) /* don't write graph g (n vertices) to file f */ { } /***********************************************************************/ static boolean isstrong(graph *g, int n) /* test if tournament g is strongly-connected * This code is strictly for tournaments only. */ { setword seen,expanded,toexpand,allbits; int i; allbits = ALLMASK(n); seen = bit[0] | g[0]; expanded = bit[0]; while (seen != allbits && (toexpand = (seen & ~expanded))) /* not == */ { i = FIRSTBIT(toexpand); expanded |= bit[i]; seen |= g[i]; } if (seen != allbits) return FALSE; seen = (allbits ^ g[0]); expanded = bit[0]; while (seen != allbits && (toexpand = (seen & ~expanded))) /* not == */ { i = FIRSTBIT(toexpand); expanded |= bit[i]; seen |= (g[i] ^ allbits); } return seen == allbits; } /**********************************************************************/ static void gcomplement(graph *g, graph *gc, int n) /* Take the complement of g and put it in gc */ { int i; setword all; all = ~(setword)BITMASK(n-1); for (i = 0; i < n; ++i) gc[i] = g[i] ^ all ^ bit[i]; } /**************************************************************************/ static void makeleveldata(void) /* make the level data for each level */ { long h; int n,dmax,dmin; long ncj; leveldata *d; xword *xcard,*xinv; xword *xset,xw,tttn,nxsets; xword cw; xword i,j; for (n = 1; n < maxn; ++n) { dmax = n/2; if (maxdeg < dmax) dmax = maxdeg; dmin = mindeg - maxn + n + 1; if (dmin < 0) dmin = 0; ncj = 1; nxsets = (dmin == 0 ? 1 : 0); for (j = 1; j <= dmax; ++j) { ncj = (ncj * (n-j+1)) / j; if (j >= dmin) nxsets += ncj; } tttn = 1L << n; d = &data[n]; d->xset = xset = (xword*) calloc(nxsets,sizeof(xword)); d->xcard = xcard = (xword*) calloc(nxsets,sizeof(xword)); d->xinv = xinv = (xword*) calloc(tttn,sizeof(xword)); d->xorb = (xword*) calloc(nxsets,sizeof(xword)); if (xset==NULL || xcard==NULL || xinv==NULL || d->xorb==NULL) { fprintf(stderr, ">E gentourng: calloc failed in makeleveldata()\n"); exit(2); } j = 0; for (i = 0;; ++i) { if ((h = XPOPCOUNT(i)) <= dmax && h >= dmin) { xset[j] = i; xcard[j] = h; ++j; } if (i == (xword)((1L<E gentourng: j=%d mxsets=%u\n", j,(unsigned)nxsets); exit(2); } h = 1; do h = 3 * h + 1; while (h < nxsets); do { for (i = h; i < nxsets; ++i) { xw = xset[i]; cw = xcard[i]; for (j = i; xcard[j-h] > cw || xcard[j-h] == cw && xset[j-h] > xw; ) { xset[j] = xset[j-h]; xcard[j] = xcard[j-h]; if ((j -= h) < h) break; } xset[j] = xw; xcard[j] = cw; } h /= 3; } while (h > 0); for (i = 0; i < nxsets; ++i) xinv[xset[i]] = i; d->xstart[0] = 0; for (i = 1; i < nxsets; ++i) if (xcard[i] > xcard[i-1]) d->xstart[xcard[i]] = i; d->xstart[xcard[nxsets-1]+1] = nxsets; } } /**************************************************************************/ static void userautomproc(int count, permutation *p, int *orbits, int numorbits, int stabvertex, int n) /* form orbits on powerset of VG called by nauty; operates on data[n] */ { xword i,j1,j2,moved,pi,pxi; xword lo,hi; xword *xorb,*xinv,*xset,w; xorb = data[n].xorb; xset = data[n].xset; xinv = data[n].xinv; lo = data[n].lo; hi = data[n].hi; if (count == 1) /* first automorphism */ for (i = lo; i < hi; ++i) xorb[i] = i; moved = 0; for (i = 0; i < n; ++i) if (p[i] != i) moved |= xbit[i]; for (i = lo; i < hi; ++i) { if ((w = xset[i] & moved) == 0) continue; pxi = xset[i] & ~moved; while (w) { j1 = XNEXTBIT(w); w ^= xbit[j1]; pxi |= xbit[p[j1]]; } pi = xinv[pxi]; j1 = xorb[i]; while (xorb[j1] != j1) j1 = xorb[j1]; j2 = xorb[pi]; while (xorb[j2] != j2) j2 = xorb[j2]; if (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1; else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2; } } /***************************************************************************** * * * refinex(g,lab,ptn,level,numcells,count,active,goodret,code,m,n) is a * * custom version of refine() which can exit quickly if required. * * * * Only use at level==0. * * goodret : whether to do an early return for code 1 * * 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, permutation *count, set *active, boolean goodret, int *code, int m, int n) { int i,c1,c2,labc1; setword x,lact; int split1,split2,cell1,cell2; int cnt,bmin,bmax; set *gptr; setword workset; int workperm[MAXN]; int bucket[MAXN+2]; if (n == 1) { *code = 1; return; } *code = 0; lact = *active; split1 = -1; while (*numcells < n && lact) { TAKEBIT(split1,lact); for (split2 = split1; ptn[split2] > 0; ++split2) {} if (split1 == split2) /* trivial splitting cell */ { gptr = GRAPHROW(g,lab[split1],1); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; c1 = cell1; c2 = cell2; while (c1 <= c2) { labc1 = lab[c1]; if (ISELEMENT1(gptr,labc1)) ++c1; else { lab[c1] = lab[c2]; lab[c2] = labc1; --c2; } } if (c2 >= cell1 && c1 <= cell2) { ptn[c2] = 0; ++*numcells; lact |= bit[c1]; } } } else /* nontrivial splitting cell */ { workset = 0; for (i = split1; i <= split2; ++i) workset |= bit[lab[i]]; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; i = cell1; if ((x = workset & g[lab[i]]) != 0) cnt = POPCOUNT(x); else cnt = 0; count[i] = bmin = bmax = cnt; bucket[cnt] = 1; while (++i <= cell2) { if ((x = workset & g[lab[i]]) != 0) cnt = POPCOUNT(x); else cnt = 0; while (bmin > cnt) bucket[--bmin] = 0; while (bmax < cnt) bucket[++bmax] = 0; ++bucket[cnt]; count[i] = cnt; } if (bmin == bmax) continue; c1 = cell1; for (i = bmin; i <= bmax; ++i) if (bucket[i]) { c2 = c1 + bucket[i]; bucket[i] = c1; if (c1 != cell1) { lact |= bit[c1]; ++*numcells; } if (c2 <= cell2) ptn[c2-1] = 0; c1 = c2; } for (i = cell1; i <= cell2; ++i) workperm[bucket[count[i]]++] = lab[i]; for (i = cell1; i <= cell2; ++i) lab[i] = workperm[i]; } } if (ptn[n-2] == 0) { if (lab[n-1] == n-1) { *code = 1; if (goodret) return; } else { *code = -1; return; } } else { i = n - 1; while (TRUE) { if (lab[i] == n-1) break; --i; if (ptn[i] == 0) { *code = -1; return; } } } } } /**************************************************************************/ static void makecanon(graph *g, graph *gcan, int n) /* gcan := canonise(g) */ { int lab[MAXN],ptn[MAXN],orbits[MAXN]; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; options.getcanon = TRUE; options.digraph = TRUE; nauty(g,lab,ptn,NULL,orbits,&options,&nauty_stats, workspace,50,1,n,gcan); } /**************************************************************************/ static 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; int lab[MAXN],ptn[MAXN],orbits[MAXN]; permutation count[MAXN]; graph h[MAXN]; int nx,numcells,code; int i0,i1,degn; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a1calls; #endif nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; gx[n] = 0; deg[n] = degn = XPOPCOUNT(x); for (i = 0; i < n; ++i) { if ((xbit[i] & x)) gx[n] |= bit[i]; else { gx[i] |= bit[n]; ++deg[i]; } } #ifdef PREPRUNE if (PREPRUNE(gx,n+1,maxn)) return FALSE; #endif i0 = 0; i1 = n; for (i = 0; i < nx; ++i) { if (deg[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == 0) { numcells = 1; active[0] = bit[0]; } else { numcells = 2; active[0] = bit[0] | bit[i1+1]; ptn[i1] = 0; } refinex(gx,lab,ptn,0,&numcells,count,active,FALSE,&code,1,nx); if (code < 0) return FALSE; if (numcells == nx) { *rigid = TRUE; #ifdef INSTRUMENT ++a1succs; #endif return TRUE; } options.getcanon = TRUE; options.digraph = TRUE; options.defaultptn = FALSE; options.userautomproc = userautomproc; /* if (!regular || nx != maxn-1) options.userautomproc = userautomproc; else options.userautomproc = NULL; */ active[0] = 0; #ifdef INSTRUMENT ++a1nauty; #endif 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 return TRUE; } else return FALSE; } /**************************************************************************/ static boolean hitinvar(graph *g, int *invar, int n) /* make hitting invariant * return FALSE if n-1 not maximal else return TRUE */ { setword x,y,z; int inv,i,v,d; for (v = n-1; v >= 0; --v) { inv = 0; x = y = g[v]; while (y) { TAKEBIT(i,y); z = x & g[i]; d = POPCOUNT(z); if (d > inv) inv = d; } invar[v] = inv; 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) /* decide if n in theta(g+x) -- version for n+1 == maxn */ { int i; int lab[MAXN],ptn[MAXN],orbits[MAXN]; int degx[MAXN],invar[MAXN]; setword vmax,gv,gxn; int qn,qv; permutation count[MAXN]; int nx,numcells,code; int degn,i0,i1,j,j0,j1; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; boolean cheapacc; #ifdef INSTRUMENT ++a2calls; if (nuniq) ++a2uniq; #endif nx = n + 1; gxn = 0; for (i = 0; i < n; ++i) { if ((xbit[i] & x)) { gxn |= bit[i]; gx[i] = g[i]; degx[i] = deg[i]; } else { gx[i] = g[i] | bit[n]; degx[i] = deg[i] + 1; } } gx[n] = gxn; degx[n] = degn = XPOPCOUNT(x); #ifdef PREPRUNE if (PREPRUNE(gx,n+1,maxn)) return FALSE; #endif if (nuniq) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } i0 = 0; i1 = n; for (i = 0; i < nx; ++i) { if (degx[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == 0) { numcells = 1; active[0] = bit[0]; if (!hitinvar(gx,invar,nx)) return FALSE; qn = invar[n]; j0 = 0; j1 = n; while (j0 <= j1) { j = lab[j0]; qv = invar[j]; if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > 0) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } else { numcells = 2; ptn[i1] = 0; active[0] = bit[0] | bit[i1+1]; vmax = 0; for (i = i1+1; i < nx; ++i) vmax |= bit[lab[i]]; gv = gx[n] & vmax; qn = POPCOUNT(gv); j0 = i1+1; j1 = n; while (j0 <= j1) { j = lab[j0]; gv = gx[j] & vmax; qv = POPCOUNT(gv); if (qv > qn) return FALSE; else if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > i1+1) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } refinex(gx,lab,ptn,0,&numcells,count,active,TRUE,&code,1,nx); if (code < 0) return FALSE; cheapacc = FALSE; if (code > 0) cheapacc = TRUE; if (cheapacc) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } options.getcanon = TRUE; options.digraph = TRUE; options.defaultptn = FALSE; active[0] = 0; #ifdef INSTRUMENT ++a2nauty; #endif nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan); if (orbits[lab[n]] == orbits[n]) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } else return FALSE; } /**************************************************************************/ static void genextend(graph *g, int n, int *deg, boolean rigid) /* extend from n to n+1 -- version for general graphs */ { xword x,dlow,dhigh,dcrit; xword *xset,*xcard,*xorb; xword i,imin,imax; int nx,xc,j,dmax; int xlb,xub,xlbx,xubx; graph gx[MAXN]; int degx[MAXN]; boolean rigidx; boolean subconnec; #ifdef INSTRUMENT boolean haschild; haschild = FALSE; if (rigid) ++rigidnodes[n]; #endif nx = n + 1; ADDBIG(nodes[n],1); if (regular && nx == maxn) { x = 0; for (i = 0; i < n; ++i) if (deg[i] == maxdeg) x |= xbit[i]; if (accept2(g,n,x,gx,deg,FALSE)) { #ifdef PRUNE if (!PRUNE(gx,nx,maxn)) #endif { #ifdef INSTRUMENT haschild = TRUE; #endif ADDBIG(nout,1); (*outproc)(outfile,canonise ? gcan : gx,nx); } } #ifdef INSTRUMENT if (haschild) ++fertilenodes[n]; #endif return; } dmax = deg[n-1]; xlb = mindeg + n + 1 - maxn; if (0 > xlb) xlb = 0; xub = dmax+1; if (n/2 < xub) xub = n/2; if (maxdeg < xub) xub = maxdeg; if (xlb > xub) return; dlow = dcrit = dhigh = 0; for (i = 0; i < n; ++i) { if (deg[i] == dmax) dlow |= xbit[i]; if (deg[i] == maxdeg) dhigh |= xbit[i]; if (deg[i] == mindeg + n - maxn) dcrit |= xbit[i]; } if (XPOPCOUNT(dhigh) > xlb) xlb = XPOPCOUNT(dhigh); if (n-XPOPCOUNT(dcrit) < xub) xub = n - XPOPCOUNT(dcrit); if (xub == dmax+1 && XPOPCOUNT(dlow)+dmax >= n) --xub; if (xlb > xub) return; #ifdef PRUNE if (PRUNE(g,n,maxn)) return; #endif imin = data[n].xstart[xlb]; imax = data[n].xstart[xub+1]; xset = data[n].xset; xcard = data[n].xcard; xorb = data[n].xorb; if (nx == maxn) { subconnec = connec && isstrong(g,n); for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if (xc == dmax+1 && (x & dlow) != 0) continue; if ((dhigh & ~x) != 0) continue; if ((dcrit & x) != 0) continue; if (accept2(g,n,x,gx,deg, xc < dmax || xc == dmax && (x & dlow) == 0)) if (!connec || (subconnec && x != 0) || isstrong(gx,nx)) { #ifdef PRUNE if (!PRUNE(gx,nx,maxn)) #endif { #ifdef INSTRUMENT haschild = TRUE; #endif ADDBIG(nout,1); (*outproc)(outfile,canonise ? gcan : gx,nx); } } } } else { for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if (xc == dmax+1 && (x & dlow) != 0) continue; if ((dhigh & ~x) != 0) continue; if ((dcrit & x) != 0) continue; if (nx == splitlevel) { if (odometer-- != 0) continue; odometer = mod - 1; } for (j = 0; j < n; ++j) degx[j] = deg[j]; xlbx = mindeg+nx+1-maxn; if (xlbx < 0) xlbx = 0; xubx = xc + 1; if (maxdeg < xubx) xubx = maxdeg; if (nx/2 < xubx) xubx = nx/2; if (xlbx > xubx) continue; data[nx].lo = data[nx].xstart[xlbx]; data[nx].hi = data[nx].xstart[xubx+1]; if (accept1(g,n,x,gx,degx,&rigidx)) { #ifdef INSTRUMENT haschild = TRUE; #endif genextend(gx,nx,degx,rigidx); } } } if (n == splitlevel-1 && n >= min_splitlevel && ISASBIG(nodes[n],multiplicity)) --splitlevel; #ifdef INSTRUMENT if (haschild) ++fertilenodes[n]; #endif } /**************************************************************************/ /**************************************************************************/ int #ifdef GENG_MAIN GENG_MAIN(int argc, char *argv[]) #else main(int argc, char *argv[]) #endif { char *arg; boolean badargs,gotd,gotD,gotf,gotmr; boolean secret,connec1; char *outfilename,sw; int i,j,argnum; graph g[1]; int deg[1]; int splitlevinc; xword testxword; double t1,t2; char msg[201]; HELP; nauty_check(WORDSIZE,1,MAXN,NAUTYVERSIONID); testxword = (xword)(-1); if (MAXN > 32 || MAXN > WORDSIZE || MAXN > 8*sizeof(xword) || (MAXN == 8*sizeof(xword) && testxword < 0)) { fprintf(stderr,"gentourng: incompatible MAXN, WORDSIZE, or xword\n"); fprintf(stderr,"--See notes in program source\n"); exit(1); } badargs = FALSE; graph6 = FALSE; sparse6 = FALSE; nooutput = FALSE; canonise = FALSE; header = FALSE; outfilename = NULL; secret = FALSE; connec1 = FALSE; maxdeg = MAXN; mindeg = 0; splitlevinc = 0; gotd = gotD = gotf = gotmr = FALSE; argnum = 0; for (j = 1; !badargs && j < argc; ++j) { arg = argv[j]; if (arg[0] == '-' && arg[1] != '\0') { ++arg; while (*arg != '\0') { sw = *arg++; SWBOOLEAN('u',nooutput) else SWBOOLEAN('g',graph6) else SWBOOLEAN('s',sparse6) else SWBOOLEAN('l',canonise) else SWBOOLEAN('h',header) else SWBOOLEAN('q',quiet) else SWBOOLEAN('c',connec1) else SWBOOLEAN('$',secret) else SWINT('d',gotd,mindeg,"gentourng -d") else SWINT('D',gotD,maxdeg,"gentourng -D") #ifdef PLUGIN_SWITCHES PLUGIN_SWITCHES #endif else badargs = TRUE; } } else if (arg[0] == '-' && arg[1] == '\0') gotf = TRUE; else { if (argnum == 0) { if (sscanf(arg,"%d",&maxn) != 1) badargs = TRUE; ++argnum; } else if (gotf) badargs = TRUE; else { if (!gotmr) { if (sscanf(arg,"%d/%d",&res,&mod) == 2) { gotmr = TRUE; continue; } } if (!gotf) { outfilename = arg; gotf = TRUE; continue; } } } } if (argnum == 0) badargs = TRUE; else if (maxn < 1 || maxn > MAXN) { fprintf(stderr,">E gentourng: n must be in the range 1..%d\n",MAXN); badargs = TRUE; } if (!gotmr) { mod = 1; res = 0; } if (connec1) connec = 1; else connec = 0; if (maxdeg >= maxn) maxdeg = maxn - 1; if (mindeg < 0) mindeg = 0; if (!badargs && (maxdeg < mindeg || 2*maxdeg < maxn-1 || 2*mindeg > maxn-1)) { fprintf(stderr,">E gentourng: impossible degree bounds\n"); badargs = TRUE; } if (connec && mindeg < 1 && maxn > 1) mindeg = 1; if (connec && maxdeg == maxn-1 && maxn > 1) maxdeg = maxn - 2; if (!badargs && (res < 0 || res >= mod)) { fprintf(stderr,">E gentourng: must have 0 <= res < mod\n"); badargs = TRUE; } if (badargs) { fprintf(stderr,">E Usage: %s\n",USAGE); GETHELP; exit(1); } if ((graph6!=0) + (sparse6!=0) + (nooutput!=0) > 1) gt_abort(">E gentourng: -uyngs are incompatible\n"); #ifdef OUTPROC outproc = OUTPROC; #else if (nooutput) outproc = nullwrite; else if (sparse6) outproc = writes6x; else if (graph6) outproc = writeg6x; else outproc = write_ascii; #endif #ifdef PLUGIN_INIT PLUGIN_INIT #endif for (i = 0; i < maxn; ++i) ZEROBIG(nodes[i]); if (nooutput) outfile = stdout; else if (!gotf || outfilename == NULL) { outfilename = "stdout"; outfile = stdout; } else if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr, ">E gentourng: can't open %s for writing\n",outfilename); gt_abort(NULL); } multiplicity = PRUNEMULT * mod; if (!quiet) { msg[0] = '\0'; if (strlen(argv[0]) > 75) fprintf(stderr,">A %s",argv[0]); else CATMSG1(">A %s",argv[0]); CATMSG2(" -%s%s",connec1 ? "c" : "",canonise ? "l" : ""); /* if (mod > 1) CATMSG2("X%dx%d",splitlevinc,multiplicity); */ CATMSG3("d%dD%d n=%d",mindeg,maxdeg,maxn); if (mod > 1) CATMSG2(" class=%d/%d",res,mod); CATMSG0("\n"); fputs(msg,stderr); fflush(stderr); } g[0] = 0; deg[0] = 0; t1 = CPUTIME; if (header) { if (sparse6) { writeline(outfile,SPARSE6_HEADER); fflush(outfile); } else if (!nooutput) { writeline(outfile,GRAPH6_HEADER); fflush(outfile); } } ZEROBIG(nout); if (maxn == 1) { if (res == 0) { ADDBIG(nout,1); (*outproc)(outfile,g,1); } } else { makeleveldata(); if (maxn >= 14 && mod > 1) splitlevel = maxn - 4; else if (maxn >= 6 && mod > 1) splitlevel = maxn - 3; else splitlevel = -1; splitlevel += splitlevinc; if (splitlevel > maxn - 1) splitlevel = maxn - 1; if (splitlevel < 3) splitlevel = -1; min_splitlevel = 6; odometer = secret ? -1 : res; regular = mindeg == maxdeg; if (regular) connec = FALSE; /* All reg tourns are strong! */ genextend(g,1,deg,TRUE); } t2 = CPUTIME; #ifdef INSTRUMENT fprintf(stderr,"\n>N node counts\n"); for (i = 1; i < maxn; ++i) { fprintf(stderr," level %2d: \n",i); PRINTBIG(stderr,nodes[i]); fprintf(stderr," (%lu rigid, %lu fertile)\n", rigidnodes[i],fertilenodes[i]); } fprintf(stderr,">A1 %lu calls to accept1, %lu nauty, %lu succeeded\n", a1calls,a1nauty,a1succs); fprintf(stderr, ">A2 %lu calls to accept2, %lu nuniq, %lu nauty, %lu succeeded\n", a2calls,a2uniq,a2nauty,a2succs); fprintf(stderr,"\n"); #endif #ifdef SUMMARY SUMMARY(nout,t2-t1); #endif if (!quiet) { fprintf(stderr,">Z "); PRINTBIG(stderr,nout); fprintf(stderr," graphs generated in %3.2f sec\n",t2-t1); } #ifdef GENG_MAIN for (i = 1; i < maxn; ++i) { free(data[i].xorb); free(data[i].xset); free(data[i].xinv); free(data[i].xcard); } return 0; #else exit(0); #endif }