1 /* File orblist.c.  Main program for orblist command, which may be used
2    to list the orbits of a permutation group of a set.  The orbits are written
3    to the standard output.  The format of the
4    command is:
5 
6       orblist <options> <permGroup>
7 
8    where the meaning of the parameters is as follows:
9 
10       <permGroup>: the permutation group whose orbits are to be computed,
11 
12    The options are as follows:
13 
14       -t:           Only the orbit lengths are listed.
15 
16       -r            The orbits are listed in randomized order.  Ignored if -l
17                     option is present.
18 
19       -gn:<str>   (Set stabilizer only).  The generators for the newly-created
20                   group created are given names <str>01, <str>02, ...  .  If
21                   omitted, the new generators are named xxxx01, xxxx02, etc.,
22                   where xxxx are the first four characters of the group name.
23 
24       -wp:<name>    Write out the ordered partition formed by the orbits.
25 
26       -wg:<name>    Write out the group, following base change.  This allows
27                     orblist to be used to change the base of a permutation
28                     group, or merely to construct a base and strong generating
29                     set (using random schreier method).
30 
31       -ws:<name>    Like -wg, except when a point list is specified, only the
32                     subgroup stabilizing that point list is written.  Note
33                     -wg and -ws options are mutually exclusive.
34 
35       -i            Used with -wg, causes generators to be written in image
36                     format.
37 
38       -f:<ptlist>   Here ptlist is a comma-separated list of points.  The
39                     orbits of the (pointwise) stabilizer of these points is
40                     found.
41 
42       -q            quite mode.  Orbit information not printed.
43 
44       -z            Remove redundant Schreier generators before group is
45                     written out.
46 
47       -s:<integer>  Seed for random number generator used in conjunction with
48                     -r option.   */
49 
50 
51 #include <stddef.h>
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56 
57 #define MAIN
58 
59 #include "group.h"
60 #include "groupio.h"
61 
62 #include "addsgen.h"
63 #include "chbase.h"
64 #include "cstborb.h"
65 #include "errmesg.h"
66 #include "factor.h"
67 #include "new.h"
68 #include "randgrp.h"
69 #include "readgrp.h"
70 #include "readpar.h"
71 #include "readpts.h"
72 #include "storage.h"
73 #include "util.h"
74 
75 static void nameGenerators(
76    PermGroup *const H,
77    char genNamePrefix[]);
78 
79 static void verifyOptions(void);
80 
81 GroupOptions options;
82 
83 
main(int argc,char * argv[])84 int main( int argc, char *argv[])
85 {
86    char libFileName[MAX_FILE_NAME_LENGTH], partnFileName[MAX_FILE_NAME_LENGTH],
87         altGroupFileName[MAX_FILE_NAME_LENGTH],
88         pointSetFileName[MAX_FILE_NAME_LENGTH];
89    char libName[MAX_NAME_LENGTH+1], partnLibName[MAX_NAME_LENGTH+1],
90         altGroupLibName[MAX_NAME_LENGTH+1], pointSetLibName[MAX_NAME_LENGTH+1];
91    char prefix[MAX_FILE_NAME_LENGTH] = "";
92    Unsigned i, j, optionCountPlus1, found, processed, pt, img, orbitCount, orbRep,
93        column, temp, cumLen, len, numOrbitsToWrite;
94    BOOLEAN lengthOnlyOption, randomOption, writePartn, writeGroup, writePtStab,
95            writeOrbit, writeMultipleOrbits, pointListOption, quietOption,
96            imageFormatFlag, printOrbits, trimStrGenSet, writePS, changeBaseOnly,
97            ptStabOnly, lengthRepOption;
98    unsigned long seed;
99    PermGroup *G;
100    Permutation *gen, *nextGen;
101    Partition *Theta;
102    PointSet *Lambda;
103    UnsignedS *completeOrbit, *startOfOrbitNo, *orbNumberOfPt, *orbOrder;
104    char comment[128], tempStr[12];
105    UnsignedS *pointList = allocIntArrayBaseSize();
106    UnsignedS *orbitRepList = allocIntArrayBaseSize();
107    char *nextPos, *currentPos;
108    UnsignedS stabLevel = 0;
109    FactoredInt factoredOrbLen;
110 
111    /* Provide usage information if no arguments (except possibly -chbase
112       or -ptstab) are given. */
113    if ( argc == 1 ) {
114       printf( "\nUsage:  orblist [options] permGroup\n");
115       return 0;
116    }
117    else if ( argc == 2 && strcmp(argv[1], "-chbase") == 0 ) {
118       printf( "\nUsage:  chbase permGroup p1,p2,...,pk newGroup\n");
119       return 0;
120    }
121    else if ( argc == 2 && strcmp(argv[1], "-ptstab") == 0 ) {
122       printf( "\nUsage:  ptstab permGroup p1,p2,...,pk stabilizerSubgroup\n");
123       return 0;
124    }
125 
126    /* Check for limits option.  If present in position 1 give limits and
127       return. */
128    if ( argc > 1 && (strcmp(argv[1], "-l") == 0 || strcmp(argv[1], "-L") == 0) ) {
129       showLimits();
130       return 0;
131    }
132 
133    /* Check for verify option.  If present, perform verify (Note verify Options
134       terminates program). */
135    if ( argc > 1 && (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "-V") == 0) )
136       verifyOptions();
137 
138    /* Check for 1 to 3 parameters following options. */
139       for ( optionCountPlus1 = 1 ; optionCountPlus1 <= argc-1 &&
140                  argv[optionCountPlus1][0] == '-' ; ++optionCountPlus1 )
141          ;
142 
143       if ( argc - optionCountPlus1 > 3 ) {
144          printf( "\n\nError: At most 3 non-option parameters are allowed.\n");
145          exit(ERROR_RETURN_CODE);
146       }
147 
148    /* Process options. */
149    options.maxBaseSize = DEFAULT_MAX_BASE_SIZE;
150    lengthOnlyOption = FALSE;
151    lengthRepOption = FALSE;
152    randomOption = FALSE;
153    writePartn = FALSE;
154    writeGroup = FALSE;
155    writePtStab = FALSE;
156    writePS = FALSE;
157    writeOrbit = FALSE;
158    writeMultipleOrbits = FALSE;
159    changeBaseOnly = FALSE;
160    ptStabOnly = FALSE;
161    pointListOption = FALSE;
162    quietOption = FALSE;
163    imageFormatFlag = FALSE;
164    options.genNamePrefix[0] = '\0';
165    seed = 47;
166    trimStrGenSet = FALSE;
167    strcpy( options.outputFileMode, "w");
168    for ( i = 1 ; i < optionCountPlus1 ; ++i ) {
169       for ( j = 1 ; argv[i][j] != ':' && argv[i][j] != '\0' ; ++j )
170 #ifdef EBCDIC
171          argv[i][j] = ( argv[i][j] >= 'A' && argv[i][j] <= 'I' ||
172                         argv[i][j] >= 'J' && argv[i][j] <= 'R' ||
173                         argv[i][j] >= 'S' && argv[i][j] <= 'Z' ) ?
174                         (argv[i][j] + 'a' - 'A') : argv[i][j];
175 #else
176          argv[i][j] = (argv[i][j] >= 'A' && argv[i][j] <= 'Z') ?
177                       (argv[i][j] + 'a' - 'A') : argv[i][j];
178 #endif
179       /* -a option */
180       if ( strcmp( argv[i], "-a") == 0 )
181          strcpy( options.outputFileMode, "a");
182       /* -chbase option */
183       else if ( strcmp(argv[i],"-chbase") == 0 )
184          changeBaseOnly = TRUE;
185       /* -gn option (not useful at present) */
186       else if ( strncmp( argv[i], "-gn:", 4) == 0 )
187          if ( strlen( argv[i]+4) <= 8 )
188             strcpy( options.genNamePrefix, argv[i]+4);
189          else
190             ERROR( "main (orblist)", "Invalid value for -gn option")
191       /* -i option */
192       else if ( strcmp( argv[i], "-i") == 0 )
193          imageFormatFlag = TRUE;
194       /* -mb option */
195       else if ( strncmp( argv[i], "-mb:", 4) == 0 ) {
196          errno = 0;
197          options.maxBaseSize = (Unsigned) strtol(argv[i]+4,NULL,0);
198          if ( errno )
199             ERROR( "main (cent)", "Invalid syntax for -mb option")
200       }
201       /* -mv option */
202       else if ( strncmp( argv[i], "-mw:", 4) == 0 ) {
203          errno = 0;
204          options.maxWordLength = (Unsigned) strtol(argv[i]+4,NULL,0);
205          if ( errno )
206             ERROR( "main (cent)", "Invalid syntax for -mw option")
207       }
208       /* -overwrite option */
209       else if ( strcmp( argv[i], "-overwrite") == 0 )
210          strcpy( options.outputFileMode, "w");
211       /* -p option */
212       else if ( strncmp( argv[i], "-p:", 3) == 0 ) {
213          strcpy( prefix, argv[i]+3);
214       }
215       /* -ps option */
216       else if ( strncmp( argv[i], "-ps:", 4) == 0 ) {
217          parseLibraryName( argv[i]+4, "", "", pointSetFileName,
218                            pointSetLibName);
219          writePS = TRUE;
220       }
221       /* -ptstab option */
222       else if ( strcmp(argv[i],"-ptstab") == 0 )
223          ptStabOnly = TRUE;
224       /* -q option */
225       else if ( strcmp( argv[i], "-q") == 0 )
226          quietOption = TRUE;
227       /* -r option */
228       else if ( strcmp( argv[i], "-r") == 0 )
229          randomOption = TRUE;
230       /* -s option */
231       else if ( strncmp(argv[i],"-s:",3) == 0 ) {
232          errno = 0;
233          seed = (unsigned long) strtol( argv[i]+3, NULL, 0);
234          if ( errno )
235             ERROR1s( "main (orblist command)", "Invalid option ", argv[i], ".")
236       }
237       /* -len option */
238       else if ( strcmp( argv[i], "-len") == 0 )
239          lengthOnlyOption = TRUE;
240       /* -lr option */
241       else if ( strcmp( argv[i], "-lr") == 0 )
242          lengthRepOption = TRUE;
243       /* -wno option */
244       else if ( strncmp( argv[i], "-wno:", 5) == 0 ) {
245          writeMultipleOrbits = TRUE;
246          if ( writeOrbit )
247             ERROR( "main (orblist command)", "-wo and -wno are incompatible.")
248          errno = 0;
249          numOrbitsToWrite = (Unsigned) strtol( argv[i]+5, NULL, 0);
250          if ( errno )
251             ERROR1s( "main (orblist command)", "Invalid option ", argv[i], ".")
252       }
253       /* -wo option */
254       else if ( strncmp( argv[i], "-wo:", 4) == 0 ) {
255          writeOrbit = TRUE;
256          if ( writeMultipleOrbits )
257             ERROR( "main (orblist command)", "-wo and -wno are incompatible.")
258          errno = 0;
259          j = 0;
260          currentPos = argv[i]+4;
261          do {
262             orbitRepList[++j] = strtol( currentPos, &nextPos, 0);
263             if ( errno )
264                ERROR( "main (orblist command)", "Invalid syntax in -wo option.")
265             currentPos = nextPos+1;
266          } while ( *nextPos == ',' && j < options.maxBaseSize );
267          orbitRepList[j+1] = 0;
268          if ( *nextPos != '\0' )
269             ERROR( "main (orblist command)", "orbitRepList invalid or too long.")
270       }
271       /* -wp option */
272       else if ( strncmp( argv[i], "-wp:", 4) == 0 ) {
273          writePartn = TRUE;
274          if ( writeGroup )
275             ERROR( "main (orblist command)", "-wg and -ws are incompatible.")
276          parseLibraryName( argv[i]+4, "", "", partnFileName, partnLibName);
277       }
278       else if ( strcmp( argv[i], "-z") == 0 )
279          trimStrGenSet = TRUE;
280       else
281             ERROR1s( "main (orblist command)", "Invalid option ", argv[i], ".")
282    }
283 
284    /* Compute maximum degree and word length. */
285    options.maxWordLength = 200 + 5 * options.maxBaseSize;
286    options.maxDegree = MAX_INT - 2 - options.maxBaseSize;
287 
288    /* -ps option requires -wo and -wno, and conversely. Check this. */
289    if ( writePS ^ (writeOrbit | writeMultipleOrbits) )
290       ERROR( "main (orblist command)",
291              "-ps option requires -wo or -wno, and conversely")
292 
293    /* If -chbase or -ptstab options has been specified, check for 3 command
294       line arguments. */
295    if ( (changeBaseOnly || ptStabOnly) && (argc - optionCountPlus1 != 3) )
296       ERROR( "main (orblist command)",
297              "3 non-option parameters are needed for chbase or ptstab");
298 
299    /* Compute name for group file. */
300    parseLibraryName( argv[optionCountPlus1], prefix, "", libFileName, libName);
301 
302    /* Process the point list, if present. */
303    if ( argc - optionCountPlus1 >= 2 ) {
304       pointListOption = TRUE;
305       errno = 0;
306       j = 0;
307       currentPos = argv[optionCountPlus1+1];
308       do {
309          pointList[++j] = strtol( currentPos, &nextPos, 0);
310          if ( errno )
311             ERROR( "main (orblist command)", "Invalid point in -f option.")
312          currentPos = nextPos+1;
313       } while ( *nextPos == ',' && j < options.maxBaseSize );
314       pointList[j+1] = 0;
315       if ( *nextPos != '\0' )
316          ERROR( "main (orblist command)", "Pointlist invalid or too long.")
317    }
318 
319    /* Process name of the point stabilizer to save, or the name under which
320       to save the group with its new base. */
321    if ( argc - optionCountPlus1 == 3 ) {
322       if ( changeBaseOnly )
323          writeGroup = TRUE;
324       else
325          writePtStab = TRUE;
326       parseLibraryName( argv[optionCountPlus1+2], "", "", altGroupFileName, altGroupLibName);
327    }
328 
329    /* Read in group. */
330    if ( pointListOption || writeGroup || writePtStab )
331       G = readPermGroup( libFileName, libName, 0, "Generate");
332    else
333       G = readPermGroup( libFileName, libName, 0, "");
334 
335    /* Change base if requested, and find level in new base of stabilizer
336       of pointList. */
337    if ( pointListOption ) {
338       changeBase( G, pointList);
339       if ( trimStrGenSet )
340          removeRedunSGens( G, 1);
341       if ( !quietOption ) {
342          printf( "\n  New base: ");
343          for ( j = 1 ; j <= G->baseSize ; ++j)
344             printf( " %u", G->base[j]);
345          printf( "\n");
346       }
347       if ( changeBaseOnly ) {
348          strcpy( G->name, altGroupLibName);
349          G->printFormat = (imageFormatFlag ? imageFormat : cycleFormat);
350          nameGenerators( G, options.genNamePrefix);
351          writePermGroup( altGroupFileName, altGroupLibName, G, NULL);
352          return 0;
353       }
354       for ( stabLevel = 1 ; stabLevel <= G->baseSize ; ++stabLevel ) {
355          for ( j = 1 ; pointList[j] != 0 && pointList[j] != G->base[stabLevel] ;
356                        ++j )
357             ;
358          if ( pointList[j] == 0 )
359             break;
360       }
361    }
362    else if ( !writeGroup && !writePtStab )
363       for ( gen = G->generator ; gen ; gen = gen->next )
364          gen->level = 0;
365 
366    /* Allocate arrays completeOrbit, startOfOrbitNo, orbNumberOfPt, and
367       orbOrder. */
368    completeOrbit = allocIntArrayDegree();
369    startOfOrbitNo = allocIntArrayDegree();
370    orbNumberOfPt = allocIntArrayDegree();
371    orbOrder = allocIntArrayDegree();
372    if ( writePartn ) {
373       Theta = allocPartition();
374       Theta->degree = 0;                      /* To be adjusted */
375       strcpy( Theta->name, partnLibName);
376       Theta->pointList = allocIntArrayDegree();
377       Theta->invPointList = allocIntArrayDegree();
378       Theta->cellNumber = allocIntArrayDegree();
379       Theta->startCell = allocIntArrayDegree();
380    }
381    if ( writePS ) {
382       Lambda = allocPointSet();
383       strcpy( Lambda->name, pointSetLibName);
384       Lambda->degree = 0;
385       Lambda->size = 0;
386       Lambda->pointList = allocIntArrayDegree();
387       Lambda->inSet = allocBooleanArrayDegree();
388       for ( j = 1 ; j <= G->degree ; ++j )
389          Lambda->inSet[j] = FALSE;
390    }
391 
392    /* Construct the orbits, one by one in order. */
393    found = processed = orbitCount = 0;
394    for ( i = 1 ; i <= G->degree ; ++i )
395       orbNumberOfPt[i] = 0;
396    for ( orbRep = 1 ; orbRep <= G->degree ; ++orbRep )
397       if ( !orbNumberOfPt[orbRep] ) {
398          completeOrbit[++found] = orbRep;
399          startOfOrbitNo[++orbitCount] = found;
400          orbNumberOfPt[orbRep] = orbitCount;
401          while ( processed < found ) {
402             pt = completeOrbit[++processed];
403             for ( gen = G->generator ; gen ; gen = gen->next )
404                if ( gen->level >= stabLevel ) {
405                   img = gen->image[pt];
406                   if ( !orbNumberOfPt[img] ) {
407                      completeOrbit[++found] = img;
408                      orbNumberOfPt[img] = orbitCount;
409                   }
410                }
411          }
412       }
413 
414    startOfOrbitNo[orbitCount+1] = G->degree+1;
415 
416    /* Write out the orbits. */
417    if ( !quietOption && (lengthOnlyOption || lengthRepOption) ) {
418       column = printf( "\n Orbit lengths for group %s", G->name);
419       if ( pointListOption ) {
420          column += printf( " (Stabilizer of");
421          for ( j = 1 ; pointList[j] != 0 ; ++j ) {
422             column += printf( " ");
423             column += printf( "%d", pointList[j]);
424          }
425          column += printf( ")");
426       }
427       column += printf( ":  ");
428       for ( i = 1 ; i <= orbitCount ; ++i ) {
429          if ( column > 66 ) {
430             printf( "\n   ");
431             column = 4;
432          }
433          if ( lengthRepOption )
434          column += printf( "%u:", completeOrbit[startOfOrbitNo[i]]);
435          column += printf( "%u ", startOfOrbitNo[i+1] -
436                                           startOfOrbitNo[i]);
437       }
438       printf( "\n");
439    }
440 
441    printOrbits = !quietOption && !lengthOnlyOption && !lengthRepOption;
442    if ( printOrbits || writePartn || writeMultipleOrbits ) {
443       if ( printOrbits )
444          printf( "\n Orbits for group %s.", G->name);
445       if ( printOrbits && pointListOption ) {
446          printf( " (Stabilizer of");
447          for ( j = 1 ; pointList[j] != 0 ; ++j ) {
448             printf( " ");
449             printf( "%d", pointList[j]);
450          }
451          printf( ")");
452       }
453       if ( printOrbits )
454          printf( "\n\n    Repr  Length  CumLen     Points\n");
455       for ( i = 1 ; i <= orbitCount ; ++i )
456          orbOrder[i] = i;
457       if ( randomOption ) {
458          initializeSeed (seed);
459          for ( i = 1 ; i <= orbitCount-1 ; ++i ) {
460             j = randInteger( i, orbitCount);
461             EXCHANGE( orbOrder[i], orbOrder[j], temp);
462          }
463       }
464       cumLen = 0;
465       for ( i = 1 ; i <= orbitCount ; ++i ) {
466          len = startOfOrbitNo[orbOrder[i]+1] - startOfOrbitNo[orbOrder[i]];
467          cumLen += len;
468          if ( printOrbits )
469             printf( "\n %6d %6d %6d       ",
470                  completeOrbit[startOfOrbitNo[orbOrder[i]]], len, cumLen);
471          column = 28;
472          for ( j = startOfOrbitNo[orbOrder[i]] ;
473                            j < startOfOrbitNo[orbOrder[i]+1] ; ++j ) {
474             if ( printOrbits && column > 71 ) {
475                printf( "\n                            ");
476                column = 28;
477             }
478             if ( printOrbits )
479                column = column + printf( "%d ", completeOrbit[j]);
480             if ( writePartn ) {
481                Theta->pointList[++Theta->degree] = completeOrbit[j];
482                Theta->invPointList[completeOrbit[j]] = Theta->degree;
483                Theta->cellNumber[completeOrbit[j]] = i;
484                if ( j == startOfOrbitNo[orbOrder[i]] )
485                   Theta->startCell[i] = Theta->degree;
486             }
487             if ( writeMultipleOrbits && i <= numOrbitsToWrite ) {
488                Lambda->pointList[++Lambda->size] = completeOrbit[j];
489                Lambda->inSet[completeOrbit[j]] = TRUE;
490             }
491          }
492       }
493    }
494    if ( printOrbits )
495       printf( "\n");
496 
497    if ( writePartn ) {
498       strcpy( comment, "Orbit partition of group ");
499       strcat( comment, G->name);
500       if ( pointListOption ) {
501          strcat( comment, ", stabilizer of");
502          for ( j = 1 ; pointList[j] != 0 ; ++j ) {
503             sprintf( tempStr, " %u", pointList[j]);;
504             strcat( comment, tempStr);
505          }
506       }
507       strcpy( Theta->name, partnLibName);
508       Theta->startCell[orbitCount+1] = Theta->degree + 1;
509       writePartition( partnFileName, partnLibName, comment, Theta);
510    }
511 
512    if ( writeMultipleOrbits ) {
513       strcpy( comment, "First ");
514       sprintf( tempStr, "%u", numOrbitsToWrite);
515       strcat( comment, tempStr);
516       strcat( comment, " orbits of group ");
517       strcat( comment, G->name);
518       if ( pointListOption ) {
519          strcat( comment, "(stabilizer of");
520          for ( j = 1 ; pointList[j] != 0 ; ++j ) {
521             sprintf( tempStr, " %u", pointList[j]);;
522             strcat( comment, tempStr);
523          strcat( comment, ")");
524          }
525       }
526       writePointSet( pointSetFileName, pointSetLibName, comment, Lambda);
527    }
528 
529    if ( writeOrbit ) {
530       strcpy( comment, "Orbit(s) in group ");
531       strcat( comment, G->name);
532       if ( pointListOption ) {
533          strcat( comment, "(stabilizer of");
534          for ( j = 1 ; pointList[j] != 0 ; ++j ) {
535             sprintf( tempStr, " %u", pointList[j]);;
536             strcat( comment, tempStr);
537          strcat( comment, ")");
538          }
539       }
540       strcat( comment, " of point(s)");
541       for ( j = 1 ; orbitRepList[j] != 0 ; ++j ) {
542          sprintf( tempStr, " %u", orbitRepList[j]);;
543          strcat( comment, tempStr);
544       }
545       for ( i = 1 ; orbitRepList[i] != 0 ; ++i )
546          if ( !Lambda->inSet[orbitRepList[i]] )
547             for ( j = startOfOrbitNo[orbNumberOfPt[orbitRepList[i]]] ;
548                   j < startOfOrbitNo[orbNumberOfPt[orbitRepList[i]]+1] ; ++j )
549                Lambda->pointList[++Lambda->size] = completeOrbit[j];
550       for ( j = 1 ; j < Lambda->size ; ++j )
551          Lambda->inSet[Lambda->pointList[j]] = TRUE;
552       writePointSet( pointSetFileName, pointSetLibName, comment, Lambda);
553    }
554 
555    if ( writeGroup ) {
556       strcpy( G->name, altGroupLibName);
557       G->printFormat = (imageFormatFlag ? imageFormat : cycleFormat);
558       nameGenerators( G, options.genNamePrefix);
559       writePermGroup( altGroupFileName, altGroupLibName, G, NULL);
560    }
561 
562    if ( writePtStab ) {
563       if ( trimStrGenSet )
564          removeRedunSGens( G, 1);
565       /* First remove generators from G having level less than stabLevel, and
566          adjust the order.  Note, after here, the group table is not valid,
567          but it is adequate for writing out (writePermGroup). */
568       for ( gen = G->generator ; gen ; gen = nextGen ) {
569          nextGen = gen->next;
570          if ( gen->level < stabLevel ) {
571             if ( gen->last )
572                gen->last->next = nextGen;
573             else
574                G->generator = nextGen;
575             if ( nextGen )
576                nextGen->last = gen->last;
577             deletePermutation( gen);
578          }
579       }
580       for ( i = 1 ; i < stabLevel ; ++i ) {
581          factoredOrbLen = factorize( G->basicOrbLen[i]);
582          factDivide( G->order, &factoredOrbLen);
583          G->basicOrbLen[i] = 1;
584       }
585 
586       /* Now write out the modified G. */
587       strcpy( comment, "Pointwise stabilizer in %s of ");
588       for ( j = 1 ; pointList[j] != 0 ; ++j ) {
589          sprintf( tempStr, " %d", pointList[j]);
590          strcat( comment, tempStr);
591       }
592       strcpy( G->name, altGroupLibName);
593       G->printFormat = (imageFormatFlag ? imageFormat : cycleFormat);
594       nameGenerators( G, options.genNamePrefix);
595       writePermGroup( altGroupFileName, altGroupLibName, G, NULL);
596    }
597 
598    /* Free pseudo-stack storage. */
599    freeIntArrayBaseSize( pointList);
600    freeIntArrayBaseSize( orbitRepList);
601 
602    /* Terminate. */
603    return 0;
604 }
605 
606 
607 /*-------------------------- nameGenerators ------------------------------*/
608 
nameGenerators(PermGroup * const H,char genNamePrefix[])609 static void nameGenerators(
610    PermGroup *const H,
611    char genNamePrefix[])
612 {
613    Unsigned i;
614    Permutation *gen;
615 
616    if ( genNamePrefix[0] == '\0' ) {
617       strncpy( genNamePrefix, H->name, 4);
618       genNamePrefix[4] = '\0';
619    }
620    for ( gen = H->generator , i = 1 ; gen ; gen = gen->next , ++i ) {
621       strcpy( gen->name, genNamePrefix);
622       sprintf( gen->name + strlen(gen->name), "%02d", i);
623    }
624 }
625 
626 
627 /*-------------------------- verifyOptions -------------------------------*/
628 
verifyOptions(void)629 static void verifyOptions(void)
630 {
631    CompileOptions mainOpts = { DEFAULT_MAX_BASE_SIZE, MAX_NAME_LENGTH,
632                                MAX_PRIME_FACTORS,
633                                MAX_REFINEMENT_PARMS, MAX_FAMILY_PARMS,
634                                MAX_EXTRA,  XLARGE, SGND, NFLT};
635    extern void xaddsge( CompileOptions *cOpts);
636    extern void xbitman( CompileOptions *cOpts);
637    extern void xcopy  ( CompileOptions *cOpts);
638    extern void xcstbor( CompileOptions *cOpts);
639    extern void xerrmes( CompileOptions *cOpts);
640    extern void xessent( CompileOptions *cOpts);
641    extern void xfactor( CompileOptions *cOpts);
642    extern void xnew   ( CompileOptions *cOpts);
643    extern void xoldcop( CompileOptions *cOpts);
644    extern void xpermgr( CompileOptions *cOpts);
645    extern void xpermut( CompileOptions *cOpts);
646    extern void xprimes( CompileOptions *cOpts);
647    extern void xrandgr( CompileOptions *cOpts);
648    extern void xrandsc( CompileOptions *cOpts);
649    extern void xreadgr( CompileOptions *cOpts);
650    extern void xreadpa( CompileOptions *cOpts);
651    extern void xreadpt( CompileOptions *cOpts);
652    extern void xstorag( CompileOptions *cOpts);
653    extern void xtoken ( CompileOptions *cOpts);
654    extern void xutil  ( CompileOptions *cOpts);
655 
656    xaddsge( &mainOpts);
657    xbitman( &mainOpts);
658    xcopy  ( &mainOpts);
659    xcstbor( &mainOpts);
660    xerrmes( &mainOpts);
661    xessent( &mainOpts);
662    xfactor( &mainOpts);
663    xnew   ( &mainOpts);
664    xoldcop( &mainOpts);
665    xpermgr( &mainOpts);
666    xpermut( &mainOpts);
667    xprimes( &mainOpts);
668    xrandgr( &mainOpts);
669    xrandsc( &mainOpts);
670    xreadgr( &mainOpts);
671    xreadpa( &mainOpts);
672    xreadpt( &mainOpts);
673    xstorag( &mainOpts);
674    xtoken ( &mainOpts);
675    xutil  ( &mainOpts);
676 }
677