1 /*****************************************************************************
2 * *
3 * This is the main file for dreadnaut() version 2.2, which is a test-bed *
4 * for nauty() version 2.2. *
5 * *
6 * ACTUALLY IT ISN'T. This is a modified edition of dreadnaut that performs *
7 * tests of conformity. Instead of reporting the results of computations to *
8 * the human, it compares them to values stored in the input and reports any *
9 * differences. *
10 * It is assumed that "long int" has at least 32 bits. *
11 * In the following, # is a hex value (without 0x) that is compared to a *
12 * hash certificate of the specified value. An error message is given if *
13 * they don't match exactly. *
14 * The following no longer have their old meanings: *
15 * a # - compare the generators *
16 * b # - compare the canonical labelling and the labelled graph *
17 * o # - compare the orbits *
18 * & # - compare the partition *
19 * S # - compare the statistics *
20 * C - run tests on bits, sets, etc. *
21 * *
22 * Copyright (1984-2002) Brendan McKay. All rights reserved. *
23 * Subject to the waivers and disclaimers in nauty.h. *
24 * *
25 * CHANGE HISTORY *
26 * 1-Sep-02 - Initial write starting at dreadnaut.c *
27 * 17-Nov-03 - Change INFINITY to NAUTY_INFINITY *
28 * *
29 *****************************************************************************/
30
31 #include "naututil.h" /* which includes nauty.h, which includes stdio.h */
32 #include "nautinv.h" /* which includes nauty.h, which includes stdio.h */
33
34 #define PM(x) ((x) ? '+' : '-')
35 #define SS(n,sing,plur) (n),((n)==1?(sing):(plur))
36 #define WORKSIZE 60
37
38 #define INFILE fileptr[curfile]
39 #define OUTFILE outfile
40
41 #if !MAXN
42 DYNALLSTAT(graph,g,g_sz);
43 DYNALLSTAT(graph,canong,canong_sz);
44 DYNALLSTAT(graph,savedg,savedg_sz);
45 DYNALLSTAT(setword,workspace,workspace_sz);
46 DYNALLSTAT(int,lab,lab_sz);
47 DYNALLSTAT(int,ptn,ptn_sz);
48 DYNALLSTAT(int,orbits,orbits_sz);
49 DYNALLSTAT(int,savedlab,savedlab_sz);
50 DYNALLSTAT(permutation,perm,perm_sz);
51 DYNALLSTAT(set,active,active_sz);
52 #else
53 static graph g[MAXM*1L*MAXN];
54 static graph canong[MAXM*1L*MAXN];
55 static graph savedg[MAXM*1L*MAXN];
56 static setword workspace[MAXM*2L*WORKSIZE];
57 static int lab[MAXN];
58 static int ptn[MAXN];
59 static int orbits[MAXN];
60 static int savedlab[MAXN];
61 static permutation perm[MAXN];
62 static set active[MAXM];
63 #endif
64
65 static DEFAULTOPTIONS_GRAPH(options);
66 static statsblk stats;
67 static int curfile;
68 static FILE *fileptr[MAXIFILES];
69 static FILE *outfile;
70 static char def_ext[] = DEFEXT;
71 static boolean firstpath; /* used in usernode() */
72
73 #define U_NODE 1 /* masks for u values */
74 #define U_AUTOM 2
75 #define U_LEVEL 4
76 #define U_TCELL 8
77 #define U_REF 16
78
79 #ifndef NODEPROC
80 #define NODEPROC usernode
81 #else
82 extern void NODEPROC(graph*,int*,int*,int,int,int,int,int,int);
83 #endif
84
85 #ifndef AUTOMPROC
86 #define AUTOMPROC userautom
87 #else
88 extern void AUTOMPROC(int,permutation*,int*,int,int,int);
89 #endif
90
91 #ifndef LEVELPROC
92 #define LEVELPROC userlevel
93 #else
94 extern void LEVELPROC(int*,int*,int,int*,statsblk*,int,int,int,int,int,int);
95 #endif
96
97 #ifndef TCELLPROC
98 #define TCELLPROC NULL
99 #else
100 extern void TCELLPROC(graph*,int*,int*,int,int,set*,int*,int*,int,int,
101 int(*)(graph*,int*,int*,int,int,int,int),int,int);
102 #endif
103
104 #ifndef REFPROC
105 #define REFPROC NULL
106 #else
107 extern void REFPROC(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int);
108 #endif
109
110 #ifndef INVARPROC
111 #define INVARPROC NULL
112 #define INVARPROCNAME "none"
113 #else
114 extern void INVARPROC(graph*,int*,int*,int,int,int,permutation*,
115 int,boolean,int,int);
116 #define INVARPROCNAME "user-defined"
117 #endif
118
119
120 static struct invarrec
121 {
122 void (*entrypoint)(graph*,int*,int*,int,int,int,permutation*,
123 int,boolean,int,int);
124 char *name;
125 } invarproc[]
126 = {INVARPROC, INVARPROCNAME,
127 NULL, "none",
128 twopaths, "twopaths",
129 adjtriang, "adjtriang",
130 triples, "triples",
131 quadruples, "quadruples",
132 celltrips, "celltrips",
133 cellquads, "cellquads",
134 cellquins, "cellquins",
135 distances, "distances",
136 indsets, "indsets",
137 cliques, "cliques",
138 cellcliq, "cellcliq",
139 cellind, "cellind",
140 adjacencies, "adjacencies",
141 cellfano, "cellfano",
142 cellfano2, "cellfano2"};
143 #define NUMINVARS ((int)(sizeof(invarproc)/sizeof(struct invarrec)))
144
145 #ifdef NLMAP
146 #define GETNW(c,f) do c = getc(f); while (c==' '||c=='\t')
147 #define GETNWC(c,f) do c = getc(f); while (c==' '||c==','||c=='\t')
148 #define GETNWL(c,f) do c = getc(f); while (c==' '||c=='\n'||c=='\t')
149 #else
150 #define GETNW(c,f) do c = getc(f); while (c==' '||c=='\t'||c=='\r')
151 #define GETNWC(c,f) do c = getc(f); while (c==' '||c==','||c=='\t'||c=='\r')
152 #define GETNWL(c,f) do c = getc(f); while (c==' '||c=='\n'||c=='\t'||c=='\r')
153 #endif
154
155 static void help(FILE*, int);
156 static void userautom(int,permutation*,int*,int,int,int);
157 static void usernode(graph*,int*,int*,int,int,int,int,int,int);
158 static void userlevel(int*,int*,int,int*,statsblk*,int,int,int,int,int,int);
159
160
161 #ifdef EXTRADECLS
162 EXTRADECLS
163 #endif
164
165 static long afound;
166
167 /*****************************************************************************
168 * *
169 * gethex(f) reads a long hex integer from f, optionally preceded by '=' *
170 * and white space. -1 is returned if the attempt was unsuccessful. *
171 * Not much error checking. *
172 * *
173 *****************************************************************************/
174
175 static long
gethex(FILE * f)176 gethex(FILE *f)
177 {
178 int c;
179 long i;
180
181 GETNWL(c,f);
182 if (c != '=') ungetc((char)c,f);
183
184 if (fscanf(f,"%lx",&i) == 1) return i;
185 else return -1;
186 }
187
188 /*****************************************************************************
189 * *
190 * permhash(s,n,seed,key) is a function whose value depends only on the *
191 * permutation s, a long seed, and an integer key. It is intended to be *
192 * independent of the machine and whether permutation has 16 or 32 bits. *
193 * n is the length. *
194 * 28 bits of seed and 15 bits of key are significant. *
195 * The result is in the low 28 bits. *
196 * *
197 *****************************************************************************/
198
199 static long
permhash(permutation * s,int n,long seed,int key)200 permhash(permutation *s, int n, long seed, int key)
201 {
202 int i,j,lsh,rsh;
203 long l,res,salt,lshmask;
204 long si;
205
206 lsh = key & 0xF;
207 rsh = 28 - lsh;
208 salt = (key >> 4) & 0x7FFL;
209 res = seed & 0xFFFFFFFL;
210 lshmask = (1L << lsh) - 1;
211
212 j = 0;
213 for (i = 0; i < n; ++i)
214 {
215 si = s[i];
216 l = si & 0xFFFFL;
217 res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt)
218 & 0xFFFFFFFL;
219 l = si >> 16;
220 res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt)
221 & 0xFFFFFFFL;
222 }
223
224 return res;
225 }
226
227 /*****************************************************************************
228 * *
229 * inthash(s,n,seed,key) is a function whose value depends only on the *
230 * int array p, a long seed, and an integer key. It is intended to be *
231 * independent of the machine and whether int has 16 or 32 bits. *
232 * 64 bits is also ok provided the values are not above 2^31-1. *
233 * n is the length. *
234 * 28 bits of seed and 15 bits of key are significant. *
235 * The result is in the low 28 bits. *
236 * *
237 *****************************************************************************/
238
239 static long
inthash(int * s,int n,long seed,int key)240 inthash(int *s, int n, long seed, int key)
241 {
242 int i,j,lsh,rsh;
243 long l,res,salt,lshmask;
244 long si;
245
246 lsh = key & 0xF;
247 rsh = 28 - lsh;
248 salt = (key >> 4) & 0x7FFL;
249 res = seed & 0xFFFFFFFL;
250 lshmask = (1L << lsh) - 1;
251
252 j = 0;
253 for (i = 0; i < n; ++i)
254 {
255 si = s[i];
256 l = si & 0xFFFFL;
257 res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt)
258 & 0xFFFFFFFL;
259 l = si >> 16;
260 res = (((res << lsh) ^ ((res >> rsh) & lshmask) ^ l) + salt)
261 & 0xFFFFFFFL;
262 }
263
264 return res;
265 }
266
267 /*****************************************************************************
268 * bit_tests() Run some configuration tests *
269 *****************************************************************************/
270
271 static int
bit_tests(void)272 bit_tests(void)
273 {
274 int i,j,bad;
275 setword w;
276
277 printf("NAUTYVERSION=%s NAUTYVERSIONID=%d NAUTYREQUIRED=%d\n",
278 NAUTYVERSION,NAUTYVERSIONID,NAUTYREQUIRED);
279 printf("MAXN=%d MAXM=%d WORDSIZE=%d NAUTY_INFINITY=%d",
280 MAXN,MAXM,WORDSIZE,NAUTY_INFINITY);
281 #ifdef BIGNAUTY
282 printf(" BIGNAUTY");
283 #endif
284 #ifdef SYS_UNIX
285 printf(" SYS_UNIX");
286 #endif
287 #ifdef SYS_CRAY
288 printf(" SYS_CRAY");
289 #endif
290
291 printf("\n");
292
293
294 bad = 0;
295
296 if (SIZEOF_INT != sizeof(int))
297 {
298 printf(" ***** NOTE: sizeof problem (int) *****\n");
299 ++bad;
300 }
301 if (SIZEOF_LONG != sizeof(long))
302 {
303 printf(" ***** NOTE: sizeof problem (long) *****\n");
304 ++bad;
305 }
306 #if SIZEOF_LONGLONG > 0
307 if (SIZEOF_LONGLONG != sizeof(long long))
308 {
309 printf(" ***** NOTE: sizeof problem (long long) *****\n");
310 ++bad;
311 }
312 #endif
313
314 if (8*sizeof(setword) < WORDSIZE)
315 {
316 printf("\n ***** NOTE: WORDSIZE mismatch *****\n");
317 ++bad;
318 }
319 if (8*sizeof(setword) > WORDSIZE)
320 {
321 printf("\n WORDSIZE < 8*sizeof(setword) [This is legal.]\n");
322 }
323
324 for (i = 0; i < WORDSIZE; ++i)
325 {
326 w = ALLMASK(i);
327 if (POPCOUNT(w) != i)
328 {
329 printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i);
330 ++bad;
331 }
332 }
333
334 for (i = 0; i < WORDSIZE; ++i)
335 {
336 w = BITMASK(i);
337 if (POPCOUNT(w) != WORDSIZE-i-1)
338 {
339 printf("\n ***** POPCOUNT(BITMASK) error %d *****\n\n",i);
340 ++bad;
341 }
342 }
343
344 for (i = 0; i < WORDSIZE; ++i)
345 if (POPCOUNT(ALLMASK(i)) != i)
346 {
347 printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i);
348 ++bad;
349 }
350
351 for (i = 0; i < WORDSIZE; ++i)
352 if (FIRSTBIT(BITT[i]) != i)
353 {
354 printf("\n ***** FIRSTBIT(BITT) error %d *****\n\n",i);
355 ++bad;
356 }
357
358 w = ALLBITS;
359 for (i = 0; i < WORDSIZE; ++i)
360 {
361 TAKEBIT(j,w);
362 if (j != i)
363 {
364 printf("\n ***** TAKEBIT error %d *****\n\n",i);
365 ++bad;
366 }
367 }
368
369 for (i = 0; i < WORDSIZE; ++i)
370 if (POPCOUNT(BITT[i]) != 1)
371 {
372 printf("\n ***** POPCOUNT(BITT) error %d *****\n\n",i);
373 ++bad;
374 }
375
376 for (i = 0; i < WORDSIZE; ++i)
377 {
378 w = 0;
379 for (j = 1; j <= WORDSIZE; ++j)
380 {
381 w |= BITT[(j*97+i)%WORDSIZE];
382 if (POPCOUNT(w) != j)
383 {
384 printf("\n ***** POPCOUNT(w) error %d %d *****\n\n",i,j);
385 ++bad;
386 }
387 }
388 }
389
390 if (bad) printf("\nXXXXXXX %d errors found XXXXXXX\n",bad);
391
392 return bad;
393 }
394
395 /*****************************************************************************
396 * *
397 * This is a program which illustrates the use of nauty. *
398 * Commands are read from stdin, and may be separated by white space, *
399 * commas or not separated. Output is written to stdout. *
400 * For a short description, see the nauty User's Guide. *
401 * *
402 *****************************************************************************/
403
404 int
main(int argc,char * argv[])405 main(int argc, char *argv[])
406 {
407 int m,n,newm,newn;
408 boolean gvalid,ovalid,cvalid,pvalid,minus,prompt,doquot;
409 int i,worksize,numcells,refcode,umask,qinvar;
410 int oldorg;
411 char *s1,*s2,*invarprocname;
412 int c,d;
413 register long li;
414 set *gp;
415 double timebefore,timeafter;
416 char filename[200];
417 int sgn,sgorg,nperm;
418 int bad,multiplicity;
419 boolean options_writeautoms,options_writemarkers;
420 long zseed;
421 long need,found;
422
423 curfile = 0;
424 fileptr[curfile] = stdin;
425 prompt = FALSE;
426 outfile = stdout;
427 options_writeautoms = options_writemarkers = TRUE;
428 n = m = 1;
429 worksize = 2*WORKSIZE;
430
431 #if !MAXN
432 n = WORDSIZE;
433 DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut");
434 DYNALLOC1(int,lab,lab_sz,n,"dreadnaut");
435 DYNALLOC1(int,ptn,ptn_sz,n,"dreadnaut");
436 DYNALLOC1(setword,workspace,workspace_sz,
437 worksize,"dreadnaut");
438 DYNALLOC1(int,orbits,orbits_sz,n,"dreadnaut");
439 DYNALLOC1(permutation,perm,perm_sz,n,"dreadnaut");
440 DYNALLOC1(set,active,active_sz,m,"dreadnaut");
441 n = 1;
442 #endif
443
444 ran_init(37);
445
446 bad = 0;
447
448 umask = 0;
449 pvalid = FALSE;
450 gvalid = FALSE;
451 ovalid = FALSE;
452 cvalid = FALSE;
453 minus = FALSE;
454 labelorg = oldorg = 0;
455 multiplicity = 1;
456 options.userautomproc = userautom;
457
458 #ifdef INITIALIZE
459 INITIALIZE;
460 #endif
461
462 invarprocname = "none";
463 if (prompt)
464 {
465 #ifdef BIGNAUTY
466 fprintf(PROMPTFILE,"Dreadnaut version %s [BIG].\n",NAUTYVERSION);
467 #else
468 fprintf(PROMPTFILE,"Dreadnaut version %s.\n",NAUTYVERSION);
469 #endif
470 fprintf(PROMPTFILE,"> ");
471 }
472
473 nauty_check(WORDSIZE,1,1,NAUTYVERSIONID);
474 nautinv_check(WORDSIZE,1,1,NAUTYVERSIONID);
475 nautil_check(WORDSIZE,1,1,NAUTYVERSIONID);
476 naututil_check(WORDSIZE,1,1,NAUTYVERSIONID);
477 naugraph_check(WORDSIZE,1,1,NAUTYVERSIONID);
478
479 while (curfile >= 0)
480 if ((c = getc(INFILE)) == EOF || c == '\004')
481 {
482 fclose(INFILE);
483 --curfile;
484 if (curfile >= 0)
485 prompt = FALSE;
486 }
487 else switch (c)
488 {
489 case '\n': /* possibly issue prompt */
490 if (prompt)
491 fprintf(PROMPTFILE,"> ");
492 minus = FALSE;
493 break;
494
495 case ' ': /* do nothing */
496 case '\t':
497 #ifndef NLMAP
498 case '\r':
499 #endif
500 case '\f':
501 break;
502
503 case '-': /* remember this for next time */
504 minus = TRUE;
505 break;
506
507 case '+': /* forget - */
508 case ',':
509 case ';':
510 minus = FALSE;
511 break;
512
513 case '<': /* new input file */
514 minus = FALSE;
515 if (curfile == MAXIFILES - 1)
516 fprintf(ERRFILE,"exceeded maximum input nesting of %d\n\n",
517 MAXIFILES);
518 if (!readstring(INFILE,filename,200))
519 {
520 fprintf(ERRFILE,
521 "missing file name on '>' command : ignored\n\n");
522 break;
523 }
524 if ((fileptr[curfile+1] = fopen(filename,"r")) == NULL)
525 {
526 for (s1 = filename; *s1 != '\0'; ++s1) {}
527 for (s2 = def_ext; (*s1 = *s2) != '\0'; ++s1, ++s2) {}
528 fileptr[curfile+1] = fopen(filename,"r");
529 }
530 if (fileptr[curfile+1] != NULL)
531 {
532 ++curfile;
533 prompt = FALSE;
534 if (prompt)
535 fprintf(PROMPTFILE,"> ");
536 }
537 else
538 fprintf(ERRFILE,"can't open input file\n\n");
539 break;
540
541 case '>': /* new output file */
542 if ((d = getc(INFILE)) != '>')
543 ungetc((char)d,INFILE);
544 if (minus)
545 {
546 minus = FALSE;
547 if (outfile != stdout)
548 {
549 fclose(outfile);
550 outfile = stdout;
551 }
552 }
553 else
554 {
555 if (!readstring(INFILE,filename,200))
556 {
557 fprintf(ERRFILE,
558 "improper file name, reverting to stdout\n\n");
559 outfile = stdout;
560 break;
561 }
562 OPENOUT(outfile,filename,d=='>');
563 if (outfile == NULL)
564 {
565 fprintf(ERRFILE,
566 "can't open output file, reverting to stdout\n\n");
567 outfile = stdout;
568 }
569 }
570 break;
571
572 case '!': /* ignore rest of line */
573 do
574 c = getc(INFILE);
575 while (c != '\n' && c != EOF);
576 if (c == '\n')
577 ungetc('\n',INFILE);
578 break;
579
580 case 'n': /* read n value */
581 minus = FALSE;
582 i = getint(INFILE);
583 if (i <= 0 || (MAXN && i > MAXN)
584 || (!MAXN && i > NAUTY_INFINITY-2))
585 fprintf(ERRFILE,
586 " n can't be less than 1 or more than %d\n\n",
587 MAXN ? MAXN : NAUTY_INFINITY-2);
588 else
589 {
590 gvalid = FALSE;
591 ovalid = FALSE;
592 cvalid = FALSE;
593 pvalid = FALSE;
594 n = i;
595 m = (n + WORDSIZE - 1) / WORDSIZE;
596 #if !MAXN
597 worksize = 2 * m * WORKSIZE;
598 DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut");
599 DYNALLOC1(int,lab,lab_sz,n,"dreadnaut");
600 DYNALLOC1(int,ptn,ptn_sz,n,"dreadnaut");
601 DYNALLOC1(setword,workspace,workspace_sz,
602 worksize,"dreadnaut");
603 DYNALLOC1(int,orbits,orbits_sz,n,"dreadnaut");
604 DYNALLOC1(permutation,perm,perm_sz,n,"dreadnaut");
605 DYNALLOC1(set,active,active_sz,m,"dreadnaut");
606 #endif
607 }
608 break;
609
610 case 'g': /* read graph */
611 minus = FALSE;
612 readgraph(INFILE,g,options.digraph,prompt,FALSE,
613 options.linelength,m,n);
614 gvalid = TRUE;
615 cvalid = FALSE;
616 ovalid = FALSE;
617 break;
618
619 case 'e': /* edit graph */
620 minus = FALSE;
621 readgraph(INFILE,g,options.digraph,prompt,gvalid,
622 options.linelength,m,n);
623 gvalid = TRUE;
624 cvalid = FALSE;
625 ovalid = FALSE;
626 break;
627
628 case 'r': /* relabel graph and current partition */
629 minus = FALSE;
630 if (gvalid)
631 {
632 #if !MAXN
633 DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut");
634 #endif
635 readvperm(INFILE,perm,prompt,n,&nperm);
636 relabel(g,(pvalid ? lab : NULL),perm,canong,m,n);
637 cvalid = FALSE;
638 ovalid = FALSE;
639 }
640 else
641 fprintf(ERRFILE,"g is not defined\n\n");
642 break;
643
644 case 'R': /* form subgraph */
645 if (gvalid)
646 {
647 #if !MAXN
648 DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut");
649 #endif
650 readvperm(INFILE,perm,prompt,n,&nperm);
651 if (minus && nperm == n || !minus && nperm == 0)
652 fprintf(ERRFILE,"can't form null graph\n\n");
653 else if (minus)
654 {
655 sublabel(g,perm+nperm,n-nperm,canong,m,n);
656 n = n - nperm;
657 }
658 else
659 {
660 sublabel(g,perm,nperm,canong,m,n);
661 n = nperm;
662 }
663 cvalid = FALSE;
664 pvalid = FALSE;
665 ovalid = FALSE;
666 m = (n + WORDSIZE - 1) / WORDSIZE;
667 }
668 else
669 fprintf(ERRFILE,"g is not defined\n\n");
670 minus = FALSE;
671 break;
672
673 case '_': /* complement graph or converse digraph */
674 minus = FALSE;
675 if ((d = getc(INFILE)) != '_') ungetc((char)d,INFILE);
676
677 if (gvalid)
678 {
679 if (d == '_') converse(g,m,n);
680 else complement(g,m,n);
681 cvalid = FALSE;
682 ovalid = FALSE;
683 }
684 else
685 fprintf(ERRFILE,"g is not defined\n\n");
686 break;
687
688 case '@': /* copy canong into savedg */
689 minus = FALSE;
690 if (cvalid)
691 {
692 #if !MAXN
693 DYNALLOC2(graph,savedg,savedg_sz,n,m,"dreadnaut");
694 DYNALLOC1(int,savedlab,savedlab_sz,n,"dreadnaut");
695 #endif
696 sgn = n;
697 for (li = (long)n * (long)m; --li >= 0;)
698 savedg[li] = canong[li];
699 for (i = n; --i >= 0;)
700 savedlab[i] = lab[i];
701 sgorg = labelorg;
702 }
703 else
704 fprintf(ERRFILE,"h is not defined\n\n");
705 break;
706
707 case '#': /* compare canong to savedg */
708 if ((d = getc(INFILE)) != '#') ungetc((char)d,INFILE);
709
710 if (cvalid)
711 {
712 if (sgn > 0)
713 {
714 if (sgn != n)
715 fprintf(OUTFILE,
716 "h and h' have different sizes.\n");
717 else
718 {
719 for (li = (long)n * (long)m; --li >= 0;)
720 if (savedg[li] != canong[li]) break;
721 if (li >= 0)
722 fprintf(OUTFILE,"h and h' are different.\n");
723 else
724 {
725 fprintf(OUTFILE,
726 "h and h' are identical.\n");
727 if (d == '#')
728 putmapping(OUTFILE,savedlab,sgorg,
729 lab,labelorg,options.linelength,n);
730 }
731 }
732 }
733 else
734 fprintf(ERRFILE,"h' is not defined\n\n");
735 }
736 else
737 fprintf(ERRFILE,"h is not defined\n\n");
738 break;
739
740 case 'j': /* relabel graph randomly */
741 minus = FALSE;
742 if (gvalid)
743 {
744 #if !MAXN
745 DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut");
746 #endif
747 ranperm(perm,n);
748 relabel(g,(pvalid ? lab : NULL),perm,canong,m,n);
749 cvalid = FALSE;
750 ovalid = FALSE;
751 }
752 else
753 fprintf(ERRFILE,"g is not defined\n\n");
754 break;
755
756 case 'v': /* write vertex degrees */
757 minus = FALSE;
758 if (gvalid)
759 putdegs(OUTFILE,g,options.linelength,m,n);
760 else
761 fprintf(ERRFILE,"g is not defined\n\n");
762 break;
763
764 case '%': /* do Mathon doubling operation */
765 minus = FALSE;
766 if (gvalid)
767 {
768 #if !MAXN
769 if (2L * ((long)n + 1L) > NAUTY_INFINITY-2)
770 {
771 fprintf(ERRFILE,
772 "n can't be more than %d\n\n",NAUTY_INFINITY-2);
773 break;
774 }
775 #else
776 if (2L * ((long)n + 1L) > MAXN)
777 {
778 fprintf(ERRFILE,"n can't be more than %d\n\n",MAXN);
779 break;
780 }
781 #endif
782 newn = 2 * (n + 1);
783 newm = (newn + WORDSIZE - 1) / WORDSIZE;
784 #if !MAXN
785 DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut");
786 #endif
787
788 for (li = (long)n * (long)m; --li >= 0;)
789 canong[li] = g[li];
790
791 #if !MAXN
792 DYNALLOC2(graph,g,g_sz,newn,newm,"dreadnaut");
793 DYNALLOC1(int,lab,lab_sz,newn,"dreadnaut");
794 DYNALLOC1(int,ptn,ptn_sz,newn,"dreadnaut");
795 worksize = 2*WORKSIZE*newm;
796 DYNALLOC1(setword,workspace,workspace_sz,
797 worksize,"dreadnaut");
798 DYNALLOC1(int,orbits,orbits_sz,newn,"dreadnaut");
799 DYNALLOC1(permutation,perm,perm_sz,newn,"dreadnaut");
800 DYNALLOC1(set,active,active_sz,newm,"dreadnaut");
801 #endif
802 mathon(canong,m,n,g,newm,newn);
803 m = newm;
804 n = newn;
805 cvalid = FALSE;
806 ovalid = FALSE;
807 pvalid = FALSE;
808 }
809 else
810 fprintf(ERRFILE,"g is not defined\n\n");
811 break;
812
813 case 's': /* generate random graph */
814 minus = FALSE;
815 i = getint(INFILE);
816 if (i <= 0)
817 i = 2;
818 rangraph(g,options.digraph,i,m,n);
819 gvalid = TRUE;
820 cvalid = FALSE;
821 ovalid = FALSE;
822 break;
823
824 case 'q': /* quit */
825 if (bad == 0) printf("OK");
826 printf("\n");
827 exit(bad);
828 break;
829
830 case '"': /* copy comment to output */
831 minus = FALSE;
832 copycomment(INFILE,OUTFILE,'"');
833 break;
834
835 case 'I': /* do refinement and invariants procedure */
836 if (!pvalid)
837 unitptn(lab,ptn,&numcells,n);
838 cellstarts(ptn,0,active,m,n);
839 doref(g,lab,ptn,0,&numcells,&qinvar,perm,active,&refcode,
840 options.userrefproc ? options.userrefproc :
841 (m == 1 ? refine1 : refine),
842 options.invarproc,0,0,
843 options.invararg,options.digraph,m,n);
844 fprintf(OUTFILE," %d cell%s; code = %x",
845 SS(numcells,"","s"),refcode);
846 if (options.invarproc != NULL)
847 fprintf(OUTFILE," (%s %s)",invarprocname,
848 (qinvar == 2 ? "worked" : "failed"));
849 fprintf(OUTFILE,"\n");
850 if (numcells > 1)
851 pvalid = TRUE;
852 break;
853
854 case 'i': /* do refinement */
855 if (!pvalid)
856 unitptn(lab,ptn,&numcells,n);
857 cellstarts(ptn,0,active,m,n);
858 if (options.userrefproc)
859 (*options.userrefproc)
860 (g,lab,ptn,0,&numcells,perm,active,&refcode,m,n);
861 else if (m == 1)
862 refine1(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n);
863 else
864 refine(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n);
865 fprintf(OUTFILE," %d cell%s; code = %x\n",
866 SS(numcells,"","s"),refcode);
867 if (numcells > 1)
868 pvalid = TRUE;
869 break;
870
871 case 'x': /* execute nauty */
872 minus = FALSE;
873 ovalid = FALSE;
874 cvalid = FALSE;
875 if (!gvalid)
876 {
877 fprintf(ERRFILE,"g is not defined\n\n");
878 break;
879 }
880 if (pvalid)
881 {
882 /* fprintf(OUTFILE,"[fixing partition]\n"); */
883 options.defaultptn = FALSE;
884 }
885 else
886 options.defaultptn = TRUE;
887 options.outfile = outfile;
888
889 if (options.getcanon)
890 {
891 #if !MAXN
892 DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut");
893 #endif
894 }
895
896 firstpath = TRUE;
897 options.writeautoms = FALSE;
898 options.writemarkers = FALSE;
899 for (i = 0; i < multiplicity; ++i)
900 {
901 afound = 1;
902 nauty(g,lab,ptn,NULL,orbits,&options,&stats,workspace,
903 worksize,m,n,canong);
904 options.writeautoms = FALSE;
905 options.writemarkers = FALSE;
906 }
907 if (stats.errstatus != 0)
908 fprintf(ERRFILE,
909 "nauty returned error status %d [this can't happen]\n\n",
910 stats.errstatus);
911 else
912 {
913 if (options.getcanon) cvalid = TRUE;
914 ovalid = TRUE;
915 /* fprintf(OUTFILE,
916 "%d orbit%s",SS(stats.numorbits,"","s"));
917 if (stats.grpsize2 == 0)
918 fprintf(OUTFILE,"; grpsize=%.0f",stats.grpsize1+0.1);
919 else
920 {
921 while (stats.grpsize1 >= 10.0)
922 {
923 stats.grpsize1 /= 10.0;
924 ++stats.grpsize2;
925 }
926 fprintf(OUTFILE,"; grpsize=%12.10fe%d",
927 stats.grpsize1,stats.grpsize2);
928 }
929 fprintf(OUTFILE,"; %d gen%s",
930 SS(stats.numgenerators,"","s"));
931 fprintf(OUTFILE,"; %ld node%s",SS(stats.numnodes,"","s"));
932 if (stats.numbadleaves)
933 fprintf(OUTFILE," (%ld bad lea%s)",
934 SS(stats.numbadleaves,"f","ves"));
935 fprintf(OUTFILE,"; maxlev=%d\n", stats.maxlevel);
936 fprintf(OUTFILE,"tctotal=%ld",stats.tctotal);
937 if (options.getcanon)
938 fprintf(OUTFILE,"; canupdates=%ld",stats.canupdates);
939 fprintf(OUTFILE,"\n");
940 if (options.invarproc != NULL &&
941 options.maxinvarlevel != 0)
942 {
943 fprintf(OUTFILE,"invarproc \"%s\" succeeded %ld/%ld",
944 invarprocname,stats.invsuccesses,stats.invapplics);
945 if (stats.invarsuclevel > 0)
946 fprintf(OUTFILE," beginning at level %d.\n",
947 stats.invarsuclevel);
948 else
949 fprintf(OUTFILE,".\n");
950 }
951 */
952 }
953 break;
954
955 case 'f': /* read initial partition */
956 if (minus)
957 {
958 pvalid = FALSE;
959 minus = FALSE;
960 }
961 else
962 {
963 readptn(INFILE,lab,ptn,&numcells,prompt,n);
964 pvalid = TRUE;
965 }
966 break;
967
968 case 't': /* type graph */
969 minus = FALSE;
970 if (!gvalid)
971 fprintf(ERRFILE,"g is not defined\n\n");
972 else
973 putgraph(OUTFILE,g,options.linelength,m,n);
974 break;
975
976 case 'T': /* type graph preceded by n, $ and g commands */
977 minus = FALSE;
978 if (!gvalid)
979 fprintf(ERRFILE,"g is not defined\n\n");
980 else
981 {
982 fprintf(OUTFILE,"n=%d $=%d g\n",n,labelorg);
983 putgraph(OUTFILE,g,options.linelength,m,n);
984 fprintf(OUTFILE,"$$\n");
985 }
986 break;
987
988 case 'u': /* call user procs */
989 if (minus)
990 {
991 umask = 0;
992 minus = FALSE;
993 }
994 else
995 {
996 umask = getint(INFILE);
997 if (umask < 0)
998 umask = ~0;
999 }
1000 if (umask & U_NODE)
1001 options.usernodeproc = NODEPROC;
1002 else
1003 options.usernodeproc = NULL;
1004 if (umask & U_AUTOM)
1005 options.userautomproc = AUTOMPROC;
1006 else
1007 options.userautomproc = userautom;
1008 if (umask & U_LEVEL)
1009 options.userlevelproc = LEVELPROC;
1010 else
1011 options.userlevelproc = NULL;
1012 if (umask & U_TCELL)
1013 options.usertcellproc = TCELLPROC;
1014 else
1015 options.usertcellproc = NULL;
1016 if (umask & U_REF)
1017 options.userrefproc = REFPROC;
1018 else
1019 options.userrefproc = NULL;
1020 break;
1021
1022 case 'o': /* type orbits */
1023 minus = FALSE;
1024 need = gethex(INFILE);
1025 if (ovalid)
1026 {
1027 found = inthash(orbits,n,761L,3);
1028 if (found != need)
1029 {
1030 printf("\nERROR: need=%lx found=%lx\n",need,found);
1031 ++bad;
1032 }
1033 else
1034 printf("+"); fflush(stdout);
1035 }
1036 else
1037 fprintf(ERRFILE,"orbits are not defined\n\n");
1038 break;
1039
1040 case 'b': /* type canonlab and canong */
1041 minus = FALSE;
1042 need = gethex(INFILE);
1043 if (cvalid)
1044 {
1045 zseed = n;
1046 for (i = 0, gp = canong; i < n; ++i, gp += m)
1047 zseed = sethash(gp,n,zseed,3109);
1048 found = inthash(lab,n,165,2) ^ zseed;
1049 if (found != need)
1050 {
1051 printf("\nERROR: need=%lx found=%lx\n",need,found);
1052 ++bad;
1053 }
1054 else
1055 printf("+"); fflush(stdout);
1056 }
1057 else
1058 fprintf(ERRFILE,"automorphisms are not defined\n\n");
1059 break;
1060
1061 case 'z': /* type hashcode for canong */
1062 minus = FALSE;
1063 if (cvalid)
1064 {
1065 zseed = n;
1066 for (i = 0, gp = canong; i < n; ++i, gp += m)
1067 zseed = sethash(gp,n,zseed,321);
1068 fprintf(OUTFILE,"[%7lx",zseed);
1069
1070 for (i = 0, gp = canong; i < n; ++i, gp += m)
1071 zseed = sethash(gp,n,zseed,3109);
1072 fprintf(OUTFILE," %7lx",zseed);
1073
1074 for (i = 0, gp = canong; i < n; ++i, gp += m)
1075 zseed = sethash(gp,n,zseed,4317);
1076 fprintf(OUTFILE," %7lx]\n",zseed);
1077 }
1078 else
1079 fprintf(ERRFILE,"h is not defined\n\n");
1080 break;
1081
1082 case 'c': /* set getcanon option */
1083 options.getcanon = !minus;
1084 minus = FALSE;
1085 break;
1086
1087 case 'w': /* read size of workspace */
1088 minus = FALSE;
1089 worksize = getint(INFILE);
1090 #if !MAXN
1091 DYNALLOC1(setword,workspace,workspace_sz,worksize,"dreadnaut");
1092 #else
1093 if (worksize > 2*MAXM*WORKSIZE)
1094 {
1095 fprintf(ERRFILE,
1096 "too big - setting worksize = %d\n\n", 2*MAXM*WORKSIZE);
1097 worksize = 2*MAXM*WORKSIZE;
1098 }
1099 #endif
1100 break;
1101
1102 case 'l': /* read linelength for output */
1103 options.linelength = getint(INFILE);
1104 minus = FALSE;
1105 break;
1106
1107 case 'y': /* set tc_level field of options */
1108 options.tc_level = getint(INFILE);
1109 minus = FALSE;
1110 break;
1111
1112 case 'M': /* set multiplicity */
1113 multiplicity = getint(INFILE);
1114 if (multiplicity <= 0) multiplicity = 1;
1115 minus = FALSE;
1116 break;
1117
1118 case 'k': /* set invarlev fields of options */
1119 options.mininvarlevel = getint(INFILE);
1120 options.maxinvarlevel = getint(INFILE);
1121 minus = FALSE;
1122 break;
1123
1124 case 'K': /* set invararg field of options */
1125 options.invararg = getint(INFILE);
1126 minus = FALSE;
1127 break;
1128
1129 case '*': /* set invarproc field of options */
1130 minus = FALSE;
1131 d = getint(INFILE);
1132 if (d >= -1 && d <= NUMINVARS-2)
1133 {
1134 options.invarproc = invarproc[d+1].entrypoint;
1135 invarprocname = invarproc[d+1].name;
1136 if (options.invarproc != NULL)
1137 {
1138 options.mininvarlevel = 0;
1139 options.maxinvarlevel = 1;
1140 if (options.invarproc == indsets ||
1141 options.invarproc == cliques ||
1142 options.invarproc == cellind ||
1143 options.invarproc == cellcliq)
1144 options.invararg = 3;
1145 else
1146 options.invararg = 0;
1147 }
1148 }
1149 else
1150 fprintf(ERRFILE,"no such vertex-invariant\n\n");
1151 break;
1152
1153 case 'a': /* set writeautoms option */
1154 minus = FALSE;
1155 need = gethex(INFILE);
1156 if (ovalid)
1157 {
1158 if (afound != need)
1159 {
1160 printf("\nERROR: need=%lx found=%lx\n",need,afound);
1161 ++bad;
1162 }
1163 else
1164 printf("+"); fflush(stdout);
1165 }
1166 else
1167 fprintf(ERRFILE,"automorphisms are not defined\n\n");
1168 break;
1169
1170 case 'C': /* check bit and set operations */
1171 minus = FALSE;
1172 bit_tests();
1173 break;
1174
1175 case 'm': /* set writemarkers option */
1176 options_writemarkers = !minus;
1177 minus = FALSE;
1178 break;
1179
1180 case 'p': /* set cartesian option */
1181 options.cartesian = !minus;
1182 minus = FALSE;
1183 break;
1184
1185 case 'd': /* set digraph option */
1186 if (options.digraph && minus)
1187 gvalid = FALSE;
1188 options.digraph = !minus;
1189 minus = FALSE;
1190 break;
1191
1192 case '$': /* set label origin */
1193 if ((d = getc(INFILE)) == '$')
1194 labelorg = oldorg;
1195 else
1196 {
1197 ungetc((char)d,INFILE);
1198 oldorg = labelorg;
1199 i = getint(INFILE);
1200 if (i < 0)
1201 fprintf(ERRFILE,"labelorg must be >= 0\n\n");
1202 else
1203 labelorg = i;
1204 }
1205 break;
1206
1207 case '?': /* type options, etc. */
1208 minus = FALSE;
1209 fprintf(OUTFILE,"m=%d n=%d labelorg=%d",m,n,labelorg);
1210 if (!gvalid)
1211 fprintf(OUTFILE," g=undef");
1212 else
1213 {
1214 li = 0;
1215 for (i = 0, gp = g; i < n; ++i, gp += m)
1216 li += setsize(gp,m);
1217 if (options.digraph)
1218 fprintf(OUTFILE," arcs=%ld",li);
1219 else
1220 fprintf(OUTFILE," edges=%ld",li/2);
1221 }
1222 fprintf(OUTFILE," options=(%cc%ca%cm%cp%cd",
1223 PM(options.getcanon),PM(options_writeautoms),
1224 PM(options_writemarkers),PM(options.cartesian),
1225 PM(options.digraph));
1226 if (umask & 31)
1227 fprintf(OUTFILE," u=%d",umask&31);
1228 if (options.tc_level > 0)
1229 fprintf(OUTFILE," y=%d",options.tc_level);
1230 if (options.mininvarlevel != 0 || options.maxinvarlevel != 0)
1231 fprintf(OUTFILE," k=(%d,%d)",
1232 options.mininvarlevel,options.maxinvarlevel);
1233 if (options.invararg > 0)
1234 fprintf(OUTFILE," K=%d",options.invararg);
1235 if (multiplicity > 1) fprintf(OUTFILE," M=%d",multiplicity);
1236 fprintf(OUTFILE,")\n");
1237 fprintf(OUTFILE,"linelen=%d worksize=%d input_depth=%d",
1238 options.linelength,worksize,curfile);
1239 if (options.invarproc != NULL)
1240 fprintf(OUTFILE," invarproc=%s",invarprocname);
1241 if (pvalid)
1242 fprintf(OUTFILE,"; %d cell%s",SS(numcells,"","s"));
1243 else
1244 fprintf(OUTFILE,"; 1 cell");
1245 fprintf(OUTFILE,"\n");
1246 if (OUTFILE != PROMPTFILE)
1247 fprintf(PROMPTFILE,"m=%d n=%d depth=%d labelorg=%d\n",
1248 m,n,curfile,labelorg);
1249 break;
1250
1251 case '&': /* list the partition and possibly the quotient */
1252 need = gethex(INFILE);
1253 if ((d = getc(INFILE)) == '&')
1254 doquot = TRUE;
1255 else
1256 {
1257 ungetc((char)d,INFILE);
1258 doquot = FALSE;
1259 }
1260 minus = FALSE;
1261 if (pvalid)
1262 {
1263 for (i = 0; i < n; ++i) if (ptn[i] > n) ptn[i] = n;
1264 found = inthash(lab,n,4123,12) ^ inthash(ptn,n,4123,12);
1265 }
1266 else
1267 found = 1001;
1268
1269 if (found != need)
1270 {
1271 printf("\nERROR: need=%lx found=%lx\n",need,found);
1272 ++bad;
1273 }
1274 else
1275 printf("+"); fflush(stdout);
1276
1277 if (doquot)
1278 {
1279 /*
1280 if (!pvalid)
1281 unitptn(lab,ptn,&numcells,n);
1282 putquotient(OUTFILE,g,lab,ptn,0,options.linelength,m,n);
1283 */
1284 }
1285 break;
1286
1287 case 'h': /* type help information */
1288 case 'H':
1289 minus = FALSE;
1290 printf("a, o, & are reassigned and output is suppressed\n");
1291 printf("Use dreadnaut for other functions\n");
1292 break;
1293
1294 default: /* illegal command */
1295 fprintf(ERRFILE,"'%c' is illegal - type 'h' for help\n\n",c);
1296 flushline(INFILE);
1297 if (prompt)
1298 fprintf(PROMPTFILE,"> ");
1299 break;
1300
1301 } /* end of switch */
1302
1303 return 0;
1304 }
1305
1306 /*****************************************************************************
1307 * *
1308 * help(f,i) writes help information to file f (i = 0,1). *
1309 * *
1310 *****************************************************************************/
1311
1312 static void
help(FILE * f,int i)1313 help(FILE *f, int i)
1314 {
1315 #define H(ss) fprintf(f," %s\n",ss);
1316
1317 if (i == 0)
1318 {
1319 H("+- a : write automs v : write degrees *=# : select invariant:")
1320 H(" b : write canong w=# : set worksize")
1321 H("+- c : canonise x : run nauty -1 = user-defined")
1322 H("+- d : digraph or loops y=# : set tc_level 0 = none")
1323 H(" e : edit graph z : write hashcode 1 = twopaths")
1324 H("-f, f=#, f=[...] : set colours 2 = adjtriang(K=0,1)")
1325 H(" g : read graph $=# : set origin 3 = triples")
1326 H(" h,H : help $$ : restore origin 4 = quadruples")
1327 H(" i : refine ? : type options 5 = celltrips")
1328 H(" I : refine using invar _ : compl __ : conv 6 = cellquads")
1329 H(" j : relabel randomly % : Mathon doubling 7 = cellquins")
1330 H("k=# # : set invar levels & : type colouring 8 = distances(K)")
1331 H(" K=# : set invar param && : + quotient matrix 9 = indsets(K)")
1332 H(" l=# : set line length >ff : write to file 10 = cliques(K)")
1333 H("+- m : write markers >>ff : append to file 11 = cellcliq(K)")
1334 H(" n=# : set order -> : revert to stdout 12 = cellind(K)")
1335 H(" o : write orbits <ff : read from file 13 = adjacencies")
1336 H("+- p : set autom format @ : save canong 14 = cellfano")
1337 H(" q : quit # : canong = savedg? 15 = cellfano2")
1338 H(" r,R : relabel/subgraph ## : + write mapping")
1339 H(" s=# : random g (p=1/#) \"...\" : copy comment")
1340 H(" t,T : type graph ! : ignore line Type H for more..")
1341 }
1342
1343 if (i == 1)
1344 {
1345 H("Commands for g and e : ")
1346 H(" There is always a \"current vertex\" v, initially first vertex.")
1347 H(" # : add edge v=# ; : increment v (exit if over limit)")
1348 H(" -# : delete edge v=# #: : set v := #")
1349 H(" ? : list nbhs of v . : exit")
1350 H("Syntax for f : f=[2 3|4:9|10] (rest in extra cell at right)")
1351 H(" -f same as f=[], f=# same as f=[#]")
1352 H("Syntax for r : r 2:4 1 5; (rest appended in order)")
1353 H("Syntax for R : R 2:4 1 5; or -R 0 3 6:10;")
1354 H("Arguments for u : 1=node,2=autom,4=level,8=tcell,16=ref (add them)")
1355 H("Accurate times for easy graphs: M=# selects number of times to run.")
1356 }
1357
1358 }
1359
1360 /*****************************************************************************
1361 * *
1362 * usernode(g,lab,ptn,level,numcells,tc,code,m,n) is a simple version of the *
1363 * procedure named by options.usernodeproc. *
1364 * *
1365 *****************************************************************************/
1366
1367 static void
usernode(graph * g,int * lab,int * ptn,int level,int numcells,int tc,int code,int m,int n)1368 usernode(graph *g, int *lab, int *ptn, int level, int numcells,
1369 int tc, int code, int m, int n)
1370 {
1371 /*
1372 register int i;
1373
1374 for (i = 0; i < level; ++i)
1375 PUTC('.',OUTFILE);
1376 if (numcells == n)
1377 fprintf(OUTFILE,"(n/%d)\n",code);
1378 else if (tc < 0)
1379 fprintf(OUTFILE,"(%d/%d)\n",numcells,code);
1380 else
1381 fprintf(OUTFILE,"(%d/%d/%d)\n",numcells,code,tc);
1382 if (firstpath)
1383 putptn(OUTFILE,lab,ptn,level,options.linelength,n);
1384 if (numcells == n)
1385 firstpath = FALSE;
1386 */
1387 }
1388
1389 /*****************************************************************************
1390 * *
1391 * userautom(count,perm,orbits,numorbits,stabvertex,n) is a simple *
1392 * version of the procedure named by options.userautomproc. *
1393 * *
1394 *****************************************************************************/
1395
1396 static void
userautom(int count,permutation * perm,int * orbits,int numorbits,int stabvertex,int n)1397 userautom(int count, permutation *perm, int *orbits,
1398 int numorbits, int stabvertex, int n)
1399 {
1400 afound ^= permhash(perm,n,107651L,count);
1401 }
1402
1403 /*****************************************************************************
1404 * *
1405 * userlevel(lab,ptn,level,orbits,stats,tv,index,tcellsize,numcells,cc,n) *
1406 * is a simple version of the procedure named by options.userlevelproc. *
1407 * *
1408 *****************************************************************************/
1409
1410 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)1411 userlevel(int *lab, int *ptn, int level, int *orbits, statsblk *stats,
1412 int tv, int index, int tcellsize, int numcells, int cc, int n)
1413 {
1414 /*
1415 fprintf(OUTFILE,
1416 "**userlevelproc: level=%d tv=%d index=%d tcellsize=%d cc=%d\n",
1417 level,tv+labelorg,index,tcellsize,cc);
1418 fprintf(OUTFILE," nodes=%ld cells=%d orbits=%d generators=%d\n",
1419 stats->numnodes,numcells,stats->numorbits,stats->numgenerators);
1420 */
1421 }
1422