1 /* File commut.c.  Main program for program to compute commutator subgroups.
2    Specifically, if H is a subgroup of G, the program computes the commutator
3    group [G,H].  The formats for the command is
4 
5       commut  <options>  <group>  <subgroup>  <commutator>
6    or
7       commut  <options>  <group>  <commutator>
8 
9    where in the second case it is understood that <subgroup> equals <group>.
10 
11    The meaning of the parameters is as follows:
12 
13       <group>:      The group referred to as G above.
14 
15       <subgroup>:   The group referred to as H above.  Defaults to G.
16 
17       <commutator>: Set to the commutator group [G,H].
18 
19    The options are as follows:
20 
21       -i          The generators of <commutator> are to be written in image format.
22 
23       -overwrite: If the Cayley library file for <commutator> exists, it will
24                   be overwritten to rather than appended to.
25 
26    The return code for set or partition stabilizer computations is as follows:
27       0: computation successful,
28       1: computation terminated due to error.
29 */
30 
31 
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 #include "group.h"
39 #include "groupio.h"
40 
41 #include "ccommut.h"
42 #include "errmesg.h"
43 #include "factor.h"
44 #include "permgrp.h"
45 #include "readgrp.h"
46 #include "readper.h"
47 #include "storage.h"
48 #include "token.h"
49 #include "util.h"
50 
51 GroupOptions options;
52 
53 static void verifyOptions(void);
54 
main(int argc,char * argv[])55 int main( int argc, char *argv[])
56 {
57    char groupFileName[MAX_FILE_NAME_LENGTH] = "",
58         subgroupFileName[MAX_FILE_NAME_LENGTH] = "",
59         commutatorFileName[MAX_FILE_NAME_LENGTH] = "";
60    Unsigned i, j, optionCountPlus1;
61    char groupLibraryName[MAX_NAME_LENGTH+1] = "",
62         subgroupLibraryName[MAX_NAME_LENGTH+1] = "",
63         commutatorLibraryName[MAX_NAME_LENGTH+1] = "",
64         prefix[MAX_FILE_NAME_LENGTH+1] = "",
65         suffix[MAX_NAME_LENGTH+1] = "",
66         commutatorName[MAX_NAME_LENGTH+1] = "";
67    PermGroup *G, *H, *C;
68    BOOLEAN imageFormatFlag = FALSE, HnotequalG, quietFlag, normalClosureFlag;
69    char comment[100];
70 
71    /* If no arguments (except possibly -ncl) are given, provide help and exit. */
72    if ( argc == 1 ) {
73       printf( "\nUsage:  commut [options] group subgroup commutatorGroup\n");
74       return 0;
75    }
76    else if ( argc == 2 && strcmp(argv[1],"-ncl") == 0 ) {
77       printf( "\nUsage:  ncl [options] group subgroup normalClosure\n");
78       return 0;
79    }
80 
81    /* Check for limits option.  If present in position 1, give limits and
82       return. */
83    if ( argc > 1 && (strcmp( argv[1], "-l") == 0 || strcmp( argv[1], "-L") == 0) ) {
84       showLimits();
85       return 0;
86    }
87    /* Check for verify option.  If present in position 1, perform verify
88       (Note verifyOptions terminates program). */
89    if ( argc > 1 && (strcmp( argv[1], "-v") == 0 || strcmp( argv[1], "-V") == 0) )
90       verifyOptions();
91 
92    /* Check for exactly 2 or 3 parameters following options. */
93    for ( optionCountPlus1 = 1 ; optionCountPlus1 < argc &&
94               argv[optionCountPlus1][0] == '-' ; ++optionCountPlus1 )
95       ;
96 
97    if ( argc - optionCountPlus1 < 2 || argc - optionCountPlus1 > 3 )
98       ERROR( "main (commut)", "Exactly 2 or 3 parameters are required.")
99 
100    /* Process options. */
101    prefix[0] = '\0';
102    suffix[0] = '\0';
103    options.maxBaseSize = DEFAULT_MAX_BASE_SIZE;
104    imageFormatFlag = FALSE;
105    quietFlag = FALSE;
106    normalClosureFlag = FALSE;
107    strcpy( options.outputFileMode, "w");
108 
109    /* Process options. */
110    for ( i = 1 ; i < optionCountPlus1 ; ++i ) {
111       for ( j = 1 ; argv[i][j] != ':' && argv[i][j] != '\0' ; ++j )
112 #ifdef EBCDIC
113          argv[i][j] = ( argv[i][j] >= 'A' && argv[i][j] <= 'I' ||
114                         argv[i][j] >= 'J' && argv[i][j] <= 'R' ||
115                         argv[i][j] >= 'S' && argv[i][j] <= 'Z' ) ?
116                         (argv[i][j] + 'a' - 'A') : argv[i][j];
117 #else
118          argv[i][j] = (argv[i][j] >= 'A' && argv[i][j] <= 'Z') ?
119                       (argv[i][j] + 'a' - 'A') : argv[i][j];
120 #endif
121       errno = 0;
122       if ( strncmp( argv[i], "-p:", 3) == 0 ) {
123          strcpy( prefix, argv[i]+3);
124       }
125       else if ( strncmp( argv[i], "-t:", 3) == 0 ) {
126          strcpy( suffix, argv[i]+3);
127       }
128       else if ( strcmp( argv[i], "-i") == 0 )
129          imageFormatFlag = TRUE;
130       else if ( strncmp( argv[i], "-mb:", 4) == 0 ) {
131          errno = 0;
132          options.maxBaseSize = (Unsigned) strtol(argv[i]+4,NULL,0);
133          if ( errno )
134             ERROR( "main (cent)", "Invalid syntax for -mb option")
135       }
136       else if ( strncmp( argv[i], "-mw:", 4) == 0 ) {
137          errno = 0;
138          options.maxWordLength = (Unsigned) strtol(argv[i]+4,NULL,0);
139          if ( errno )
140             ERROR( "main (cent)", "Invalid syntax for -mw option")
141       }
142       else if ( strncmp( argv[i], "-n:", 3) == 0 )
143          if ( isValidName( argv[i]+3) )
144             strcpy( commutatorName, argv[i]+3);
145          else
146             ERROR1s( "main (commut)", "Invalid name ", commutatorName,
147                      " for commutator group.")
148       else if ( strcmp( argv[i], "-a") == 0 )
149          strcpy( options.outputFileMode, "a");
150       else if ( strcmp( argv[i], "-q") == 0 )
151          quietFlag = TRUE;
152       else if ( strcmp( argv[i], "-ncl") == 0 )
153          normalClosureFlag = TRUE;
154       else
155          ERROR1s( "main (compute subgroup)", "Invalid option ", argv[i], ".")
156    }
157 
158    /* Compute maximum degree and word length. */
159    options.maxWordLength = 200 + 5 * options.maxBaseSize;
160    options.maxDegree = MAX_INT - 2 - options.maxBaseSize;
161 
162    HnotequalG = (argc - optionCountPlus1 == 3);
163    if ( normalClosureFlag && !HnotequalG )
164       ERROR( "main (commut)", "Invalid number of arguments for normal closure")
165 
166    /* Compute names for files and libraries. */
167    parseLibraryName( argv[optionCountPlus1], prefix, suffix,
168                      groupFileName, groupLibraryName);
169    if ( HnotequalG )
170       parseLibraryName( argv[optionCountPlus1+1], prefix, suffix,
171                         subgroupFileName, subgroupLibraryName);
172    parseLibraryName( argv[optionCountPlus1+1+HnotequalG], "", "",
173                      commutatorFileName, commutatorLibraryName);
174 
175    /* Read in the groups G and H. */
176    G = readPermGroup( groupFileName, groupLibraryName, 0, "Generate");
177    if ( HnotequalG )
178       if ( normalClosureFlag )
179          H = readPermGroup( subgroupFileName, subgroupLibraryName, G->degree,
180                          "Generate");
181       else
182          H = readPermGroup( subgroupFileName, subgroupLibraryName, G->degree,
183                          "");
184    else
185       H = G;
186 
187    /* Now we set C to the commutator of [G,H] of G and H, and write out C. */
188    if ( normalClosureFlag )
189       C = normalClosure( G, H);
190    else
191       C = commutatorGroup( G, H);
192    if ( commutatorName[0] != '\0' )
193       strcpy( C->name, commutatorName);
194    else
195       strcpy( C->name, commutatorLibraryName);
196    C->printFormat = (imageFormatFlag ? imageFormat : cycleFormat);
197    if ( normalClosureFlag )
198       sprintf( comment, "The normal closure in %s of %s.", G->name, H->name);
199    else
200       sprintf( comment, "The commutator group [%s,%s].", G->name, H->name);
201    writePermGroup( commutatorFileName, commutatorLibraryName, C, comment);
202 
203    /* Write commutator group order to std output. */
204    if ( !quietFlag ) {
205       if ( normalClosureFlag )
206          printf( "\nNormal closure %s of %s in %s has order ", C->name,
207                   H->name, G->name);
208       else
209          printf( "\nCommutator group %s = [%s,%s] has order ", C->name,
210                   G->name, H->name);
211       if ( C->order->noOfFactors == 0 )
212          printf( "%d", 1);
213       else
214          for ( i = 0 ; i < C->order->noOfFactors ; ++i ) {
215             if ( i > 0 )
216                printf( " * ");
217             printf( "%u", C->order->prime[i]);
218             if ( C->order->exponent[i] > 1 )
219                printf( "^%u", C->order->exponent[i]);
220          }
221       printf( "  (random Schreier)\n");
222    }
223 
224    /* Return to caller. */
225    if ( normalClosureFlag )
226       return 0;
227    else if ( C->order->noOfFactors == 0 )
228       return 0;
229    else if ( H->order )
230       if ( factEqual( H->order, C->order) )
231          return 3;
232       else
233          return 2;
234    else
235       return 4;
236 }
237 
238 
239 /*-------------------------- verifyOptions -------------------------------*/
240 
verifyOptions(void)241 static void verifyOptions(void)
242 {
243    CompileOptions mainOpts = { DEFAULT_MAX_BASE_SIZE, MAX_NAME_LENGTH,
244                                MAX_PRIME_FACTORS,
245                                MAX_REFINEMENT_PARMS, MAX_FAMILY_PARMS,
246                                MAX_EXTRA,  XLARGE, SGND, NFLT};
247    extern void xaddsge( CompileOptions *cOpts);
248    extern void xbitman( CompileOptions *cOpts);
249    extern void xccommu( CompileOptions *cOpts);
250    extern void xcopy  ( CompileOptions *cOpts);
251    extern void xcstbor( CompileOptions *cOpts);
252    extern void xerrmes( CompileOptions *cOpts);
253    extern void xessent( CompileOptions *cOpts);
254    extern void xfactor( CompileOptions *cOpts);
255    extern void xnew   ( CompileOptions *cOpts);
256    extern void xoldcop( CompileOptions *cOpts);
257    extern void xpermgr( CompileOptions *cOpts);
258    extern void xpermut( CompileOptions *cOpts);
259    extern void xprimes( CompileOptions *cOpts);
260    extern void xrandgr( CompileOptions *cOpts);
261    extern void xrandsc( CompileOptions *cOpts);
262    extern void xreadgr( CompileOptions *cOpts);
263    extern void xstorag( CompileOptions *cOpts);
264    extern void xtoken ( CompileOptions *cOpts);
265    extern void xutil  ( CompileOptions *cOpts);
266 
267    xaddsge( &mainOpts);
268    xbitman( &mainOpts);
269    xccommu( &mainOpts);
270    xcopy  ( &mainOpts);
271    xcstbor( &mainOpts);
272    xerrmes( &mainOpts);
273    xessent( &mainOpts);
274    xfactor( &mainOpts);
275    xnew   ( &mainOpts);
276    xoldcop( &mainOpts);
277    xpermgr( &mainOpts);
278    xpermut( &mainOpts);
279    xprimes( &mainOpts);
280    xrandgr( &mainOpts);
281    xrandsc( &mainOpts);
282    xreadgr( &mainOpts);
283    xstorag( &mainOpts);
284    xutil  ( &mainOpts);
285 }
286 
287 
288 
289